Ski*_*eak 5 python user-interface tkinter
So here's the issue. I am programming a GUI using Python's TKinter, and I need the window to be a specific size. The release version of the program will have the screen settings as root.attributes("-fullscreen", True) so that it's fullscreen and the user won't be able to access any menus. Said screen will be an 800x480 tablet screen.
Obviously I am programming on a screen much bigger than 800x480, so when I create my tkinter window I am setting root.minsize("800x480") to simulate the environment the program will be in.
As for what is on the GUI, I'll have a series of Buttons and other things. The window itself is going to be split into two Frames: A Button Frame, and a Visual Frame. The Button Frame, as the name implies will be a Frame consisting entirely of Buttons for user input, whereas the Visual Frame, again obviously, will just contain visual outputs for the user.
So here is my problem. I am currently working on the Button Frame, and I am having an issue where the Frame is not sized properly. Since I don't have the programming done for the Visual Frame yet, I've just been creating two Button Frames and placing them into the root window. Both the Frames should take up the whole screen, but they aren't. Here is my code:
import tkinter as tk
from tkinter import ttk
class ButtonManager(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.config(background = 'green')
self.columnconfigure(0, weight = 1)
self.rowconfigure(0, weight = 1)
lblFrame = LabelFrame(self, controller)
lblFrame.grid(column = 0, row = 0, sticky = "nsew")
lblFrame.tkraise()
btnFrame = ButtonFrame(self, controller)
btnFrame.grid(column = 0, row = 1, sticky = "nsew")
btnFrame.tkraise()
for child in self.winfo_children():
child.grid_configure(padx = 5, pady = 5)
class LabelFrame(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.config(background = 'blue')
lblTitleBar = ttk.Label(self, text = 'TITLE BAR', background = 'grey', font = ("Arial", 20, "bold"))
lblTitleBar.grid(column = 1, row = 1, columnspan = 4, sticky = "nsew")
lblTextBar = ttk.Label(self, text = 'test text', background = 'grey', font = ("Arial", 16, "bold"))
lblTextBar.grid(column = 1, row = 2, columnspan = 4, sticky = "nsew")
class ButtonFrame(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.config(background = 'red')
btn1 = ttk.Button(self, text = '1', command = lambda : print("1"))
btn1.grid(column = 1, row = 1, columnspan = 2, rowspan = 2, sticky = "nsew")
#Not gonna type out the code for all the buttons, but I have 2 columns, and 6 rows.
#The buttons on the 4th and 6th row span the columns of both rows.
#In total there are 10 buttons
for child in self.winfo_children():
child.grid_configure(padx = 5, pady = 5)
class Interface(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.grid(column = 0, row = 0, sticky = "nsew")
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
bMan1 = ButtonManager(container, self)
bMan1.grid(column = 0, row = 0, sticky = "nsew")
bMan2 = ButtonManager(container, self)
bMan2.grid(column = 1, row = 0, sticky = "nsew")
interface = Interface()
interface.minsize(800, 480)
interface.mainloop()
Run Code Online (Sandbox Code Playgroud)
As I said above my issue is that I need each of the ButtonManager objects to take up half the screen each width wise. However I instead get 2 small-ish boxes and a large grey area.
The random colours are for testing purposes btw :P
EDIT: Had a few copy/paste errors in my code, and it should work as a single file now. Apologies.
你试图一次解决太多问题。当第一次开始使用 tkinter 时,或者当第一次布局一个新的 GUI 时,有条不紊地一次只解决一个布局问题真的很有帮助。
您已选择为 GUI 中的所有内容创建一个“容器”。因此,第一步是在尝试让其他任何事情发挥作用之前先让其发挥作用。如果它太小,那么它会导致它里面的所有东西都太小,这就是原始代码问题的一部分。
由于它是根目录中唯一的小部件,因此我建议使用pack. 您可以使用grid,但这需要三行代码而不是一行,因为grid您必须记住配置至少一行和一列的权重。
从以下内容开始(并且仅以下内容):
class Interface(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self, background="bisque")
container.pack(fill="both", expand=True)
interface = Interface()
interface.minsize(800, 480)
interface.mainloop()
Run Code Online (Sandbox Code Playgroud)
它看起来如何?对我来说看起来不错——蓝色完全填满了 800x480 的窗口。我们现在不再需要担心容器。
如果要使用grid,请删除调用 的一行pack,并将其替换为以下三行:
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
container.grid(row=0, column=0, sticky="nsew")
Run Code Online (Sandbox Code Playgroud)
看起来容器将包含两个孩子,对吗?左侧为按钮框,右侧为主要区域。现在让我们使用几个空框架,并在继续之前让它们工作。
您没有指定这些区域的大小,因此在此示例中,左侧的列将是屏幕大小的 1/3,右侧的列将是 2/3。如果您愿意,您可以为左侧使用固定的像素宽度,而让右侧占据其余部分。
如果你需要一个非常具体的宽度,你可以place在这里使用,但现在我们将坚持使用grid.
将以下内容添加到 的底部Interface.__init__:
bman = ButtonManager(container, controller=self)
main = Main(container, controller=self)
container.grid_columnconfigure(0, weight=1)
container.grid_columnconfigure(1, weight=2)
container.grid_rowconfigure(0, weight=1)
bman.grid(row=0, column=0, sticky="nsew")
main.grid(row=0, column=1, sticky="nsew")
Run Code Online (Sandbox Code Playgroud)
我们还需要为ButtonManager和定义存根Main:
class ButtonManager(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background="green")
class Main(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background="yellow")
Run Code Online (Sandbox Code Playgroud)
编码就够了。停止并运行代码,确保粉色窗口占据蓝色区域的 1/3,黄色窗口占据另外 2/3。
这可能是使用不同columnconfigure属性值(minsize、weight、pad)的好时机,或者切换到 usingplace看看它是如何工作的。
我们只需要继续这个过程,再深入一层。好消息是,我们只需要关注按钮管理器内部发生的事情。除非我们添加一个太大而无法容纳的小部件,否则我们无法整体更改窗口的整体布局。
它看起来ButtonManager由一个标题和一个按钮区域组成。所以,让我们补充一下。由于这个框架中只有两个小部件,我们可以再次使用 节省几行代码和一些麻烦pack,因为 pack 擅长从上到下堆叠东西。
在下面的代码中,我将标签贴在顶部,并让按钮框填充窗口的其余部分。
更改ButtonManager为如下所示:
class ButtonManager(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.config(background = 'green')
lblFrame = LabelFrame(self, controller)
btnFrame = ButtonFrame(self, controller)
lblFrame.pack(side="top", fill="x", expand=False)
btnFrame.pack(side="top", fill="both", expand=True)
Run Code Online (Sandbox Code Playgroud)
这只是一个带有几个标签的框架。同样,由于它只有几个小部件,pack将节省一些编码。您可以grid根据需要使用,只需记住您必须配置行和列的权重。
class LabelFrame(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background="blue")
lblTitleBar = ttk.Label(self, text = 'TITLE BAR', background = 'grey', font = ("Arial", 20, "bold"))
lblTextBar = ttk.Label(self, text = 'test text', background = 'grey', font = ("Arial", 16, "bold"))
lblTitleBar.pack(side="top", fill="x")
lblTextBar.pack(side="top", fill="x")
Run Code Online (Sandbox Code Playgroud)
最后,按钮框架。将有一个按钮网格。到目前为止,应该熟悉该过程 - 创建小部件,并使用grid或pack布置它们。在这种情况下grid最有意义。
class ButtonFrame(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background="red")
for row in range(7):
self.grid_rowconfigure(row, weight=1)
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
b1 = tk.Button(self, text="Button 1")
b2 = tk.Button(self, text="Button 2")
b3 = tk.Button(self, text="Button 3")
b4 = tk.Button(self, text="Button 4")
b5 = tk.Button(self, text="Button 5")
b6 = tk.Button(self, text="Button 6")
b7 = tk.Button(self, text="Button 7")
b8 = tk.Button(self, text="Button 8")
b9 = tk.Button(self, text="Button 9")
b10 = tk.Button(self, text="Button 10")
b1.grid(row=0, column=0, sticky="nsew")
b2.grid(row=0, column=1, sticky="nsew")
b3.grid(row=1, column=0, sticky="nsew")
b4.grid(row=1, column=1, sticky="nsew")
b5.grid(row=2, column=0, sticky="nsew")
b6.grid(row=2, column=1, sticky="nsew")
b7.grid(row=3, column=0, columnspan=2, sticky="nsew")
b8.grid(row=4, column=0, sticky="nsew")
b9.grid(row=4, column=1, sticky="nsew")
b10.grid(row=5, column=0, columnspan=2, sticky="nsew")
Run Code Online (Sandbox Code Playgroud)
如果您对 GUI 布局采用有条理的方法,那么问题将变得更容易解决,因为您一次只解决一个区域。如果您严格遵循上述所有内容,您最终会得到一个 GUI,即使您扩大或缩小窗口,它也能很好地工作。
我知道您需要一个非常具体的尺寸,但是养成编写 gui 的习惯是很好的,这些 gui 可以响应字体、分辨率和窗口尺寸的变化。