Python Tkinter связывается через несколько окон и возвращает значения после уничтожения - PullRequest
0 голосов
/ 12 ноября 2018

Я хочу создать программу с несколькими окнами 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 проблемами: главное окно не закрывается после уничтожения верхнего уровня и данные с верхнего уровня не возвращаются.

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Один из способов сделать это - скрыть корневое окно, используя окно верхнего уровня, а затем обновить это окно. Это позволяет нам много сгущать.

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()

Лично я предпочитаю подход ООП, и это облегчает управление в будущем.

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()

Это сказало, что вам, вероятно, не нужно использовать место. Вы сможете получить необходимый вам вид от grid() или pack(), как только научитесь правильно их использовать.

0 голосов
/ 12 ноября 2018

Один из способов заставить его работать - просто вывести корневое окно вместо его уничтожения и использовать StringVar для передачи данных.

Вы также можете просто переписать корень с новым макетом, если вам больше не нужно то, что на нем, я бы посмотрел другие примеры.

Одна из основных проблем, с которыми вы сейчас сталкиваетесь, - это уничтожение TopLevel до того, как данные будут переданы в корень, но уничтожение после обратного вызова будет игнорировать уничтожение, и ему не нравится передавать TopLevel в рут, для меня все равно.

Я не совсем понимаю, почему вы предпочитаете <bind> атрибуту 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()
...