我正在尝试使用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
布尔值,但问题是我不知道如何检测窗口何时关闭。
任何帮助都是有目的的。
答案 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'。