如何在Python中同时运行多个tkinter窗口?

时间:2016-03-30 16:57:25

标签: python multithreading tkinter

所以我正在创建一个记笔记的应用程序(类似于Windows Sticky Notes)。由于我需要同时显示多个音符,因此我使用了一个继承自Thread的类,并创建了一个tkinter窗口。问题是我的窗户不能同时打开。第二个在第一个关闭后打开。这是代码。我究竟做错了什么?还有其他方法可供我使用吗? [现在我只是显示我硬编码的笔记。]

from tkinter import *
from threading import Thread

class Note(Thread):
nid = 0
title = ""
message = ""

    def __init__(self, nid, title, message):
      Thread.__init__(self)
      self.nid = nid
      self.title = title
      self.message = message


    def display_note_gui(self): 
      '''Tkinter to create a note gui window with parameters '''    
      window = Tk()
      window.title(self.title)
      window.geometry("200x200")
      window.configure(background="#BAD0EF")

      title = Entry(relief=FLAT, bg="#BAD0EF", bd=0)
      title.pack(side=TOP)
      scrollBar = Scrollbar(window, takefocus=0, width=20)
      textArea = Text(window, height=4, width=1000, bg="#BAD0EF", font=("Times", "14"))
      scrollBar.pack(side=RIGHT, fill=Y)
      textArea.pack(side=LEFT, fill=Y)
      scrollBar.config(command=textArea.yview)
      textArea.config(yscrollcommand=scrollBar.set)
      textArea.insert(END, self.message)
      window.mainloop()

    def run(self):
      self.display_note_gui()

new_note1 = Note(0, "Hello", "Hi, how are you?")
new_note1.start()
new_note1.join()


new_note2 = Note(1, "2", "How's everyone else?")
new_note2.start()
new_note2.join()

2 个答案:

答案 0 :(得分:1)

如果您只需要多个注释窗口,那么您绝对不需要线程。 Tkinter非常有能力管理数十个或数百个打开的窗口。

只为根窗口以外的每个窗口创建Toplevel的实例。这是一个有点过于设计的例子:

import Tkinter as tk

class Notepad(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.text = tk.Text(self, wrap="word")
        self.vsb = tk.Scrollbar(self, orient="vertical", comman=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.vsb.pack(side="right", fill="y")
        self.text.pack(side="left", fill="both", expand=True)

def main():
    root = tk.Tk()
    Notepad(root).pack(fill="both", expand=True)
    for i in range(5):
        top = tk.Toplevel(root)
        Notepad(top).pack(fill="both", expand=True)

    root.mainloop()

if __name__ == "__main__":
    main()

答案 1 :(得分:0)

而不是将Thread子类化为子类Toplevel,而tkinter中的顶级是同一应用程序中的一个单独窗口,听起来就像您要完成的那样:

from tkinter import *
#from threading import Thread #no longer needed

class Note(Toplevel):
    nid = 0
    #title = "" #this would block the method to override the current title
    message = ""

    def __init__(self, master, nid, title, message):
      Toplevel.__init__(self,master)
      self.nid = nid 
      self.title(title) #since toplevel widgets define a method called title you can't store it as an attribute
      self.message = message
      self.display_note_gui() #maybe just leave that code part of the __init__?


    def display_note_gui(self): 
      '''Tkinter to create a note gui window with parameters '''    
      #no window, just self
      self.geometry("200x200")
      self.configure(background="#BAD0EF")
      #pass self as the parent to all the child widgets instead of window
      title = Entry(self,relief=FLAT, bg="#BAD0EF", bd=0)
      title.pack(side=TOP)
      scrollBar = Scrollbar(self, takefocus=0, width=20)
      textArea = Text(self, height=4, width=1000, bg="#BAD0EF", font=("Times", "14"))
      scrollBar.pack(side=RIGHT, fill=Y)
      textArea.pack(side=LEFT, fill=Y)
      scrollBar.config(command=textArea.yview)
      textArea.config(yscrollcommand=scrollBar.set)
      textArea.insert(END, self.message)
      #self.mainloop() #leave this to the root window

    def run(self):
      self.display_note_gui()

root = Tk()
root.withdraw() #hide the root so that only the notes will be visible

new_note1 = Note(root, 0, "Hello", "Hi, how are you?")
#new_note1.start()
#new_note1.join()


new_note2 = Note(root, 1, "2", "How's everyone else?")
#new_note2.start()
#new_note2.join()

root.mainloop() #still call mainloop on the root

请注意,您无需将标题存储为属性,而是可以调用self.title()来获取窗口的当前标题,并self.title("new title")进行更改。