Making Window Scrollable after window goes less than a particular size

I want to make my window scrollable only if it goes less than a particular size (if it is opened on the laptop screen, it should be scrollable, but on a bigger monitor, it should not).

I believe this thing is done by using ScrolledWindow or ScrolledPanel by some way, but I exactly don’t know how. Below is a code snippet for the same

import wx
import wx.lib
import wx.lib.scrolledpanel

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        screenSize = wx.DisplaySize()
        screenWidth = screenSize[0]
        screenHeight = screenSize[1]
        
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)

        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        self.nb = wx.Notebook(self, wx.ID_ANY)
        sizer_1.Add(self.nb, 1, wx.EXPAND, 0)
        
        self.notebook_1_pane_1 = wx.lib.scrolledpanel.ScrolledPanel(self.nb,-1, size=(screenWidth,400), pos=(0,28), style=wx.SIMPLE_BORDER)
        self.notebook_1_pane_1.SetupScrolling()

        self.SetSizer(sizer_1)
        self.Layout()
        self.Update()


class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

Even on the bigger monitor screen where defining self.notebook_1_pane_1 as a simple panel (using wx.Panel) gives proper GUI, making it a scrolledpanel is adding scrollbars even there and making all sizers take additional spaces.

Please help!

Your panel is inside a notebook which is probably inside a frame.
Each of these has some window decoration. So the available space for the panel is less than the screen size. The panel size=(screenWidth,400) requires the scroll bars already.

P.S.: Please always post a runnable sample.

P.P.S.: And please stop posting the same question on multiple lists/pages. I told you previously already. I will not answer any of your questions any more.

Hi, As you had said, I have not posted questions on multiple places after that.
This particular query went dead on StackOverflow, hence had to post it here too

So any solution for the problem?
I have tried changing the size = (a,b) parameters, but it still doesn’t work.
I have also updated the code to be a runnable one

Set the size on the top-level window, and let the Layout algorithm size everything within to the available space.

Here’s a runnable sample with scrollbars added only as needed:

import wx.lib
import wize as iz

app = wx.App()
screenSize = wx.DisplaySize()
screenWidth = screenSize[0]
screenHeight = screenSize[1]
with iz.Frame(size=(screenWidth,400), pos=(0,28), orient=wx.VERTICAL) as fr:
    with iz.Notebook(flag=wx.EXPAND, proportion=1):
        with iz.Page("page title"):
            with iz.ScrolledWindow(style=wx.SIMPLE_BORDER, proportion=1, orient=wx.VERTICAL) as notebook_1_pane_1:
                for _ in range(1,25):
                    iz.StaticText("Content that may or may not need scrolling")
fr.Layout()
fr.Show()
app.MainLoop()

Oh yes you did. You posted this question to both the mailing list and here. Not nice.

I saw the mailing list post first, and assumed you had gotten no answers, because there were no answers on the mailing list.

Hi,

Yeah I was mentioning about this question only.
So Dietmar is talking about one earlier question that I had posted on 2 places a while back.
He told me (and rightly so) not to put same question on multiple places, and after that I am not doing that.(I’ve posted quite a few questions after that)

This particular question I posted here also because post on StackoverFlow went dead.

Regarding the mailing list thing, I think there is some issue with its updation. I posted the question and waited for 2 hours, and didn’t showed the question as posted.
So I posted the question here.
I got to know about Discuss wxPython from the mailing list only, it’s written in the Notice section…

This still doesn’t work…
After making the changes, scrollbar is added in the GUI in the bigger monitor also.
I am attaching screenshots of the same.

This is how I want my GUI to be on the bigger monitor

This is how the GUI is becoming after modifying as per your suggestion (scrollbar is added, which isn’t desired on the bigger screen):-

The window is detecting extra space availability, that’s why the sizers are taking up more spaces, which should not happen.

Also, when I say I don’t want a scrollbar on bigger screen, it means I don’t want it to be scrollable.
It is fine if a scrollbar is ‘just present’

If you don’t want scrollbars, then don’t create a ScrolledWindow or ScrolledPanel in the first place. Check the display size in advance and just use a regular wx.Panel on a big screen.

As I have mentioned in my question (and in the title also), I want a scrollbar when the window size is less than a particular size, like in a laptop screen.

So the GUI should not be scrollable when viewed on a bigger monitor, but it should be scrollable when viewed on a smaller screen like that of a laptop

well, @Tanmay_Agrawal, if you follow the docu there shouldn’t be any problem (I think) :star_struck:

ChuckM_scrwin_blth - Copy.py (12.2 KB)

@Tanmay_Agrawal As the other authors indicated, wx.lib.scrolledpanel.ScrolledPanel shows the scroll bars if it exceeds the client window size and hide them automatically if it doesn’t. Many controls manage their scroll bars like that.
Try this:

from wx.lib.scrolledpanel import ScrolledPanel

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        wx.Frame.__init__(self, *args, **kwds)

        self.panel = ScrolledPanel(self, size=(300,300))
        self.panel.SetupScrolling()

In your code, I think you forgot wx.Notebook.AddPage.

EDIT Sorry that this code is not a good example. :sweat_smile: The argument size=(300,300) does not make sense.
Please see the following post. When you add widgets to the scrolledPanel sizer, it can manage the view of the children.

That’s the issue mate, it isn’t working… the sizers weirdly start taking additional spaces :frowning:
Attaching the screenshot, when I use wx.lib.scrolledpanel.ScrolledPanel

Yeah I missed pasting .AddPage here

Hi Tanmay,
Your application structure would be like this:

Frame/
    Notebook/
        ScrolledPanel/
            <children>

When you add widgets to the scrolledPanel sizer, it can manage the view of the children.
For convenience and readability, create a scrollable custom panel:

class ControlPanel(wx.lib.scrolledpanel.ScrolledPanel):
    def __init__(self, *args, **kwargs):
        wx.lib.scrolledpanel.ScrolledPanel.__init__(self, *args, **kwargs)
        self.SetupScrolling()
        
        page = wx.Panel(self, size=(300,300))
        page.SetBackgroundColour('blue')
        
        sizer = wx.BoxSizer()
        sizer.Add(page)
        self.SetSizer(sizer)

Then, replace the following lines in your code with:

        ## self.notebook_1_pane_1 = wx.lib.scrolledpanel.ScrolledPanel(self.nb,-1, size=(screenWidth,400), pos=(0,28), style=wx.SIMPLE_BORDER)
        ## self.notebook_1_pane_1.SetupScrolling()
        self.pane = ControlPanel(self.nb)
        self.nb.AddPage(self.pane, "test")

Clipboard01

Hi Tanmay,

I’ve re-read this thread and it looks like your problem is caused by the large panel you added to the scrolledpanel,

The width of the scrolledpanel client is always less than the screenWidth, so the scrollbar are always visible. How about reducing the panel size and seeing what happens?

I have tried all possible numbers in the size parameter… 100, 300, 500, 5000
All are giving same results.

I don’t think the panel size is getting impacted by what number I put in size parameter

OK, I guess you are giving the size as an argument of ScrolledPanel, and you haven’t set a sizer for the ScrolledPanel?

The next step might be to inspect using InspectionTool.
In your test suite, add the following lines:

    from wx.lib.inspection import InspectionTool
    it = InspectionTool()
    it.Show()

Then, the widget inspection tool will launch.


To inspect the sizer’s problem,

  1. Click [Find] button and select the control you want to inspect.
    Then, the object tree will be expanded under [Widget Tree].
  2. Click the [Highlight] button.
    Then, the selected panel will be highlighted.

If you run into problems, you should start with the simplest code. It will help you to find the cause of the problem.

Code Example (click to expand)
import wx
import wx.lib.scrolledpanel as scrolled

class ControlPanel(scrolled.ScrolledPanel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        self.SetupScrolling()
        
        page = wx.Panel(self, size=(300,300))
        page.SetBackgroundColour('blue')
        
        sizer = wx.BoxSizer()
        sizer.Add(page)
        self.SetSizer(sizer)

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        self.nb = wx.Notebook(self)
        
        self.pane = ControlPanel(self.nb)
        self.pane.SetupScrolling()
        
        self.nb.AddPage(self.pane, "page")

if __name__ == "__main__":
    app = wx.App()
    frm = MyFrame(None)
    if 1:
        from wx.lib.inspection import InspectionTool
        it = InspectionTool()
        it.Show()
    frm.Show()
    app.MainLoop()

Hi.
This inspection tool is really helpful :love_you_gesture:
The issue is not solved, but now I know the exact problem.

Due to some reason, The SetVirtualSize parameter is not getting invoked. That’s why the windows is taking some VirtualSize on its own…
When from the inspection tool I set the Virtual Size and refresh it (via the Pycrust window), it works.
But I again have to give the command whenever I resize the window

So why is SetVirtualSize not getting invoked? How to invoke it everytime the window is resized?
Any solution for the problem?

I think you may have to use wx.ScrolledWindow and SetVirtualSize().