Pregunta

I am working on my first wxpython project and I stumbled over a problem, that I can not solve. Basically I have a panel with a combo box and a status bar embedded in the frame. When I select an item in the combo box I want the selected item to be displayed in the status bar. That works just fine. But what I want is that when the frame pops up, also the initial selection in the combo box is already displayed in the status bar. The latter does not happen and I don't understand why. Because my app is quite complicated I want to solve this by using the pubsub.

I made a minimal working example which demonstrates what is the issue. Notice that when the frame is opened, the status bar is empty, but it should show the initial value which is in the combo box. Also, I don't know why the current item in the combo box is highlighted. Any ideas ?

By the way: I am new in python programming, so I would also appreciate some comments on my code, if something should or could be written in a more pythonic manner.

OK, thanks in advance for your help. Finally, here is the code (I'm using the wxpython 3.0):

import wx
from wx.lib.pubsub import pub

class CtrlPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, style = wx.SUNKEN_BORDER)

        self.lstCombo = wx.ComboBox(self, -1)
        self.lstCombo.Bind(wx.EVT_COMBOBOX, self.onSelect)
        self.get_data()

    def get_data(self):
        self.lst = range(1,10)
        self.lst = [str(x) for x in self.lst]
        self.lstCombo.Clear()
        self.lstCombo.AppendItems(self.lst)
        self.lstCombo.SetValue(self.lst[2])
        pub.sendMessage('F.Change', fobj=self.lstCombo.GetValue())

    def onSelect(self, event):
        pub.sendMessage('F.Change', fobj=self.lstCombo.GetValue())

class MainFrame(wx.Frame):
    """ The main frame of the application
    """
    def __init__(self, parent, title):

        wx.Frame.__init__(self, parent, title=title)

        self.ctrl_panel = CtrlPanel(self)
        self.statusbar = self.CreateStatusBar()

        pub.subscribe(self.change_StatusBarText, 'F.Change')

    def change_StatusBarText(self, fobj):
        self.SetStatusText(fobj)

def main():
    app = wx.App(redirect=False)
    frame = MainFrame(None, "Test")
    frame.Centre()
    frame.Show(True)
    app.MainLoop()

if __name__ == '__main__':
    main()
¿Fue útil?

Solución

The reason the statusbar doesn't show the initial selection is down to the order of your message sending/subscribing. You are creating an instance of CtrlPanel that is sending a pubsub message at the end of its init and then subscribing to that message afterwards. You need to be subscribbed to the message before it is sent, move the creation of the CtrlPanel to after the pubsub subcribe.

The current item in the combo box is highlighted because it is the only ctrl so it has focus.

Heres code with modified ordering of pubsub subscribe.

import wx
from wx.lib.pubsub import pub


class CtrlPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)

        self.lstCombo = wx.ComboBox(self, -1)
        self.lstCombo.Bind(wx.EVT_COMBOBOX, self.onSelect)
        self.get_data()

    def get_data(self):
        self.lst = range(1, 10)
        self.lst = [str(x) for x in self.lst]
        self.lstCombo.Clear()
        self.lstCombo.AppendItems(self.lst)
        self.lstCombo.SetValue(self.lst[2])
        pub.sendMessage('F.Change', fobj=self.lstCombo.GetValue())

    def onSelect(self, event):
        pub.sendMessage('F.Change', fobj=self.lstCombo.GetValue())


class MainFrame(wx.Frame):
    """ The main frame of the application
    """
    def __init__(self, parent, title):

        wx.Frame.__init__(self, parent, title=title)

        self.statusbar = self.CreateStatusBar()
        pub.subscribe(self.change_StatusBarText, 'F.Change')
        self.ctrl_panel = CtrlPanel(self)

    def change_StatusBarText(self, fobj):
        self.SetStatusText(fobj)


def main():
    app = wx.App(redirect=False)
    frame = MainFrame(None, "Test")
    frame.Centre()
    frame.Show(True)
    app.MainLoop()

if __name__ == '__main__':
    main()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top