0

One post right before mine, I found some Code I would like to use. There is an ComboPopup which has checkboxes in it. If one of These checkboxes is activated, I want to pass the selected text back to my class (i.e. MyForm). There is an StaticText called self.text. I want to Change the Label with the choosen Text of the ComboPopup.

I tried it with:

    test = MyForm()
    MyForm.OnUpdate(test,item.GetText())

as I thought that self.text is parent from MyForm(). But that doesn't work. No errors, but also no changes of the text.

What is self in this case? Is there a good way to find out what self is ? Like print the Name or anything :-)

My Code:

import wx
import wx.stc
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin

class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):

    def __init__(self, parent):
        wx.ListCtrl.__init__(self, parent, wx.ID_ANY, style=wx.LC_REPORT | 
                wx.SUNKEN_BORDER)
        CheckListCtrlMixin.__init__(self)
        ListCtrlAutoWidthMixin.__init__(self)
        self.SetSize(-1, -1, -1, 50)

    def OnCheckItem(self, index, flag):
        item = self.GetItem(index)
        if flag:
            what = "checked"
        else:
            what = "unchecked"
        print(f'{item.GetText()} - {what}')

        test = MyForm()
        MyForm.OnUpdate(test,item.GetText())


class ListViewComboPopup(wx.ComboPopup):

    def __init__(self):
        wx.ComboPopup.__init__(self)
        self.lc = None
    def AddItem(self, txt):
        self.lc.InsertItem(0, txt)
    def Init(self):
        self.value = -1
        self.curitem = -1
    def Create(self, parent):
        self.lc = CheckListCtrl(parent)
        self.lc.InsertColumn(0, '', width=90)
        return True
    def GetControl(self):
        return self.lc
    def OnPopup(self):
        wx.ComboPopup.OnPopup(self)
    def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
        return wx.ComboPopup.GetAdjustedSize(
            self, minWidth, 110, maxHeight)

class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title="Popup Menu")
        self.panel = wx.Panel(self)

        vsizer = wx.BoxSizer(wx.VERTICAL)

        comboCtrl = wx.ComboCtrl(self.panel, wx.ID_ANY, "Select Text")    
        popupCtrl = ListViewComboPopup()
        comboCtrl.SetPopupControl(popupCtrl)

        popupCtrl.AddItem("Text One")

        self.txt = wx.StaticText(self.panel,-1,style = wx.ALIGN_LEFT)
        self.txt.SetLabel("Startup Text")

        vsizer.Add(comboCtrl,1,wx.EXPAND)
        vsizer.Add(self.txt,1,wx.EXPAND)

        self.panel.SetSizer(vsizer)

    def OnUpdate(self, txt):
        self.txt.SetLabel(txt) 

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()
K-Doe
  • 509
  • 8
  • 29
mk1337
  • 105
  • 10

2 Answers2

2

Your wx.Frame subclass instance does not have a parent. You explicitly create it without one:

wx.Frame.__init__(self, None, title="Popup Menu")

You create an instance of MyForm in your __name__ == '__main__' block:

frame = MyForm().Show()
# Note: your name 'frame' holds the return value of the method Show(), i.e. a boolean
# This probably should rather read:
# frame = MyForm()
# frame.Show()

This is the MyForm instance you show in your app.
What you do here:

test = MyForm()

is creating a new instance of MyFrame (that has nothing to do with the one your app shows). You then call onUpdate on that new instance of your MyForm class

MyForm.OnUpdate(test,item.GetText())

Since you never Show() that new instance, you can't see the effect of your operation. However, you probably don't want/need that new instance anyway. You need your instance from the main block.

There is a parent argument on the CheckListCtrl initializer. This might contain a chain of objects which you probably can ascend until you reach your MyForm instance. I can't tell for sure, since it is not visible where and how this is called in the ListViewComboPopup:

def Create(self, parent):
    self.lc = CheckListCtrl(parent)

Do a print(self.Parent) in OnCheckItem to see what it contains and then add another .Parent to self.Parent until you hopefully end up on a <__main__.MyForm instance [...]>. This is where you want to call the onUpdate Method. That should look similar to this:

self.Parent.Parent.Parent.OnUpdate(item.GetText())
# the number of '.Parent' my vary, based on where in the chain you find your MyForm instance

Edit
As per the OP's comment, the parent attribute on wx objects is spelled with a capital P. The respective code snippets have been updated accordingly.

shmee
  • 4,721
  • 2
  • 18
  • 27
  • `self.Parent.Parent.Parent.OnUpdate(item.GetText())`(upper case P at Parent) did the trick! Thanks for the answer! Would you mind to Review my Code and Show where i can do better? I get your Explanation but i really want to get behind making my Code better. – mk1337 Mar 11 '19 at 11:08
  • 1
    Ah .. uppercase attribute names. Ok, that was not obvious from reading the docs. Good you found that! Code reviews are better suited over at [CodeReview](https://codereview.stackexchange.com/) and I'm not really familiar with `wx`. Your code looks quite OK, honestly, except for that `frame = MyForm().Show()` I mentioned. It's a bit strange to see old-style calls to parent class initializers, but the `wx` docs do that all over the place, so it might be related to that package ... – shmee Mar 11 '19 at 11:22
  • I will take a look on CodeReview! Many thanks. Also i will Change `frame = MyForm().Show()`. Have a nice day. – mk1337 Mar 11 '19 at 11:28
0

I don't know what wx library does but there is a way to check where .text is.

You want vars() mixed with pprint():

from pprint import pprint
pprint(vars(your_object))

pprint(your_object) # this is OK too

Suggestion 2

type(x).__name__

This gets you the class name of an instance. You could insert this line before self.text. And give self as argument instead of x.

Original: Link

Community
  • 1
  • 1
Inyoung Kim 김인영
  • 1,434
  • 1
  • 17
  • 38
  • Thanks for your answer. WX is a GUI Toolkit. And your Code just gives me an empty dict. And you fourth line gives me this `))` – mk1337 Mar 11 '19 at 09:35