0

我正在尝试Toplevel从系统托盘菜单中打开一个带有 tkinter 的窗口。

from cmath import phase
from tkinter import *
from tkinter import messagebox, messagebox
from tracemalloc import start
from pystray import MenuItem as item
import pystray
from PIL import ImageTk,Image
import pickle

def quit_window(icon, item):
    icon.stop()
    root.destroy()
    exit()

def hidden():
    global my_img1
    top=Toplevel()
    top.title("Secret menu, shhh :^)")
    top.overrideredirect(True)
    top.attributes('-alpha', 0.9)
    w = 1100
    h = 450
    ws = top.winfo_screenwidth()
    hs = top.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/3) - (h/2)
    top.geometry('%dx%d+%d+%d' % (w, h, x, y))
    top.iconbitmap('screen.ico')
    my_img1 = ImageTk.PhotoImage(Image.open("ITEXTRA.png"))
    label1=Label(top,image=my_img1).place(relx=0.01,rely=0.01)
    button2=Button(top,text="Close window",bg='#ff4a65',command=top.destroy, relief=GROOVE).place(relx=0.9,rely=0.9)
    # Marks window as used
    hiddenwindow=1
    pickle.dump(hiddenwindow, open("window.dat", "wb"))
    Button(root, text="Developer Options", padx=57, bg="#86b3b3",fg="black", command = hidden).grid(row=3,column=0)

def hide_window():
    root.withdraw()
    image=Image.open("screen.ico")
    menu=(item('Dev window', hidden),item('show window', show_window),item('Exit app', quit_window))
    icon=pystray.Icon("ITExtra", image, "Program", menu)
    icon.run()

def show_window(icon, item):
    icon.stop()
    root.after(0,root.deiconify())
    root.after(0,root.focus_force)


root = Tk()
root.title("ITextra")
root.geometry("400x400")
root.protocol('WM_DELETE_WINDOW', hide_window)
hidden()

root.mainloop()

但不幸的是,这不起作用,它不会拉起顶层窗口,也不会拉起主窗口。如果我自己打开根窗口,顶层窗口将打开,但没有响应。

编辑 好吧,所以我尝试将顶窗添加为类,但我不断收到错误“顶部”对象没有属性“tk”。我在下面粘贴了更新的代码。任何帮助总是非常感谢!

from cmath import phase
from tkinter import *
from tkinter import messagebox, messagebox
from tracemalloc import start
from pystray import MenuItem as item
import pystray
from PIL import ImageTk,Image
import pickle


class Top():
    def __init__(self,master=None):
        self.hide = True

    def hidden(self):
      if self.hide:
        global my_img1
        self.top=Toplevel(root)
        self.top.title("Secret menu, shhh :^)")
        self.top.attributes('-alpha', 0.9)
            
        w = 1100
        h = 450
        ws = self.top.winfo_screenwidth()
        hs = self.top.winfo_screenheight()
        x = (ws/2) - (w/2)
        y = (hs/3) - (h/2)
        self.top.geometry('%dx%d+%d+%d' % (w, h, x, y))
        self.top.iconbitmap('screen.ico')
        my_img1 = ImageTk.PhotoImage(Image.open("ITEXTRA.png"))
        label1=Label(self.top,image=my_img1).place(relx=0.01,rely=0.01)
        button2=Button(self.top,text="Close window",bg='#ff4a65',command=self.top.destroy, relief=GROOVE).place(relx=0.9,rely=0.9)
        # Marks window as used
        hiddenwindow=1
        pickle.dump(hiddenwindow, open("window.dat", "wb"))
        self.top.mainloop()


def somewhereelse():
    top.hide = True
    top.hidden()

def quit_window(icon, item):
    icon.stop()
    root.destroy()
    exit()

def show_window(icon, item):
    icon.stop()
    root.after(0,root.deiconify())
    root.after(0,root.focus_force)

def hide_window():
    root.withdraw()
    image=Image.open("screen.ico")
    try:
        if pickle.load(open("window.dat","rb")) ==1:
            menu=(item('Dev window', top.hidden),
                    item('show window', show_window),
                    item('Exit app', quit_window))
        else:
            menu=(item('Exit app', quit_window))
    except:
        menu=(item('Exit app', quit_window))
    icon=pystray.Icon("ITextra", image, "Program", menu)
    icon.run()
    
    
root = Tk()
root.title("ITextra")
root.geometry("400x400")
top = Top(root) #in main part
root.protocol('WM_DELETE_WINDOW', hide_window)

Button(root, text="Developer Options", padx=57, bg="#86b3b3",fg="black", command =top.hidden).grid(row=3,column=0)



root.mainloop()


顶部窗口仍然没有响应 不是在root打开时,而是当top自行打开时,它仍然没有响应。但是,当我单击按钮并拖动鼠标时,它会响应。我尝试在顶部添加一个主循环,但 aself.top.mainloop和 aroot.mainloop都不起作用。我尝试使用绑定,但它们也表现出相同的行为。

我在创造一些不起作用的东西吗?

我正在创建的应用程序是多线程的,我的问题是;这会使其他类的事情复杂化吗?我对编码很陌生,坦率地说,我不知道。对于任何感兴趣的人,将整个项目放在一个 pastebin中。我认为这是一团糟,但对于初学者来说,我仍然为此感到自豪。

4

1 回答 1

0

仍然没有响应,Toplevel()因为它没有附加事件循环 ( mainloop()),因为在此代码中,Toplevel 充当独立的主窗口。

需要将此 Toplevel 附加到 root -top = Toplevel(root)其中 root 作为参数传递给hidden(root). 这样,根事件循环适用于所有小部件子项,例如Toplevel. 这将有助于解决问题的主要部分。

(#add...) 所以没有必要,top.mainloop()因为现在根是主/父top在里面root.mainloop()

事件循环用于检查您通常使用的小部件上发生的任何事件bind()。例如 top.bind('<Button>',dosomething)dosomething定义函数在哪里。(...#添加)

如果您想要一个标题,top那么您需要创建自己的标题栏或标签(如果您正在使用)overrideredirect(True),因为这会删除平台窗口管理器。

(#add...)平台窗口管理器并没有被删除,因为它在使用overrideredirect(True). 这可能是您的窗口在此阶段的代码中似乎没有响应的另一个原因。需要自己编写附加到小部件的事件 - 就像您关闭小部件所做的那样Button。(...#添加)

对于问题的主要部分:此代码中没有任何内容涉及top小部件。show_window

(#add...) 可以考虑创建top一个类并在根目录中实例化它。hiddenfor的默认状态top可以是此类的一个属性。然后,您可以更改类属性以在其他地方的代码主体内隐藏或显示功能。

例如骨架草图:

class Top():
    def __init__(self,master=None):
        ... 
        self.hide = True
        ...

    def hidden(self):
      if self.hide:
          ...

def somewhereelse():
    top.hide = true
    top.hidden()

top = Top(root) #in main part

!!!显然非常简短的一般想法需要在这里工作以维护您的设计,这对我来说似乎相当不错。有几种方法可以将 Toplevel 小部件合并到类中,但这与原始问题有点离题。(...#添加)

1 月 28 日添加...

我建议class更彻底地学习,而不是仅仅举我的例子。但这里还有一点

class Top():
    def __init__(self,master=None):
        super().__init__()
        self.master = master 
        self.hide = True

    def hidden(self):
        ...
        self.top = Toplevel(self.master)
        ...

用我的话来说,但请检查 Python 文档,super().__init__()将调用继承对象的初始化函数,在这种情况下,它会返回到self.masterwhich isroot然后返回到tk.__init__which is 调用 in Tk()

我建议查看 Python 下载文件夹中的代码__init__.py文件,Lib\tkinter\以更好地了解 tkinter 的工作原理。

我认为这绝对是可以实现的,但可能需要一个不同的 GUI——同意这对于初学者来说是一个很好的开始,因此并不是一团糟!

使用class对于实现您想要做的事情并不重要,但类对于封装对象非常有用,因此可以为您的项目定制与该对象相关的任何额外属性和方法。这使得进一步或未来的开发更容易。

...添加于 1 月 28 日

于 2022-01-24T20:35:49.307 回答