Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScrolledFrame Behavior #140

Closed
antrrax opened this issue Jan 14, 2022 · 5 comments · Fixed by #193
Closed

ScrolledFrame Behavior #140

antrrax opened this issue Jan 14, 2022 · 5 comments · Fixed by #193
Labels
bug Something isn't working

Comments

@antrrax
Copy link
Contributor

antrrax commented Jan 14, 2022

Is this a bug or expected behavior?

This code generates this layout:

import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.scrolled import ScrolledFrame

class MainFrame(ttk.Window):
    def __init__(self):
        ttk.Window.__init__(self)

        self.geometry('500x300')
        self.title('Tkinter')
        
        self.set_notebook()
        self.set_tab0()
        return

    def set_notebook(self):
        self.nb = ttk.Notebook(self)
        self.nb.place(relx=0, rely=0, relwidth=1, relheight=1)
        return

    def set_tab0(self):
        #self.frm = ScrolledFrame(self, autohide=True)
        self.frm = ttk.Frame(self)
        self.frm.place(relx=0, rely=0, relwidth=1, relheight=1)

        ##Top
        self.frm_top = ttk.Frame(self.frm)
        self.frm_top.pack(fill=BOTH, expand=1)

        ttk.Label(self.frm_top, text='frame 1: top place (10, 25)').place(x=10, y=25)
        
        ttk.Label(self.frm_top, text='frame 1: top pack').pack()

        #middle
        self.frm_middle = ttk.Frame(self.frm)
        self.frm_middle.pack(fill=BOTH, expand=1)

        ttk.Label(self.frm_middle, text='frame 2: middle - pack').pack()

        ttk.Label(self.frm_middle, text='frame 2: middle - place (10, 25)').place(x=10, y=25)

        #Bottom
        self.frm_bottom = ttk.Frame(self.frm)
        self.frm_bottom.pack(side=BOTTOM, fill=X)
        ttk.Label(self.frm_bottom, text='frame 3: bottom - pack').pack()

        #self.nb.add(self.frm.container, text='Test')
        self.nb.add(self.frm, text='Test')
        return

if __name__== '__main__':
    app = MainFrame()
    app.mainloop()

nromal


Scrolled:

If I replace the frame (self.frm) with a ScrolledFrame, see how the layout changes: the widget with .place was not displayed and the frame side=bottom does not obey the bottom position:

scrolled

import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.scrolled import ScrolledFrame

class MainFrame(ttk.Window):
    def __init__(self):
        ttk.Window.__init__(self)

        self.geometry('500x300')
        self.title('Tkinter')
        
        self.set_notebook()
        self.set_tab0()
        return

    def set_notebook(self):
        self.nb = ttk.Notebook(self)
        self.nb.place(relx=0, rely=0, relwidth=1, relheight=1)
        return

    def set_tab0(self):
        self.frm = ScrolledFrame(self, autohide=True)
        #self.frm = ttk.Frame(self)
        self.frm.place(relx=0, rely=0, relwidth=1, relheight=1)

        ##Top
        self.frm_top = ttk.Frame(self.frm)
        self.frm_top.pack(fill=BOTH, expand=1)

        ttk.Label(self.frm_top, text='frame 1: top place (10, 25)').place(x=10, y=25)
        
        ttk.Label(self.frm_top, text='frame 1: top pack').pack()

        #middle
        self.frm_middle = ttk.Frame(self.frm)
        self.frm_middle.pack(fill=BOTH, expand=1)

        ttk.Label(self.frm_middle, text='frame 2: middle - pack').pack()

        ttk.Label(self.frm_middle, text='frame 2: middle - place (10, 25)').place(x=10, y=25)

        #Bottom
        self.frm_bottom = ttk.Frame(self.frm)
        self.frm_bottom.pack(side=BOTTOM, fill=X)
        ttk.Label(self.frm_bottom, text='frame 3: bottom - pack').pack()

        self.nb.add(self.frm.container, text='Test')
        #self.nb.add(self.frm, text='Test')
        return

if __name__== '__main__':
    app = MainFrame()
    app.mainloop()
@israel-dryer
Copy link
Owner

This may be related to the issue when using pack and place together. However, this gave me a clue of how to fix this, which I was partially implementing already. I just needed to assign a height as well as width so that the pack and place managers have a point of reference.

Code_sjyWy6qFHF

When doing this, I get this result.

python_4T1obZHa3t

Also, this line is not needed, and should probably be avoided as the frm no longer has control of the geometry when you delegate it to the notebook.

self.frm.place(relx=0, rely=0, relwidth=1, relheight=1)

Instead, you would use the sticky parameter when you add the frame:

self.nb.add(self.frm.container, text='Test', sticky=NSEW)

Finally, a tip on using Window, you can actually assign the size and title in the constructor if you wish

class MainFrame(ttk.Window):
    def __init__(self):
        ttk.Window.__init__(self, size=(500, 300), title="Tkinter")

I'll push a fix on this soon after I run a few more tests.

@israel-dryer israel-dryer added the bug Something isn't working label Jan 16, 2022
@israel-dryer
Copy link
Owner

@antrrax, confirm if you can that this fixes your issue. I was able to test it successfully on my end, but I want to make sure.

@antrrax
Copy link
Contributor Author

antrrax commented Jan 17, 2022

I tested it with the same code as in the first post. At first the problem was solved.
Thanks for the quick resolution.

@israel-dryer
Copy link
Owner

@antrrax, I'm reworking this widget, and the fix above actually created another problem. However, I now realize why this isn't working above and how to fix it. This is a unique case with using place and relative positioning so it took a while to figure out exactly why this should work, and why my fix caused other issues.

The height of the frame is determined by either the contents or a fixed size that you specify. This is what makes the content frame scrollable relative to the container frame. To fix the issue above, you would simply give the scrolled frame a height. ScrolledFrame.place controls the geometry of the container, not the geometry of the content frame inside of it. So, that is why the relative height does not affect the internal frame, but does affect the container.

@israel-dryer israel-dryer linked a pull request Feb 8, 2022 that will close this issue
@israel-dryer
Copy link
Owner

@antrrax, the scrolled frame has a default width and height like the Canvas widget, however, you can override with pack, place, grid, just as with any other widget.

I've added a new parameter called scrollheight which sets the height of the content frame manually in the case that you are using a relative positioning such as in the example above.

self.frm = ScrolledFrame(self, autohide=True, scrollheight=300)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants