簡體   English   中英

Tkinter頂層窗口不可移動

[英]Tkinter Toplevel Window Not Movable

在我的Tkinter應用程序中,我有一個按鈕可以打開一個頂級窗口,該窗口將支付事件日志。 我需要一些頂級窗口才能執行的操作:

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

我們可以從toplevel窗口的頂部刪除工具欄,並防止用戶使用self.textWindow.overrideredirect(True)移動窗口。

然后,通過獲取根窗口位置,然后使用self.master.winfo_x()self.master.winfo_y()toplevel窗口設置為相同的位置,可以確保toplevel窗口位於右上角。

最后,我將添加一個關閉窗口的按鈕,因為我們不再具有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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM