首页 > 解决方案 > 将一组小部件复制到每个单元格的最佳方法是什么?特金特

问题描述

我想创建一个循环,我可以用它来用相同的三个小部件填充列中的每个单元格,这些小部件彼此堆叠并在同一个单元格内。我能想到的最好方法是首先为每个单元格创建一个框架(通过一个循环),然后用三个小部件(通过一个单独的循环)填充每个框架。顶部和底部小部件将是按钮,中间小部件将是标签。

这是一个好方法,还是你能建议一些更清洁的方法?

简化代码:

import tkinter as tk
from tkinter import simpledialog,filedialog,colorchooser,messagebox,Frame,Button
from PIL import ImageTk, Image
import textwrap

root = tk.Tk()
root.state('zoomed')
rq = 10 # row quantity

canv_1 = tk.Canvas(root, bg="blue")
canv_1.pack(side="top", fill="both")#, fill="both", expand=True)

canv_2 = tk.Canvas(root, bg="gray")
canv_2.pack(fill="both", expand=True)

def onFrameConfigure(canvas):
    '''Reset the scroll region to encompass the inner frame'''
    canvas.configure(scrollregion=canvas.bbox("all"))

frame = tk.Frame(canv_2)

# create, bind & position scrollbar
vsb = tk.Scrollbar(canv_2, orient="vertical", command=canv_2.yview)
canv_2.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")

canv_2.pack(side="left", fill="both", expand=True)
canv_2.create_window((0,0), window=frame, anchor="nw")
frame.bind("<Configure>", lambda event, canv_2=canv_2: onFrameConfigure(canv_2))

labels = ["","Chapter Title", "Slide", "Instructions"]
ColWidths = [5, 15, 15, 40]
root.label_wid = []
font1 = ("arial", 15)

load1 = Image.open("StartingImage.jpg")
root.render1 = ImageTk.PhotoImage(load1)

ch_text = []

for i in range(len(labels)):
    root.label_wid.append(tk.Label(canv_1,
                                   font=font1,
                                   relief="raised",
                                   text=labels[i],
                                   width=ColWidths[i],
                                   ).grid(row=0, column=i, sticky="we"))

c1 = "#a9d08e"
c2 = "#8dd1bf"

Move_col = [
    tk.Entry(
        frame,
        bg = c1,
        width = ColWidths[0],
        font = font1)
    for y in range(0, rq)
]

Title_col = [
    tk.Entry(
        frame,
        bg = c1,
        width = ColWidths[1],
        font = font1)
    for y in range(0, rq)
]

Slide_col = [
    tk.Entry(
        frame,
        bg = c2,
        width = ColWidths[2],
        font = font1)
    for y in range(0, rq)
]

instruction_col = [
    tk.Text(
        frame,
        bg="white",
        wrap="word",
        font=font1, width = ColWidths[3], height=10)
    for y in range(0, rq)
]

for y in range(0, rq):
    Move_col[y].grid(row=y + 1, column=0, sticky='news')
    Title_col[y].grid(row=y + 1, column=1, sticky='news')
    Slide_col[y].grid(row=y + 1, column=2, sticky='news')
    instruction_col[y].grid(row=y+1, column=3, sticky='news')

bt1 = tk.Button(canv_1, text="Export", font=font1, bg="#f5b942")
bt1.grid(row=0, column=4)
load2 = Image.open("scroll-up-gray.png")
root.render2 = ImageTk.PhotoImage(load2)
load3 = Image.open("scroll-down.png")
root.render3 = ImageTk.PhotoImage(load3)

root.mainloop()

输出:

在此处输入图像描述

期望的输出:

在此处输入图像描述

标签: pythonuser-interfacetkinter

解决方案


我建议创建一个从小Frame部件继承的类。然后,您几乎可以像使用任何其他小部件一样使用此类的实例。我说“几乎”是因为它不支持与内置小部件相同的所有选项,但它的行为方式相同:您可以创建它、销毁它,然后调用packplacegrid对其进行调用。

有很多方法可以做到这一点。以下示例使用文本而不是图像作为按钮以保持示例简单:

class MoveWidget(tk.Frame):
    """
    Custom widget with buttons for moving up and down. When clicked,
    the button will call the given command with two parameters: the
    index and either "up" or "down"
    """
    def __init__(self, parent, bg, index, command):
        super().__init__(parent, background=bg)

        self.index = index
        self.command = command

        self.up_button = tk.Button(self, text="^", bg=bg, command=self.up)
        self.down_button = tk.Button(self, text="v", bg=bg, command=self.down)
        self.label = tk.Label(self, bg=bg, text=str(index))

        self.up_button.pack(side="top", fill="x")
        self.down_button.pack(side="bottom", fill="x")
        self.label.pack(side="top", fill="both", expand=True)

    def up(self):
        self.command(self.index, "up")

    def down(self):
        self.command(self.index, "down")

在使用此类之前,您需要定义一个函数来移动项目。让它接受一个索引和一个方向。实际的实现取决于你,这对于这个答案来说已经足够了:

    def move(index, direction):
        if direction == "up":
            print(f"Moving index {index} up")
        else:
            print(f"Moving index {index} down")

现在您可以创建该类的一个实例,为其提供父窗口小部件、索引、命令和颜色作为参数:

Move_col = [
    MoveWidget(
        frame,
        bg=c1,
        index=y,
        command=move)
    for y in range(0, rq)
]

您不必更改调用grid此小部件的代码。


推荐阅读