【问题标题】:Not sure about Tkinter class structure and layout不确定 Tkinter 类结构和布局
【发布时间】:2017-09-24 14:40:01
【问题描述】:

我首先创建一个简单的提示窗口,用户将在其中填写目录名称以从中获取图像以及保存生成的 .csv 文件(和其他一些信息)的位置。

在这种情况下(在这种情况下)按回车后,我希望关闭此提示窗口,并显示用户将执行所有工作的主窗口。

简而言之,这是开始为我的 GUI 构建类的正确方法吗?还有为什么行:

frame = Frame(master, height=500,padx=20, pady=20)

不更改此初始窗口的格式/布局?

我觉得一旦我牢牢掌握了如何构建这个初始窗口,我将有适当的基础来继续我自己的其余部分。

#imports
from Tkinter import *
import glob
from PIL import Image, ImageTk
#end imports

class prompt_window:

    def __init__(self, master):

        frame = Frame(master, height=500,padx=20, pady=20)

        #Build prompt window labels
        self.source_label = Label(root, text="Source Directory")
        self.destination_label = Label(root, text="Destination Directory")
        self.region_sz_label = Label(root, text="Region Size")
        self.save_file_name_label = Label(root, text="Save File Name")

        #Build prompt window entry forms
        self.source_entry = Entry(root)
        self.destination_entry = Entry(root)
        self.region_sz_entry = Entry(root)
        self.save_file_name_entry = Entry(root)

        #Build enter button
        self.enter_button = Button(root, text="Enter")

        #Align labels in prompt window grid
        self.source_label.grid(row=0)
        self.destination_label.grid(row=1)
        self.region_sz_label.grid(row=2)
        self.save_file_name_label.grid(row=3)

        #Align entry forms in prompt window grid
        self.source_entry.grid(row=0, column=1)
        self.destination_entry.grid(row=1, column=1)
        self.region_sz_entry.grid(row=2, column=1)
        self.save_file_name_entry.grid(row=3, column=1)

        #Add button
        self.enter_button.grid(row=4,column=2)

#create root
root = Tk()

#create prompt window
prompt = prompt_window(root)

#run indefinitely
root.mainloop()

【问题讨论】:

  • 您需要在frame 上调用.grid(),它可能应该是其他小部件的第一个参数,而不是root。类名应改为PromptWindow,以符合PEP 8 - Style Guide for Python Code
  • @martineau 你能解释一下为什么应该在框架上调用 .grid() 以及它与保持适当结构的关系吗?
  • 如果您的代码按预期运行且没有任何错误,并且您需要有关性能或代码的建议,您可以在CodeReview 上发布问题。当然,在发布之前,请阅读他们的旅游页面。
  • @Lafexlos 此代码未按预期工作:它不显示小部件。并且OP不知道如何组织事情,以便在提示窗口关闭后打开主窗口。

标签: python class user-interface tkinter


【解决方案1】:

您需要在 Frame 上调用其中一种布局方法(.pack.grid.place)使其可见。在我的程序版本中,我已将类名从 prompt_window 更改为 PromptWindow 以符合 PEP-8 样式指南。我还更改了 Tkinter 导入语句,因此我们的命名空间不会被所有这些 Tkinter 名称弄乱。

组织 GUI 代码与组织一个普通的 CLI 程序有点不同。一旦我们定义了所有内容,我们就坐在一个循环中等待事件响应。因此,对于这个程序,我们需要进行设置,以便当提示窗口关闭时,主窗口打开并且它可以访问提示窗口收集的数据。

您说您希望提示窗口与主窗口不同,因此我们需要为其创建一个窗口。一个 Tkinter 程序只能有一个根窗口,所以我们创建一个 Toplevel 窗口来保存提示 Frame。

您不需要将标签保存为 PromptWindow 实例的属性,因为在创建它们之后您没有对它们进行任何操作。

我稍微更改了 Entry 小部件:我给了每个小部件一个 StringVar 来保存它们的数据。这使得在提示窗口关闭后访问该数据成为可能。当小部件的父窗口关闭时,您将无法再访问它。因此,我们不是将每个条目保存为 PromptWindow 的属性,而是保存关联的 StringVar。

当按下“Enter”按钮或按下提示窗口的关闭小部件时,我们会关闭提示窗口并使主窗口可见。

我创建了一个简单的 MainWindow 类,其中包含一个按钮,可以让我们打印提示窗口收集的数据。

import Tkinter as tk

class PromptWindow(object):
    def __init__(self, master):
        self.master = master
        self.win = tk.Toplevel(master)
        self.win.title("Prompt Window")

        # Intercept close window events so that when the user closes this window 
        # (via the close widget or the Enter button) the main window reopens
        self.win.protocol("WM_DELETE_WINDOW", self.close)

        frame = tk.Frame(self.win, height=500,padx=20, pady=20)
        frame.pack()

        # Build prompt window labels
        tk.Label(frame, text="Source Directory").grid(row=0)
        tk.Label(frame, text="Destination Directory").grid(row=1)
        tk.Label(frame, text="Region Size").grid(row=2)
        tk.Label(frame, text="Save File Name").grid(row=3)

        # Build prompt window entry widgets
        self.source = tk.StringVar() 
        tk.Entry(frame, textvariable=self.source).grid(row=0, column=1)

        self.destination = tk.StringVar()
        tk.Entry(frame, textvariable=self.destination).grid(row=1, column=1)

        self.region_sz = tk.StringVar()
        tk.Entry(frame, textvariable=self.region_sz).grid(row=2, column=1)

        self.save_file_name = tk.StringVar()
        tk.Entry(frame, textvariable=self.save_file_name).grid(row=3, column=1)

        # Build enter button
        tk.Button(frame, text="Enter", command=self.close).grid(row=4,column=2)

    def close(self):
        # Close this window
        self.win.destroy()
        # Reopen the main window
        self.master.deiconify()

class MainWindow(object):
    def __init__(self):
        # Create root window
        root = tk.Tk()
        # and make it invisible
        root.withdraw()
        root.title("Main Window")

        # Add some widgets
        tk.Label(root, text="This is the main window").pack()
        tk.Button(root, text="Show data", command=self.show_data).pack()

        # Create prompt window
        self.prompt = PromptWindow(root)

        # Loop forever
        root.mainloop()

    # Display the data gathered by the prompt window
    def show_data(self):
        prompt = self.prompt
        src = prompt.source.get()
        dest = prompt.destination.get()
        region = prompt.region_sz.get()
        fname = prompt.save_file_name.get()

        fmt = 'src: {!r}, dest: {!r}, region: {!r}, fname: {!r}'
        print(fmt.format(src, dest, region, fname)) 

MainWindow()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多