2017-08-08 206 views
0

在我的Tkinter應用程序中,我有一個按鈕,打開一個顯示事件日誌的Toplevel窗口。有幾件事我需要Toplevel窗口能夠做到:Tkinter Toplevel窗口不可移動

  1. 打開時顯示以前的日誌條目,以及用新的日誌條目更新。
  2. 禁用用戶的移動窗口周圍,同時能力也使能關閉窗口
  3. 用戶有窗口總是與它固定的右上角處於根窗口的右上角

我想出了#1。我可以打開窗口並顯示以前的條目,並在窗口打開時更新這些條目。我的問題是#2和#3。

對於#2我不知道如何禁用用戶移動窗口的能力。我假定這也可以禁用用戶的,所以我不知道如何保持這一功能完好,關閉窗口的能力。也許有一個按鈕self.quit()作爲它的命令?

至於#3,我不知道如何去做這件事。也許我喜歡谷歌搜索,但我似乎無法找到如何做到這一點。

這是我現在的代碼,它能夠正確實現功能#1。

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

回答

1

我們才能把toplevel窗口頂部的工具欄和防止用戶與self.textWindow.overrideredirect(True)移動窗口。

然後我們就可以確保該toplevel窗口通過獲取根窗口的位置,然後設置toplevel窗口到相同的位置與self.master.winfo_x()self.master.winfo_y()位於右上角。

最後我會添加一個關閉窗口的按鈕,因爲我們不再有toplevel窗口的工具欄。

更新:我已經添加了toplevel窗口保留在根窗口之上的能力,並在拖動根目錄時使用根窗口四處移動。

我們可以使用bind()來跟蹤何時移動根窗口,然後有一個函數將更新toplevel窗口位置以匹配根窗口。

我們還可以使用self.textWindow.attributes("-topmost", True)來告訴tkinter在所有其他窗口上排除toplevel窗口。

看看下面的代碼修改後的版本。讓我知道你的想法或者如果你有任何問題。

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

這基本上是我在找的。非常感謝你:) – Skitzafreak

+0

@Skitzafreak:我已經制定出一些錯誤與如何檢查是否存在窗口。我只是更新了我的答案,以防止由於某些if語句而發生的錯誤。如果您對更新後的代碼有任何疑問,請告知我們。 –