简体   繁体   中英

Python tkinter Frame with multiple widgets within another Frame

I'd like to position one of my python tkinter Frames ( ButtonWindow ) within my other Frame ( MainWindow ), so that when I run the app the widgets in ButtonWindow are present in MainWindow along with the MainWindow widget.

In the code below the Buttons from ButtonWindow are present along with the MainWindow Label, but the ButtonWindow Label is missing.

I looked at the answers in Frame inside another frame In python Tkinter and tried to set the background to purple to understand where the borders of ButtonWindow actually are, but I can't see any purple?

Thanks for any help!

import tkinter as tk 

class ButtonWindow(tk.Frame):   

    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.bd = 5
        self.bg = "purple"
        self.label = tk.Label(text="Button window", font=12)
        for i in range(3):
            self.button = ttk.Button(text="button", command= lambda: button_fun())
            self.button.pack(side = tk.LEFT)
        
    def button_fun(self):
        pass
                          

class MainWindow(tk.Frame):   

    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.label = tk.Label(text="Main Window", font=12)
        self.label.pack(pady=10,padx=10)
        self.button_window = ButtonWindow()
        self.button_window.pack()
  
app = MainWindow()
app.mainloop()

If I understood correctly what you want is create a Main Frame with another frame inside it which include 3 buttons.

In this case, I changed a little bit your code to do that. One of the changes was replace the tk.Label for the tk.LabelFrame (This corrects the Label that was missing in the ButtonWindow as you stated).

The second change that I suggest is to pass the MainFrame to the ButtonWindow as a parent frame. To do this I created the myCoreFrame inside the MainWindow class. Also, for all widgets I've set a parent frame.

import tkinter as tk

class ButtonWindow():   

    def __init__(self, Frame, *args, **kwargs):
        self.label = tk.LabelFrame(Frame, text="Button window", font=12, bg = "purple")
        self.label.pack()
        for i in range(3):
            self.button = tk.Button(self.label, text="button", command= lambda: button_fun())
            self.button.pack(side = tk.LEFT)
        
def button_fun(self):
    pass
                          

class MainWindow():   

    def __init__(self, window, *args, **kwargs):
        
        myCoreFrame = tk.Frame(window)
        myCoreFrame.pack()
        
        self.label = tk.LabelFrame(myCoreFrame, text="Main Window", font=12, bg = "red")
        self.label.pack(pady=10,padx=10)
        self.button_window = ButtonWindow(self.label)

root = tk.Tk()
app = MainWindow(root)
root.mainloop()

The problem is that you aren't putting the labels and buttons inside frames. You need to explicitly set the frame as the parent of the button and label. If you don't, the widgets become children of the root window.

class ButtonWindow(tk.Frame):   

    def __init__(self, *args, **kwargs):
        ...
        self.label = tk.Label(self, text="Button window", font=12)
        #                     ^^^^^^
        for i in range(3):
            self.button = ttk.Button(self, text="button", command= lambda: button_fun())
            #                        ^^^^^^
        ...

class MainWindow(tk.Frame):   

    def __init__(self, *args, **kwargs):
        ...
        self.label = tk.Label(self, text="Main Window", font=12)
        #                     ^^^^^ 
        self.label.pack(pady=10,padx=10)
        self.button_window = ButtonWindow(self)
        #                                 ^^^^
        ...

It is better to specify the parent of widgets when creating them, otherwise they will be children of root window.

Also you have never called any layout function on the "Button window" label so it is not visible.

self.bd = 5 and self.bg = "purple" will not change the border width and the background color. Use self.config(bd=5, bg="purple") instead.

import tkinter as tk
from tkinter import ttk

class ButtonWindow(tk.Frame):

    def __init__(self, master=None, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
        self.config(bd=5, bg="purple") # replace self.bd = 5 and self.bg = "purple"
        self.label = tk.Label(self, text="Button window", font=12, fg='white', bg='purple') # specify parent
        self.label.pack() # pack the label, otherwise it is not visible
        for i in range(3):
            self.button = ttk.Button(self, text="button", command=self.button_fun) # specify parent
            self.button.pack(side=tk.LEFT)

    def button_fun(self):
        pass


class MainWindow(tk.Frame):

    def __init__(self, master=None, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
        self.label = tk.Label(self, text="Main Window", font=12) # specify parent
        self.label.pack(pady=10, padx=10)
        self.button_window = ButtonWindow(self) # specify parent
        self.button_window.pack()

root = tk.Tk() # create root window explicitly
MainWindow(root).pack()
root.mainloop()

Also I have changed command=lambda: button_fun() to command=self.button_fun . The former one will raise exception when any of the buttons is clicked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM