javanewbie javanewbie - 1 month ago 9
Python Question

wxPython: 2nd and 3rd Panels not showing/bugging

My program has 3 panels that I switch between by hiding 2 and showing 1. However, only Panel no. 1 seems to work, because when I switch to the 2nd or 3rd, the frame is grey besides a little white box in the upper left corner. What is causing this? Any help would be appreciated. (Code supplied below)

Screenshots:

https://i.stack.imgur.com/3A6BN.png - 1st Panel

https://i.stack.imgur.com/kiGPC.png - 2nd Panel

https://i.stack.imgur.com/dUUyZ.png - 3rd Panel

Code:

#!/usr/bin/python

import wx
import webbrowser
from wx.lib import sized_controls
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
import sys

employees = [('jessica alba', 'pomona', '1981'), ('sigourney weaver', 'new york', '1949'),
('angelina jolie', 'los angeles', '1975'), ('natalie portman', 'jerusalem', '1981'),
('rachel weiss', 'london', '1971'), ('scarlett johansson', 'new york', '1984'), ('jessica alba', 'pomona', '1981'), ('sigourney weaver', 'new york', '1949'),
('angelina jolie', 'los angeles', '1975'), ('natalie portman', 'jerusalem', '1981'),
('rachel weiss', 'london', '1971'), ('scarlett johansson', 'new york', '1984')]

ID_GMAIL = wx.NewId()
ID_OUTLOOK = wx.NewId()

#######################################################################################################################


class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, pos=(120, 55), size=(400, 240), style=wx.LC_REPORT)
ListCtrlAutoWidthMixin.__init__(self)


class CustomDialog(sized_controls.SizedDialog):
def __init__(self, *args, **kwargs):
super(CustomDialog, self).__init__(*args, **kwargs)
pane = self.GetContentsPane()

static_text = wx.StaticText(pane, label='Choose Your Platform', style=wx.ALIGN_CENTER)
static_text.SetSizerProps(border=('all', 0), expand=True)

pane_btns = sized_controls.SizedPanel(pane)
pane_btns.SetSizerType('horizontal')
pane_btns.SetSizerProps(align='center')

button_ok = wx.Button(pane_btns, ID_GMAIL, label='Gmail')
button_ok.Bind(wx.EVT_BUTTON, self.on_button)

button_ok = wx.Button(pane_btns, ID_OUTLOOK, label='Outlook')
button_ok.Bind(wx.EVT_BUTTON, self.on_button)

self.Fit()
self.Centre()

def on_button(self, event):
if self.IsModal():
self.EndModal(event.EventObject.Id)
else:
self.Close()

#######################################################################################################################

class GUI(wx.Frame):
def __init__(self, *args):
super(GUI, self).__init__(*args,
style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)

self.InitUI()

def InitUI(self):
self.CreateStatusBar()
self.menubar = wx.MenuBar()
self.menu = wx.Menu()

self.add_entry = wx.MenuItem(self.menu, 3, '&Add Entry/View List\tShift+A', 'Add Employee to List/View List')
self.birthday_t = wx.MenuItem(self.menu, 1, '&Birthdays: Today\tShift+T', 'View Current Birthdays')
self.birthday_s = wx.MenuItem(self.menu, 2, '&Birthdays: In 7 Days\tShift+S', 'View Birthdays in 7 Days')
self.quit = wx.MenuItem(self.menu, wx.ID_EXIT, '&Quit\tESC', 'Quit application')

self.menu.AppendItem(self.add_entry)
self.menu.AppendItem(self.birthday_t)
self.menu.AppendItem(self.birthday_s)
self.menu.AppendSeparator()
self.menu.AppendItem(self.quit)

self.birthday_t.Enable(False)

self.menubar.Append(self.menu, '&View')

self.SetMenuBar(self.menubar)

#######################################################################################################################

self.panel_one = wx.Panel(self)
self.panel_two = wx.Panel(self)
self.panel_three = wx.Panel(self)

self.panel_one.Show()
self.panel_two.Hide()
self.panel_three.Hide()

vbox = wx.BoxSizer(wx.VERTICAL)

vbox.Add(self.panel_one, 1, wx.EXPAND)
vbox.Add(self.panel_two, 1, wx.EXPAND)
vbox.Add(self.panel_three, 1, wx.EXPAND)
self.SetSizer(vbox)

p1vbox = wx.BoxSizer(wx.HORIZONTAL)
p2vbox = wx.BoxSizer(wx.HORIZONTAL)
p3vbox = wx.BoxSizer(wx.HORIZONTAL)

self.panel_one.SetSizer(p1vbox)
self.panel_two.SetSizer(p2vbox)
self.panel_three.SetSizer(p3vbox)

#######################################################################################################################

self.email_button1 = wx.Button(self.panel_one, id=3, label='Send an Email', size=(100, 30))
self.email_button2 = wx.Button(self.panel_two, id=3, label='Send an Email', size=(100, 30))

p1vbox.AddStretchSpacer()
p1vbox.Add(self.email_button1, flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM | wx.ALL, border=17)
p1vbox.AddStretchSpacer()

p2vbox.AddStretchSpacer()
p2vbox.Add(self.email_button2, flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM | wx.ALL, border=17)
p2vbox.AddStretchSpacer()

#######################################################################################################################

self.list = AutoWidthListCtrl(self.panel_one)
self.list.InsertColumn(0, 'Name', width=140)
self.list.InsertColumn(1, 'E-mail', width=130)
self.list.InsertColumn(2, 'Birthday', width=90)

for i in employees:
index = self.list.InsertStringItem(sys.maxint, i[0])
self.list.SetStringItem(index, 1, i[1])
self.list.SetStringItem(index, 2, i[2])

#######################################################################################################################

self.birthday_text_t = wx.StaticText(self.panel_one, label='BIRTHDAYS: TODAY', pos=(210, 15))
self.birthday_text_s = wx.StaticText(self.panel_two, label='BIRTHDAYS: IN 7 DAYS', pos=(180, 15))
self.add_entry_text_a = wx.StaticText(self.panel_three, label='ADD EMPLOYEE/LIST OF BIRTHDAYS', pos=(180, 15))
self.grats = wx.StaticText(self.panel_one, label='GIVE YOUR CONGRATULATIONS', pos=(230, 310))

birthday_text_t_font = wx.Font(18, wx.TELETYPE, wx.NORMAL, wx.BOLD)
self.birthday_text_t.SetFont(birthday_text_t_font)

birthday_text_s_font = wx.Font(13, wx.MODERN, wx.NORMAL, wx.BOLD)
self.birthday_text_s.SetFont(birthday_text_s_font)

grats_font = wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD)
self.grats.SetFont(grats_font)

self.Bind(wx.EVT_MENU, self.onQuit, self.quit)
self.Bind(wx.EVT_KEY_DOWN, self.onESCQuit, self.quit)

self.Bind(wx.EVT_MENU, self.onPanelSwap, self.birthday_t)
self.Bind(wx.EVT_KEY_DOWN, self.onPanelSwap_t, self.birthday_t)

self.Bind(wx.EVT_MENU, self.onPanelSwap, self.birthday_s)
self.Bind(wx.EVT_KEY_DOWN, self.onPanelSwap_s, self.birthday_s)

self.Bind(wx.EVT_MENU, self.onPanelSwap, self.add_entry)
self.Bind(wx.EVT_KEY_DOWN, self.onPanelSwap_a, self.add_entry)

self.email_button1.Bind(wx.EVT_BUTTON, self.onClick)
self.email_button2.Bind(wx.EVT_BUTTON, self.onClick)

#######################################################################################################################

self.SetSize((650, 450))

self.SetTitle('Prototype')

self.Centre()

self.Show(True)

#######################################################################################################################

def onQuit(self, event):
dial = wx.MessageDialog(None, 'Are you sure to quit?', 'Question', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
dial = dial.ShowModal()

if dial == wx.ID_YES:
self.Close()

def onESCQuit(self, event):

if event.GetKey() == wx.WXK_ESCAPE:
dial = wx.MessageDialog(None, 'Are you sure to quit?', 'Question',
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)

if dial.ShowModal() == wx.ID_YES:
self.Close()

#######################################################################################################################

def onPanelSwap(self, event):
event_id = event.GetId()
if self.panel_one.IsShown() and event_id == 3:
self.panel_one.Hide()
self.panel_two.Hide()
self.panel_three.Show()

self.birthday_t.Enable(True)
self.birthday_s.Enable(True)
self.add_entry.Enable(False)

elif self.panel_one.IsShown() and event_id == 2:
self.panel_one.Hide()
self.panel_two.Show()
self.panel_three.Hide()

self.birthday_t.Enable(True)
self.birthday_s.Enable(False)
self.add_entry.Enable(True)

elif self.panel_two.IsShown() and event_id == 3:
self.panel_one.Hide()
self.panel_two.Hide()
self.panel_three.Show()

self.birthday_t.Enable(True)
self.birthday_s.Enable(True)
self.add_entry.Enable(False)

elif self.panel_two.IsShown() and event_id == 1:
self.panel_one.Show()
self.panel_two.Hide()
self.panel_three.Hide()

self.birthday_t.Enable(False)
self.birthday_s.Enable(True)
self.add_entry.Enable(True)

elif self.panel_three.IsShown() and event_id == 2:
self.panel_one.Hide()
self.panel_two.Show()
self.panel_three.Hide()

self.birthday_t.Enable(True)
self.birthday_s.Enable(False)
self.add_entry.Enable(True)

elif self.panel_three.IsShown() and event_id == 1:
self.panel_one.Show()
self.panel_two.Hide()
self.panel_three.Hide()

self.birthday_t.Enable(False)
self.birthday_s.Enable(True)
self.add_entry.Enable(True)

event.Skip()

#######################################################################################################################

def onPanelSwap_t(self, event):
if event.GetKey == 'shift+c':
self.panel_one.Show()
self.panel_two.Hide()
self.panel_three.Hide()

self.birthday_t.Enable(False)
self.birthday_s.Enable(True)
self.add_entry.Enable(True)

event.Skip()

def onPanelSwap_s(self, event):
if event.GetKey == 'shift+s':
self.panel_one.Hide()
self.panel_two.Show()
self.panel_three.Hide()

self.birthday_t.Enable(True)
self.birthday_s.Enable(False)
self.add_entry.Enable(True)

event.Skip()

def onPanelSwap_a(self, event):
if event.GetKey == 'shift+a':
self.panel_one.Hide()
self.panel_two.Hide()
self.panel_three.Show()

self.birthday_t.Enable(True)
self.birthday_s.Enable(True)
self.add_entry.Enable(False)

event.Skip()

#######################################################################################################################

def onClick(self, event):
dlg = CustomDialog(None, title='E-mail Your Colleague')
result = dlg.ShowModal()
if result == ID_GMAIL:
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
webbrowser.get(chrome_path).open('https://mail.google.com/mail')
elif result == ID_OUTLOOK:
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
webbrowser.get(chrome_path).open('https://outlook.live.com')
dlg.Destroy()

#######################################################################################################################

def main():
app = wx.App()
GUI(None)
app.MainLoop()


if __name__ == '__main__':
main()

Answer

As I know BoxSizer puts panels in separated cells and it use panels sizes to calculate cells sizes. Try to use Show() for all panels at start and you see all panels at the same time - one below another.

When you hide first panel then BoxSizer doesn't recalulate cells sizes and it still display first cell but with hidden panel so you don't see other panels. You can use self.Layout() to force all window to recalculate sizes.

def onPanelSwap(self, event):

    ...

    self.Layout()

    event.Skip()

BTW: you could use wx.Notebook which was created to display many panels - Example