0

Basic outline of situation

In wxPython, I have a wx.lib.sized_controls.SizedFrame() as a class object which holds a wx.lib.sized_controls.SizedScrolledPanel() with SetSizerProps(expand=True, proportion=9) and SetSizerType('grid', {'cols': 14, 'hgap': 1, 'vgap': 1}).

So it is a self expanding and aligning grid-sizer based GUI, with scrollbars. It works perfectly.

Current approach

Inside the GUI, I build the contents one row at a time. Every row starts with a StaticText object displaying a "rank". When I hover the text with the mouse I want a popup window to be showed. I currently create it in a loop as such:

# Define and set rank
rank = wx.StaticText(self.sp, label=cdc.get_rank(result, result[7]))
rank.Bind(wx.EVT_ENTER_WINDOW, self.on_enter_field(conf.DATABASE_NAME_1, result[7], rank, "Rank", "Rank"))
rank.Bind(wx.EVT_LEAVE_WINDOW, mm.on_mouse_leave())

This works, for when I hover the mouse over the wx.StaticText object in the GUI the self.on_enter_field() method is called and the popup window shows up correctly.

Problem

However, the problem is, when I create it in this way the self.on_enter_field() is called many times when the script is executed. For every row that is created in the GUI the method is initialized.

Needed result

What I want is that the on_enter_field() method is only initialized when the mouse hovers the wx.StaticText() field and not during GUI creation.

Failed attempts

I tried the following 2 approached, both failed because when I tried it in these ways the method wasn't initialized at all:

Failed attempt 1 (with functools)

import functools

# Define and set rank
rank = wx.StaticText(self.sp, label=cdc.get_rank(result, result[7]))
rank.Bind(wx.EVT_ENTER_WINDOW, functools.partial(self.on_enter_field, coin_id=result[7], field=rank, field_name="Rank", category="Rank"))
rank.Bind(wx.EVT_LEAVE_WINDOW, self.on_mouse_leave)

Failed attempt 2 (with lambda function)

# Define and set rank
rank = wx.StaticText(self.sp, label=cdc.get_rank(result, result[7]))
rank.Bind(wx.EVT_ENTER_WINDOW, lambda event, field=rank: self.on_enter_field(event, result[7], field, "Rank", "Rank"))
rank.Bind(wx.EVT_LEAVE_WINDOW, self.on_mouse_leave)

How can I make this work?

3
  • Do not use parentheses in the Bind method… use rank.Bind(event, method), not rank.Bind(event, method()) Commented Mar 26, 2024 at 3:08
  • But how can I then pass variables to the method? Commented Mar 26, 2024 at 14:17
  • @Montmons You clearly already understand instance variables because you are using self.sp. If you declare the variable as self.whatever, you can access them in the function, without specifically passing them. Or use lambda as in one of your attempts. Commented Mar 26, 2024 at 18:43

1 Answer 1

0

You can try to "Bind" the "Enter Window" and "Leave Window" events after the full initialisation of your frame and controls, when everything is shown.

Something like the following:

frame = MyFrame(......)
frame.Show()
frame.DoBindEvents()
......
Sign up to request clarification or add additional context in comments.

3 Comments

AttributeError: 'GUISizedFrame' object has no attribute 'DoBindEvents'. The GUISizedFrame is a wx.lib.sized_controls.SizedFrame() object.
@Montmons, you need to use Bind. He just use DoBindEvents() to show you that all events should be use/bound at the very end of initialization. Otherwise what you are seeing will happen. You can't predict where the mouse is during the program start and whether the user will type some keys.
Or any other event will happen for that matter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.