Пример кода Tkinter для нескольких окон, почему кнопки не загружаются правильно?
Я пишу программу, которая должна:
- Откройте окно нажатием кнопки.
- Закройте новое открытое окно нажатием другой кнопки.
Я использую классы, чтобы потом вставить код в большую программу. Однако я не могу заставить мои кнопки загружаться правильно.
import tkinter as tk
class Demo1(tk.Frame):
def __init__(self):
tk.Frame.__init__(self)
self.pack()
self.master.title("Demo 1")
self.button1 = tk.Button(self, text = "Button 1", width = 25,
command = self.new_window)
self.button1.grid(row = 0, column = 1, columnspan = 2, sticky = tk.W+tk.E+tk.N+tk.S)
def new_window(self):
self.newWindow = Demo2()
class Demo2(tk.Frame):
def __init__(self):
new = tk.Frame.__init__(self)
new = tk.Toplevel(self)
new.title("Demo 2")
new.button = tk.Button(text = "Button 2", width = 25,
command = self.close_window)
new.button.pack()
def close_window(self):
self.destroy()
def main():
Demo1().mainloop()
if __name__ == '__main__':
main()
4 ответа
Я переписал ваш код более организованным, более практичным способом:
import tkinter as tk
class Demo1:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)
self.button1.pack()
self.frame.pack()
def new_window(self):
self.newWindow = tk.Toplevel(self.master)
self.app = Demo2(self.newWindow)
class Demo2:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.master.destroy()
def main():
root = tk.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
Результат:
Вам нужно указать мастер для второй кнопки. В противном случае он будет упакован в первое окно. Это нужно не только для Button
, но также для других виджетов и не-графических объектов, таких как StringVar
,
Быстрое исправление: добавьте рамку new
в качестве первого аргумента к вашему Button
в Demo2
,
Возможно лучше: в настоящее время у вас есть Demo2
наследование от tk.Frame
но я думаю, что это имеет больше смысла, если вы измените Demo2
быть чем-то вроде этого,
class Demo2(tk.Toplevel):
def __init__(self):
tk.Toplevel.__init__(self)
self.title("Demo 2")
self.button = tk.Button(self, text="Button 2", # specified self as master
width=25, command=self.close_window)
self.button.pack()
def close_window(self):
self.destroy()
Так же, как предложение, вы должны только импортировать tkinter
один раз. Выберите один из первых двух операторов импорта.
#!/usr/bin/env python
import Tkinter as tk
from Tkinter import *
class windowclass():
def __init__(self,master):
self.master = master
self.frame = tk.Frame(master)
self.lbl = Label(master , text = "Label")
self.lbl.pack()
self.btn = Button(master , text = "Button" , command = self.command )
self.btn.pack()
self.frame.pack()
def command(self):
print 'Button is pressed!'
self.newWindow = tk.Toplevel(self.master)
self.app = windowclass1(self.newWindow)
class windowclass1():
def __init__(self , master):
self.master = master
self.frame = tk.Frame(master)
master.title("a")
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25 , command = self.close_window)
self.quitButton.pack()
self.frame.pack()
def close_window(self):
self.master.destroy()
root = Tk()
root.title("window")
root.geometry("350x50")
cls = windowclass(root)
root.mainloop()
Я попытался использовать более двух окон, используя приведенный выше пример Rushy Panchal. Намерение состояло в том, чтобы изменить вызов дополнительных окон с различными виджетами в них. Функция butnew создает разные кнопки для открытия разных окон. Вы передаете в качестве аргумента имя класса, содержащего окно (второй аргумент не нужен, я поместил его туда только для проверки возможного использования. Было бы интересно унаследовать от другого окна общие виджеты.
import tkinter as tk
class Demo1:
def __init__(self, master):
self.master = master
self.master.geometry("400x400")
self.frame = tk.Frame(self.master)
self.butnew("Window 1", "ONE", Demo2)
self.butnew("Window 2", "TWO", Demo3)
self.frame.pack()
def butnew(self, text, number, _class):
tk.Button(self.frame, text = text, width = 25, command = lambda: self.new_window(number, _class)).pack()
def new_window(self, number, _class):
self.newWindow = tk.Toplevel(self.master)
_class(self.newWindow, number)
class Demo2:
def __init__(self, master, number):
self.master = master
self.master.geometry("400x400+400+400")
self.frame = tk.Frame(self.master)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.label = tk.Label(master, text=f"this is window number {number}")
self.label.pack()
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.master.destroy()
class Demo3:
def __init__(self, master, number):
self.master = master
self.master.geometry("400x400+400+400")
self.frame = tk.Frame(self.master)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.label = tk.Label(master, text=f"this is window number {number}")
self.label.pack()
self.label2 = tk.Label(master, text="THIS IS HERE TO DIFFERENTIATE THIS WINDOW")
self.label2.pack()
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.master.destroy()
def main():
root = tk.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
Открыть новое окно только один раз
Чтобы не было возможности нажать несколько раз кнопку с несколькими окнами... которые являются одним и тем же окном, я сделал этот скрипт (взгляните и на эту страницу)
import tkinter as tk
def new_window1():
global win1
try:
if win1.state() == "normal": win1.focus()
except:
win1 = tk.Toplevel()
win1.geometry("300x300+500+200")
win1["bg"] = "navy"
lb = tk.Label(win1, text="Hello")
lb.pack()
win = tk.Tk()
win.geometry("200x200+200+100")
button = tk.Button(win, text="Open new Window")
button['command'] = new_window1
button.pack()
win.mainloop()
Что вы могли бы сделать, это скопировать код с tkinter.py
в файл с именем mytkinter.py
, затем сделайте этот код:
import tkinter, mytkinter
root = tkinter.Tk()
window = mytkinter.Tk()
button = mytkinter.Button(window, text="Search", width = 7,
command=cmd)
button2 = tkinter.Button(root, text="Search", width = 7,
command=cmdtwo)
И у вас есть два окна, которые не сталкиваются!