'transient popup with slider wrong value when mouse is over parent panel using wxPython
- OS: Linux (Fedora 35)
- Python: 3.10.4
- wxPython: 4.1.1 (gtk3, released 2020-11-21)
- wxWidgets: 3.1.5 (released 2021-04-14)
Using wxPython, I'm trying to have a PopupTransientWindow show a slider, however I noticed that if the mouse is over the parent panel, then the slider is always set to it's maximum value. The slider only tracks the mouse when it's over the slider itself or over the titlebar or above the parent window - anywhere else, the slider is pegged at either the minimum or maximum. This example illustrates the issue (click on the button to popup the window, start sliding the slider and drag over the parent panel to see).
I'm wondering if this is a bug in wxPython, wxWidgets or something I'm doing wrong. For example, do I have the parent relationship between the slider and the panels correct? Do I need to bind some other mouse event to have the slider get the correct position of the mouse when it's not over the slider itself?
See how the slider jumps to the maximum value when the mouse goes over the parent panel but not when it's outside the main window frame:

import wx
class PopupWindow(wx.PopupTransientWindow):
def __init__(self, parent):
super().__init__(parent)
self.panel = wx.Panel(self)
self.slider = wx.Slider(
self.panel, wx.ID_ANY,
value=100, minValue=30, maxValue=300,
size=wx.Size(300, -1))
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.slider, flag=wx.EXPAND)
self.panel.SetSizer(vbox)
vbox.Fit(self.panel)
vbox.Fit(self)
self.Bind(wx.EVT_SLIDER, self.on_slider_change, self.slider)
def on_slider_change(self, evt):
print(evt.GetInt())
class MainWindow(wx.Frame):
def __init__(self):
initial_size = wx.Size(width=480, height=480)
super().__init__(None, wx.ID_ANY, title='Test', size=initial_size)
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, wx.ID_ANY, 'Popup Menu')
self.Bind(wx.EVT_BUTTON, self.on_button, self.button)
def on_button(self, evt):
popup_window = PopupWindow(self.button)
pos = self.button.ClientToScreen((0, 0))
sz = (-1, self.button.GetSize().GetHeight())
popup_window.Position(pos, sz)
popup_window.Popup()
if __name__ == '__main__':
app = wx.App()
win = MainWindow()
win.Show()
app.MainLoop()
Solution 1:[1]
Both wx.EVT_SLIDER and the subsequent evt.GetInt() are a bit generic.
To be much more specific use:wx.EVT_SCROLL - nailing down exactly the event you are interested in
andself.slider.GetValue() - again very specific.
With that said, on Linux wx 4.1.1 your code behaves itself, so I can only assume that you are using Windows.
Edit:
There appears to be an issue with the transient popup.
Because you have locked onto the slider with the mouse and not released, as the mouse leaves the window, the slider leaps to the maximum or minimum value. Given that you've made the window Fit this becomes obvious, where normally you might not notice.
The only thing I can suggest, is make it a wx.PopupWindow rather than a wx.PopupTransientWindow.
A wx.PopupWindow appears to behave as you would expect.
Although, I suspect that the erroneous behaviour is something you wouldn't expect to come across in normal use. You tend to release the mouse button on the slider, not drag it all over the screen.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
