2017-08-08 2 views
0

In meiner Tkinter App habe ich eine Schaltfläche, die ein Toplevel-Fenster öffnet, das ein Ereignisprotokoll anzeigt. Es gibt ein paar Dinge, die ich brauche, um das Toplevel-Fenster ausführen zu können:Tkinter Toplevel Fenster nicht beweglich

  1. Zeigen Sie die vorherigen Protokolleinträge an, wenn Sie geöffnet sind, und aktualisieren Sie sie mit neuen.
  2. die Fähigkeit des Benutzers Deaktivieren Sie die Fenster um die während zu bewegen auch das Fenster der Benutzer in der Lage zu schließen machen
  3. Haben das Fenster immer mit seiner rechten oberen Ecke in der oberen rechten Ecke des Fensters Wurzel ist verankert werden

Ich habe # 1 herausgefunden. Ich kann das Fenster öffnen und vorherige Einträge anzeigen sowie diese Einträge aktualisieren, während das Fenster geöffnet ist. Mein Problem ist mit # 2 und # 3.

Für # 2 bin ich nicht sicher, wie Sie die Fähigkeit des Benutzers deaktivieren, das Fenster zu verschieben. Ich gehe davon aus, dass dies auch die Fähigkeit des Benutzers deaktivieren kann, das Fenster zu schließen, so dass ich nicht sicher bin, wie ich diese Funktionalität intakt halte. Vielleicht eine Taste mit self.quit() als Befehl?

Wie für # 3 habe ich keine Ahnung, wie man das macht. Vielleicht sauge ich als Googling, aber ich kann nicht herausfinden, wie das zu erreichen ist.

Dies ist der Code, den ich im Moment habe, der Feature # 1 richtig implementieren kann.

import tkinter as tk 

class guiapp(tk.Frame): 

    def __init__(self, master): 
     tk.Frame.__init__(self, master) 
     self.master = master 
     self.value = 0.0 
     self.alive = True 
     self.list_for_toplevel = [] 
     btn = tk.Button(self.master, text = "Click", command = self.TextWindow) 
     btn.pack() 

    def TextWindow(self): 
     self.textWindow = tk.Toplevel(self.master) 
     self.textFrame = tk.Frame(self.textWindow) 
     self.textFrame.pack() 
     self.textArea = tk.Text(self.textWindow, height = 10, width = 30) 
     self.textArea.pack(side = "left", fill = "y") 

     bar = tk.Scrollbar(self.textWindow) 
     bar.pack(side = "right", fill = "y") 
     bar.config(command = self.textArea.yview) 
     self.alive = True 
     self.timed_loop() 

    def timed_loop(self): 
     if self.alive == True and tk.Toplevel.winfo_exists(self.textWindow): 
      self.master.after(1000, self.timed_loop) 
      self.value += 1 
      self.list_for_toplevel.append(self.value) 
      self.textArea.delete(1.0, "end-1c") 
      for item in self.list_for_toplevel: 
       self.textArea.insert('end', "{}\n".format(item)) 
       self.textArea.see('end') 
     else: 
      self.alive = False 

if __name__ == "__main__": 

    root = tk.Tk() 
    root.geometry("800x480") 
    myapp = guiapp(root) 
    root.mainloop() 

Antwort

1

Wir können die Werkzeugleiste vom oberen Rand des toplevel Fenster entfernen und den Benutzer bewegt das Fenster mit self.textWindow.overrideredirect(True) verhindern.

Dann können wir sicherstellen, dass das toplevel Fenster in der rechten oberen Ecke positioniert wird, indem die Wurzel Fenster Standort bekommen und dann mit self.master.winfo_x() und self.master.winfo_y() das toplevel Fenster auf die gleiche Stelle zu setzen.

Zuletzt würde ich eine Schaltfläche hinzufügen, die das Fenster schließt, weil wir nicht mehr die Symbolleiste für das toplevel-Fenster haben.

UPDATE: Ich habe die Fähigkeit für das toplevel Fenster hinzugefügt, um über dem Stammfenster zu bleiben und sich mit dem Stammfenster zu bewegen, wenn root gezogen wird.

können wir bind() verwenden, um zu verfolgen, wenn das Stammfenster verschoben wird, und dann über eine Funktion verfügen, die die toplevel Windows-Position aktualisiert, um den Stammfenstern zu entsprechen.

Wir können auch self.textWindow.attributes("-topmost", True) verwenden, um tkinter zu sagen, um das Fenster toplevel über allen anderen Fenstern fernzuhalten.

Werfen Sie einen Blick auf die modifizierte Version Ihres Codes unten. Lass mich wissen, was du denkst oder ob du Fragen hast.

import tkinter as tk 

class guiapp(tk.Frame): 

    def __init__(self, master): 
     tk.Frame.__init__(self, master) 
     self.master = master 
     self.textWindow = None 
     self.master.bind("<Configure>", self.move_me) 
     self.value = 0.0 
     self.list_for_toplevel = [] 
     btn = tk.Button(self.master, text = "Click", command = self.TextWindow) 
     btn.pack() 

    def TextWindow(self): 
     x = self.master.winfo_x() 
     y = self.master.winfo_y() 

     self.textWindow = tk.Toplevel(self.master) 
     self.textFrame = tk.Frame(self.textWindow) 
     self.textWindow.overrideredirect(True) 
     self.textFrame.pack() 
     self.textWindow.attributes("-topmost", True) 

     self.textWindow.geometry('+{}+{}'.format(x+10, y+30)) 
     self.close_toplevel = tk.Button(self.textWindow, text = "close", command = self.close_textWindow) 
     self.close_toplevel.pack() 
     self.textArea = tk.Text(self.textWindow, height = 10, width = 30) 
     self.textArea.pack(side = "left", fill = "y") 

     bar = tk.Scrollbar(self.textWindow) 
     bar.pack(side = "right", fill = "y") 
     bar.config(command = self.textArea.yview) 
     self.alive = True 
     self.timed_loop() 

    def close_textWindow(self): 
     self.textWindow.destroy() 
     self.textWindow = None 

    def move_me(self, event): 
     if self.textWindow != None: 
      x = self.master.winfo_x() 
      y = self.master.winfo_y() 
      self.textWindow.geometry('+{}+{}'.format(x+10, y+30)) 

    def timed_loop(self): 
     if self.textWindow != None: 
      self.master.after(1000, self.timed_loop) 
      self.value += 1 
      self.list_for_toplevel.append(self.value) 
      self.textArea.delete(1.0, "end-1c") 
      for item in self.list_for_toplevel: 
       self.textArea.insert('end', "{}\n".format(item)) 
       self.textArea.see('end') 


if __name__ == "__main__": 

    root = tk.Tk() 
    root.geometry("800x480") 
    myapp = guiapp(root) 
    root.mainloop() 
+0

Dies ist im Grunde, was ich suche. Vielen Dank :) – Skitzafreak

+0

@Skitzafreak: Ich musste einige Bugs austesten, um zu überprüfen, ob ein Fenster existiert. Ich habe gerade meine Antwort aktualisiert, um Fehler zu vermeiden, die aufgrund einiger if-Anweisungen aufgetreten sind. Lassen Sie mich wissen, wenn Sie Fragen zum aktualisierten Code haben. –

Verwandte Themen