python - tkinter 顶级窗口不会从系统托盘菜单打开

标签 python tkinter pystray

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

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

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

编辑 好吧,所以我尝试将 topwindow 添加为类,但我不断收到错误“Top”对象没有属性“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 自行打开时,它仍然没有响应。但是,当我单击按钮并拖动鼠标时,它会做出响应。我尝试在顶部添加一个主循环,但是 self.top.mainloop 和 root.mainloop 都不起作用。 我尝试使用绑定(bind),但它们也显示出相同的行为。

我是否创建了一些不起作用的东西?

我正在创建的应用程序是多线程的,我的问题是;这会让其他类的事情变得复杂吗?我对编码很陌生,坦率地说我不知道​​。 我将整个项目放在粘贴箱中 here ,对于任何有兴趣的人。我认为这很困惑,但对于初学者来说我仍然感到非常自豪。

最佳答案

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

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

(#added...) 所以不需要 top.mainloop()因为现在根是主/父top在里面root.mainloop() .

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

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

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

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

(#已添加...) 可以看看制作 top一个类并在根中实例化它。默认状态hidden对于 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.master这是 root然后返回tk.__init__Tk() 中调用.

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

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

使用class对于实现您想要做的事情并不是必需的,但是类对于封装对象非常有用,以便可以为您的项目自定义与该对象相关的任何额外属性和方法。这使得进一步或 future 的开发变得更加容易。

...添加于 1 月 28 日

关于python - tkinter 顶级窗口不会从系统托盘菜单打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70839527/

相关文章:

python - 列组中的平均值

python - python中set.intersection的对面?

python - 为什么 Canvas 在添加小部件时不随滚动条滚动并自动调整大小?

python - 为什么我使用pystray时无法关闭?

python - 使用 selenium 和 beautifulsoup 进行网页抓取..解析和选择按钮时遇到麻烦

python - 如何在 32 位模式下使用 PyCharm

python - 如何刷新 Canvas 以显示变化矩阵的网格

python - 使按钮一次只打开一个窗口(通过关闭顶层窗口启用按钮)

python - 如何在 Pystray 中创建菜单和更新图标