仅当Tkniter Toplevel尚不存在时才打开它

时间:2017-07-12 19:40:24

标签: python user-interface tkinter

我正在尝试使用Tkinter UI创建一个python应用程序,目前我遇到了以下问题。我正在尝试设置UI,以便在后台保留日志,当用户按下按钮时,会出现Toplevel窗口。该窗口显示日志,并实时附加更新。到目前为止,所有这些都能正常运作。

但是我想这样做,如果Toplevel窗口打开,则无法再次打开。

此外,主程序在运行时将全屏显示。这意味着如果日志窗口处于打开状态且用户再次与主程序交互,则日志窗口将不再可见。有没有办法让Toplevel窗口保持在根窗口之上,即使在用户与根窗口交互时也是如此?

以下是我一直在摆弄的代码:

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):
        #if not tk.Toplevel.winfo_exists(self.textWindow):
            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()
    myapp = guiapp(root)
    root.mainloop()

我在TextWindow方法(if not tk.Toplevel.winfo_exists(self.textWindow))中注释掉的行是我试图用作“如果存在,不要使窗口”的交易。无论如何运行我都会收到错误:

'guiapp' has no attribute ''textWindow'

我的意思是我理解程序在它存在之前没有属性textWindow。这就是我首先尝试使用winfo_exists()的全部原因。

我想知道是否应该创建一个isOpen布尔值,但问题是我不知道如何检测窗口何时关闭。

任何帮助都是有目的的。

3 个答案:

答案 0 :(得分:2)

作为一个简单的修复,我只想在构造函数中创建self.topLevel。然后,由于tk.Toplevel.winfo_exists()显然不能将None作为参数,你可以使你的条件:

system("cmd /c C:[path to file]");

然后无论你总是将有效的TopLevel传递给winfo_exists(),并且在第一次点击按钮时仍然会创建TopLevel。

最终结果如下:

if self.textWindow == None or not tk.Toplevel.winfo_exists(self.textWindow):

答案 1 :(得分:1)

除了检查它是否存在外,您还需要初始化self.textWindow

class guiapp(tk.Frame):
    ...
    self.textWindow = None
    ...

    def TextWindow(self):
        if self.textWindow is None or not self.textWindow.winfo_exists():
            self.textWindow = tk.Toplevel(self.master)
            ...

答案 2 :(得分:0)

我的第一个想法是制作一个#include <random> #include <iostream> int main() { std::random_device rd; //Will be used to obtain a seed for the random number engine std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() std::uniform_int_distribution<> dis(1, 6); for (int n=0; n<10; ++n) //Use dis to transform the random unsigned int generated by gen into an int in [1, 6] std::cout << dis(gen) << ' '; std::cout << '\n'; } 版本,可以对被销毁做出反应:

Toplevel

我会在点击时禁用该按钮,并使用上面的其他代码重新启用它。

class Skitzafreak(tk.Toplevel):
    def destroy(self):
        print('destroyed toplevel') # plus any other code you want to add
        tk.Toplevel.destroy(self)

另外,请记住使用'self'作为小部件的主人,而不是'self.master'。