首页 > 解决方案 > 如何在 tkinter 中重现课程

问题描述

我使用 tkinter 构建了一个小的 Synchronizer GUI 程序。我最近尝试添加一个 +-Button,它再现了文件浏览按钮和输入字段,因此我可以同步 2 个以上的目录。(即我个人将我的文档和图片备份在我想要保持更新的 USB 驱动器上,但我不想复制我的整个 /home 目录。)

我遇到了两个问题。第一个问题是加号按钮的定位:我已将行数初始化为零,因此每次单击 + 按钮时,按钮/字段的新行实际上是在新行上。可悲的是,这不适用于在函数之外定义的加号按钮,但 self.rowcount += 1 不应该为整个班级调整行数吗?self.sourcefile其次,我不确定如何处理self.targetfile:当我选择一个新文件夹时,它会替换以前的输入,这不是想法。

我真的很感激任何帮助!

from tkinter import *
from tkinter import filedialog

class Application():
    def __init__(self):
        self.root = Tk()

        self.rowcount = 0
        self.sourcefile = ""
        self.targetfile = ""

        self.sourceDirectory = Entry(self.root, width=10)
        self.targetDirectory = Entry(self.root, width=10)
        self.sourceDirectory.insert(0, "Source")
        self.targetDirectory.insert(1, "Target")
        selectSource = Button(self.root, text = "browse source", command=self.select_source, height=15, width=15)
        selectTarget = Button(self.root, text = "browse target", command=self.select_target, height=15, width=15)
        plusButton = Button(self.root, text = "+", command=self.create_new)

        self.sourceDirectory.grid(row=0, column=0)
        self.targetDirectory.grid(row=0, column=5)
        selectSource.grid(row=0, column=1)
        selectTarget.grid(row=0, column=10)
        plusButton.grid(row=self.rowcount + 1, column=10)

        self.root.mainloop()

    def create_new(self):
        self.rowcount += 1
        print(self.rowcount)
        self.sourceDirectory = Entry(self.root, width=10)
        self.targetDirectory = Entry(self.root, width=10)
        self.sourceDirectory.insert(0, "Source")
        self.targetDirectory.insert(1, "Target")
        selectSource = Button(self.root, image=self.browsericon, command=self.select_source, height=15, width=15)
        selectTarget = Button(self.root, image=self.browsericon, command=self.select_target, height=15, width=15)

        self.sourceDirectory.grid(row=self.rowcount, column=0)
        self.targetDirectory.grid(row=self.rowcount, column=5)
        selectSource.grid(row=self.rowcount, column=1)
        selectTarget.grid(row=self.rowcount, column=10)

    def select_source(self):
        source = filedialog.askdirectory(title="Select Source")
        self.sourceDirectory.delete(0, END)
        self.sourceDirectory.insert(0, source)
        self.sourcefile = source

    def select_target(self):
        target = filedialog.askdirectory(title="Select Target")
        self.targetDirectory.delete(0, END)
        self.targetDirectory.insert(1, target)
        self.targetfile = target

Application()

标签: python-3.xtkinter

解决方案


self.rowcount += 1 不应该为全班调整行数吗?

是的,它在你的代码中。但是,更改变量不会更改在grid命令中使用该变量的小部件的位置。

我的建议是将行放在一个框架中,将按钮放在另一个框架中。这样您就不必不断调整按钮的位置。例如:

self.row_frame = Frame(self.root)
self.button_frame = Frame(self.root)
self.button_frame.pack(side="bottom", fill="x")
self.row_frame.pack(side="top", fill="both", expand=True

此外,如果“+”按钮创建了一个新行,它不应该是重复代码。您需要一个用于添加行的函数。由于您已经有一个函数来执行此操作,因此您可以在__init__.

把它们放在一起看起来像这样:

class Application():
    def __init__(self):
        self.root = Tk()
        self.root.title("File Synchronizer")
        self.rowcount = 0
        self.sourcefile = ""
        self.targetfile = ""

        self.row_frame = Frame(self.root)
        self.button_frame = Frame(self.root)

        self.button_frame.pack(side="bottom", fill="x")
        self.row_frame.pack(side="top", fill="both", expand=True)

        startSync = Button(self.button_frame, text="Start", command=self.synchronize)
        plusButton = Button(self.button_frame, text = "+", command=self.create_new)

        startSync.grid(row=1, column=2)
        plusButton.grid(row=0, column=10)

        self.create_new()

        self.root.mainloop()

    def create_new(self):
        self.rowcount += 1
        self.sourceDirectory = Entry(self.row_frame, width=10)
        self.targetDirectory = Entry(self.row_frame, width=10)
        self.sourceDirectory.insert(0, "Source")
        self.targetDirectory.insert(1, "Target")
        selectSource = Button(self.row_frame, text = "browse source", command=self.select_source)
        selectTarget = Button(self.row_frame, text = "browse source", command=self.select_target)

        self.sourceDirectory.grid(row=self.rowcount, column=0)
        self.targetDirectory.grid(row=self.rowcount, column=5)
        selectSource.grid(row=self.rowcount, column=1)
        selectTarget.grid(row=self.rowcount, column=10)

这并没有将“加号”和“开始”按钮放在完全相同的位置,但这只是因为它与答案有些无关。您可以使用任何您想将其放置在按钮框架中的选项。由于两个框架是独立的,您可以在一个框架中调整行、列和权重,而不会影响另一个框架。或者,您可以pack在一个框架和grid另一个框架中使用。


您的代码的另一个问题是它self.sourceDirectory只能self.targetDirectory保存一个值,因此它将始终引用最后创建的小部件。

由于您正在创建多个源和目标小部件,因此您需要将它们保存在一个列表中。

例如,首先在__init__方法中向您的应用程序添加一个空列表:

self.sources = []
self.targets = []

然后,当您添加新行时,将其附加到列表中:

source_entry = Entry(self.row_frame, width=10)
target_entry = Entry(self.row_frame, width=10)
self.sources.append(source_entry)
self.targets.append(target_entry)

然后,您可以遍历这两个列表以处理所有源值和目标值。

您还必须修改浏览函数的回调以接受索引,以便按钮知道要更新哪个条目。


推荐阅读