I am cross posting from stack overflow as I got zero responses there
Creating a slider in a wxPython sized panel incorrectly displays the labels as shown here:
The following is the smallest program I could write to demonstrate the problem.
from typing import cast
from wx import App
from wx import DEFAULT_FRAME_STYLE
from wx import FRAME_FLOAT_ON_PARENT
from wx import ID_ANY
from wx import SL_AUTOTICKS
from wx import SL_HORIZONTAL
from wx import SL_LABELS
from wx import Slider
from wx.lib.sized_controls import SizedFrame
from wx.lib.sized_controls import SizedPanel
WINDOW_WIDTH: int = 400
WINDOW_HEIGHT: int = 200
class SliderBugApp(App):
def __init__(self):
super().__init__()
self._frameTop: SizedFrame = cast(SizedFrame, None)
def OnInit(self) -> bool:
title: str = 'Demo Buggy Slider'
frameStyle: int = DEFAULT_FRAME_STYLE | FRAME_FLOAT_ON_PARENT
self._frameTop = SizedFrame(parent=None, id=ID_ANY, size=(WINDOW_WIDTH, WINDOW_HEIGHT), style=frameStyle, title=title)
sizedPanel: SizedPanel = self._frameTop.GetContentsPane()
slideStyle: int = SL_HORIZONTAL | SL_AUTOTICKS | SL_LABELS
Slider(sizedPanel, id=ID_ANY, value=100, minValue=25, maxValue=100, style=slideStyle)
self._frameTop.Show(True)
return True
testApp = SliderBugApp()
testApp.MainLoop()
The labels look OK when I run your code using wxPython 4.2.1 + Python 3.10.12 + Linux Mint 21.3
Good catch.
I should have said that I am running this code on an Apple M1 Pro, macOS Sonoma 14.4.1
Python 3.11.5, wxPython 4.2.1
I get the same result as you on my 2019 Intel MacBook Pro using Sonoma 14.4.1, Python 3.11.9, wxPython 4.2.1.
Hmm. Wonder how to proceed
I created a simple app that has a slider, but no sized controls:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 1.1.0a2 on Thu May 2 20:15:10 2024
#
import wx
# begin wxGlade: dependencies
# end wxGlade
# begin wxGlade: extracode
# end wxGlade
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((400, 100))
self.SetTitle("Test Slider")
self.panel = wx.Panel(self, wx.ID_ANY)
sizer = wx.BoxSizer(wx.VERTICAL)
self.slider = wx.Slider(self.panel, wx.ID_ANY, 100, 25, 100, style=wx.SL_AUTOTICKS | wx.SL_HORIZONTAL | wx.SL_LABELS)
sizer.Add(self.slider, 0, wx.EXPAND, 0)
self.panel.SetSizer(sizer)
self.Layout()
# end wxGlade
# end of class MyFrame
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
# end of class MyApp
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()
When I ran it on my MacBook Pro, I got:
I have tried a few experiments with your original code, based on information in How to work with sized controls (Phoenix) - wxPyWiki
First I tried adding a call to sizedPanel.SetSizerType()
using various combinations of the allowed values for the type
and options
parameters. Some permutations caused the layout of the slider and its labels to change, but none of them produced the correct layout.
This made me wonder if the slider and labels were being treated as separate controls by the SizedPanel
on mac whereas they are treated as a single composite control on linux?
I then tried making the slider a child of an ordinary wx.Panel
and making the wx.Panel
a child of the SizedPanel
. However, that caused all the labels to be drawn on top of each other, above the left end of the slider!
there is no problem on Windows
I did another experiment with your original code.
After the line:
self._frameTop.Show(True)
I added the following line:
print(sizedPanel.GetChildren())
When I ran the app on linux I got:
WindowList: [<wx._core.Slider object at 0x7fb7d6e39bd0>]
But when I ran it on mac I got:
WindowList: [<wx._core.Slider object at 0x1039e2320>, <wx._core.StaticText object at 0x1039e24d0>, <wx._core.StaticText object at 0x1039e2560>, <wx._core.StaticText object at 0x1039e25f0>]
So it does look like the labels are separate Statictext
controls on mac.
The following version appears to work on mac:
from typing import cast
import wx
from wx import App
from wx import DEFAULT_FRAME_STYLE
from wx import FRAME_FLOAT_ON_PARENT
from wx import ID_ANY
from wx import SL_AUTOTICKS
from wx import SL_HORIZONTAL
from wx import SL_LABELS
from wx import Slider
from wx.lib.sized_controls import SizedFrame
from wx.lib.sized_controls import SizedPanel
WINDOW_WIDTH: int = 400
WINDOW_HEIGHT: int = 200
class SliderBugApp(App):
def __init__(self):
super().__init__()
self._frameTop: SizedFrame = cast(SizedFrame, None)
def OnInit(self) -> bool:
title: str = 'Demo Buggy Slider'
frameStyle: int = DEFAULT_FRAME_STYLE | FRAME_FLOAT_ON_PARENT
self._frameTop = SizedFrame(parent=None, id=ID_ANY, size=(WINDOW_WIDTH, WINDOW_HEIGHT), style=frameStyle, title=title)
sizedPanel: SizedPanel = self._frameTop.GetContentsPane()
slideStyle: int = SL_HORIZONTAL | SL_AUTOTICKS | SL_LABELS
slider_panel = wx.Panel(sizedPanel)
sizer = wx.BoxSizer(wx.VERTICAL)
slider = Slider(slider_panel, id=ID_ANY, value=100, minValue=25, maxValue=100, style=slideStyle)
sizer.Add(slider, 1, wx.EXPAND, 0)
slider_panel.SetSizer(sizer)
self._frameTop.Show(True)
return True
testApp = SliderBugApp()
testApp.MainLoop()
You are a bulldog. I tried a version of this approach but could not get it to work. Thanks for this work around
Cross posted this to StackOverflow