【问题标题】:Python Tkinter communicate through multiple windows and return values after destroyPython Tkinter 通过多个窗口进行通信并在销毁后返回值
【发布时间】:2018-11-12 15:19:24
【问题描述】:

我想制作一个有多个 tkinter 窗口的程序,但是我遇到了一些问题。我有一个包含一个按钮的主窗口。按下该按钮后,将打开一个顶层,其中包含通过用户输入一些数据的小部件。该顶层还包含一个按钮,一旦按下该按钮,顶层就会被销毁,并且引入的数据会从第一个按钮返回给事件调用的函数。主窗口被销毁,数据作为参数传递给将使用它的第三个窗口。

from tkinter import *


def third_window(data):
    root = Tk()

    lbl = Label(root, text=data)
    lbl.place(x=20,y=20)

    root.mainloop()

def second_window():
    def event_btn(event):
        e = entry.get()
        if len(e) != 0:
            root.destroy()
            print(e)
            return e
    root = Toplevel()
    root.geometry("400x400+200+200")

    entry = Entry(root, width=15)
    entry.place(x=30,y=30)
    btn = Button(root, text="Send")
    btn.bind("<Button-1>", event_btn)
    btn.place(x=80, y=80)
    root.wait_window()

    root.mainloop()

def main():
    def event_btn(event):
        data = second_window()
        print(data)
        root.destroy()
        third_window(data)
    root = Tk()
    root.geometry("200x200+100+100")

    btn = Button(root, text="Test button")
    btn.bind("<Button-1>", event_btn)   
    btn.place(x=50, y=50)

    root.mainloop()

if __name__ == "__main__":
    main()

遇到2个问题:顶层销毁后主窗口没有关闭,顶层数据没有返回。

【问题讨论】:

  • 我在这里看到了几个问题。 1 是root 不在全局命名空间中。第二,您在这里创建了 2 个 Tk() 实例,而不是只使用一个。这很可能不是您想要做的。

标签: python events tkinter toplevel


【解决方案1】:

您可以这样做的一种方法是使用顶级窗口隐藏根窗口,然后更新该窗口。这让我们可以压缩很多东西。

import tkinter as tk

def second_window():
    root.withdraw()
    top = tk.Toplevel(root)
    top.geometry("400x400+200+200")
    entry = tk.Entry(top, width=15)
    entry.place(x=30,y=30)

    def actions():
        x = entry.get()
        entry.destroy()
        btn.destroy()
        tk.Label(top, text=x).place(x=20,y=20)

    btn = tk.Button(top, text="Send", command=actions)
    btn.place(x=80, y=80)


if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("200x200+100+100")
    tk.Button(root, text="Test button", command=second_window).place(x=50, y=50)
    root.mainloop()

就我个人而言,我更喜欢 OOP 方法,它使事情变得更容易管理。

import tkinter as tk

class Example(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry("200x200+100+100")
        self.btn = tk.Button(self, text="Test button", command=self.update_window)
        self.btn.place(x=50, y=50)

    def update_window(self):
        self.geometry("400x400+200+200")
        self.entry = tk.Entry(self, width=15)
        self.entry.place(x=30,y=30)
        self.btn.config(text="Send", command=self.actions)
        self.btn.place(x=80, y=80)

    def actions(self):
        tk.Label(self, text=self.entry.get()).place(x=20,y=20)
        self.btn.destroy()
        self.entry.destroy()

if __name__ == "__main__":
    Example().mainloop()

也就是说你可能不需要使用 place。一旦您学会了如何正确使用它们,您将能够从grid()pack() 获得所需的外观。

【讨论】:

  • 是的,我知道 OOP 是一种更有用和更干净的方式来做这些事情。这段代码只是为了帮助你理解我想要的。非常感谢您的帮助!
【解决方案2】:

让它工作的一种方法是简单地撤回根窗口而不是销毁它,并使用StringVar 来传递数据。

你也可以简单地用你的新布局重写根,如果你不再需要它上面的东西,我会看看其他例子。

您现在面临的主要问题之一是在数据传递给根之前销毁 TopLevel,但在返回调用之后销毁将忽略销毁,并且它不喜欢将 TopLevel 传递给root,反正对我来说。

我真的不明白为什么您更喜欢 &lt;bind&gt; 而不是按钮的 command 属性。

from tkinter import *

def third_window(data):
    top = Toplevel()
    lbl = Label(top, text=data)
    lbl.place(x=20,y=20)
    top.wait_window()

def second_window(root, v):
    def event_btn():
        if len(v.get()) != 0:
            top.destroy()
    top = Toplevel()
    top.geometry("400x400+200+200")

    entry = Entry(top, textvariable = v, width=15)
    entry.place(x=30,y=30)
    btn = Button(top, text="Send", command = event_btn)
    btn.place(x=80, y=80)
    root.wait_window(top)

def main():
    def event_btn():
        second_window(root, v)
        print(v.get())
        root.withdraw()
        third_window(v.get())
    root = Tk()
    root.geometry("200x200+100+100")

    btn = Button(root, text="Test button", command = event_btn) 
    btn.place(x=50, y=50)

    v = StringVar()
    root.mainloop()

if __name__ == "__main__":
    main()

【讨论】:

  • 感谢您的帮助!
猜你喜欢
  • 2020-02-22
  • 2021-09-24
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多