简体   繁体   English

Python-将包含tkinter小部件的框架传递给类

[英]Python - Passing a frame containing tkinter widgets into a class

I'm tring to build a scrollable GUI window containing ttk.Entry and ttk.Label . 我正在尝试构建一个包含ttk.Entryttk.Label的可滚动GUI窗口。

The only way doing so (as noted in many questions here )- is by creating a Canvas , with a frame that contains all that widgets. 这样做的唯一方法(如此处的许多问题所述)是通过创建一个Canvas ,其中包含一个包含所有小部件的框架。

So- my goal is to make such class- that gets as a parameter a frame containing all needed widgets, and display it in a window with horizontal and vertical scroll bars ( since I need it in many displays inside my code ). 因此,我的目标是使此类成为一个包含所有所需小部件的框架作为参数,并将其显示在具有水平和垂直滚动条的窗口中(因为我在代码内部的许多显示器中都需要它)。

After coding successfully - I tried to make a class, but it shows only empty green canvas. 成功编码后-我尝试制作一个类,但只显示空的绿色画布。

Any ideas what am I doing wrong? 有什么想法我做错了吗?

import tkinter as tk
from tkinter import ttk


class CanvasWidgets(ttk.Frame):
    def __init__(self, master, frame_in, width=100, height=100):
        ttk.Frame.__init__(self, master)

        self.master = master
        self.frame = frame_in
        self.width, self.height = width, height

        self.build_gui()

    def build_gui(self):
        self.canvas = tk.Canvas(self.master, self.width, self.height, bg='light green')
        # self.frame = ttk.Frame(self.frame_in)

        self.frame.bind("<Configure>", self.onFrameConfigure)
        self.vsb = tk.Scrollbar(self.frame, orient="vertical", command=self.canvas.yview)
        self.hsb = tk.Scrollbar(self.frame, orient="horizontal", command=self.canvas.xview)
        self.canvas.configure(yscrollcommand=self.vsb.set, xscrollcommand=self.hsb.set)
        self.vsb.grid(row=0, column=1, sticky=tk.N + tk.S + tk.W)
        self.hsb.grid(row=1, column=0, sticky=tk.W + tk.N + tk.E)
        self.canvas.create_window((4, 4), window=self.frame, anchor="nw")

        self.canvas.grid(row=0, column=0)

    def onFrameConfigure(self, event):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))


root = tk.Tk()
frame = ttk.Frame(root)

rows, cols = 5, 5
for row in range(rows):
    for col in range(cols):
        ttk.Label(frame, text=[row, col], relief=tk.SUNKEN, width=5).grid(row=row, column=col, sticky=tk.E)

a = CanvasWidgets(root, frame)
a.grid()
root.mainloop()

The first problem is that you are placing the canvas in master when it needs to be in self . 第一个问题是,你是把画布在master时,它需要在self Think of the instance of CanvasWindow as a box in which you are going to put everything else. CanvasWindow实例视为要在其中放置其他所有内容的框。

The second problem is that, because the frame was created before the canvas, the frame has a lower stacking order than the canvas. 第二个问题是,因为框架是在画布之前创建的,所以框架的堆叠顺序比画布低。 You need to call lift on the frame to get it to be above the canvas. 您需要调用框架上的lift ,使其位于画布上方。

The third problem is that you're putting the scrollbars in frame . 第三个问题是您要将滚动条放入frame You can't put them in the inner frame because they control the inner frame. 您不能将它们放在内部框架中,因为它们控制内部框架。 Instead, they also need to be in self . 相反,他们还需要保持self Both the scrollbar and the canvas need to share a common parent. 滚动条和画布都需要共享一个公共父级。

The fourth problem is that the frame isn't a child of the canvas, so it won't be clipped by the borders of the canvas. 第四个问题是框架不是画布的子元素,因此不会被画布的边界剪裁。 It would be better if the CanvasWidgets created the frame, and then the caller can get the frame and add widgets to it. 如果CanvasWidgets创建了框架,然后调用者可以获取框架并向其添加小部件,那就更好了。

For example: 例如:

a = CanvasWidgets(root)

rows, cols = 5, 5
for row in range(rows):
    for col in range(cols):
        label = ttk.Label(a.frame, text=[row, col], relief=tk.SUNKEN, width=5)
        label.grid(row=row, column=col, sticky=tk.E)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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