wxPython Slider incorrectly displays with sized panels

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:

BugScreenShot

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

Screenshot at 2024-05-02 18-57-14

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 :joy:

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 :clap:

Cross posted this to StackOverflow