【问题标题】:Make tkinter Window appear in the taskbar使 tkinter 窗口出现在任务栏中
【发布时间】:2015-09-16 09:18:09
【问题描述】:

我正在制作音乐播放器 GUI,但我无法让它出现在任务栏或 Alt-Tab 中。我已将 overrideredirect() 设置为 true 以删除边框和标题。我还这样做了,当用户执行“鼠标单击并拖动”操作时,窗口会移动。 代码如下:

import tkinter
import sys
import os


class Win(tkinter.Tk):
    global imgfile
    imgfile = r"play.png"

    def __init__(self, master=None):
        def close():
            self.destroy()
            sys.exit()

        def dirchosen():
            global songlist
            songlist = []
            try:
                os.chdir(dirinput.get())
            except:
                print("Invalid Directory")
                raise
            for file in os.listdir(dirinput.get()):
                songlist.append(file)

        tkinter.Tk.__init__(self, master)
        self.overrideredirect(True)
        self._offsetx = 0
        self._offsety = 0

        self.bind('<Button-1>', self.clickwin)
        self.bind('<B1-Motion>', self.dragwin)

        self.geometry("350x200")
        self.config(bg="#FF4766")

        titlelabel = tkinter.Label(self, text="FoxSGR Media Player", bg="#FF4766", font=("Segoe UI", 12))
        titlelabel.pack(ipady=4)

        chdirbutton = tkinter.Button(self, relief="groo", activebackground="#FF8080", command=dirchosen)
        chdirbutton.config(text="Choose Directory", bg="#FF4766", font=("Segoe UI", 8))
        chdirbutton.pack()
        chdirbutton.place(relx=0.66, rely=0.22)

        dirinput = tkinter.Entry(self, font=("Segoe UI", 8), width="34")
        dirinput.pack()
        dirinput.place(relx=0.05, rely=0.23)

        xbutton = tkinter.Button(self, text="x", height="1", command=close)
        xbutton.config(bg="red", activebackground="#FF8080", relief="groo", font=("Segoe UI", 8))
        xbutton.pack()
        xbutton.place(relx=0.90, rely=0.05)

    def dragwin(self, event):
        x = self.winfo_pointerx() - self._offsetx
        y = self.winfo_pointery() - self._offsety
        self.geometry('+{x}+{y}'.format(x=x, y=y))

    def clickwin(self, event):
        self._offsetx = event.x
        self._offsety = event.y

win = Win()

# Had to set the images appart from up there

imgplay = tkinter.PhotoImage(file=imgfile)
playbutton = tkinter.Button(win, image=imgplay, bg="#FF4766", relief="flat")
playbutton.pack()
playbutton.place(rely=0.45, relx=0.4)

imgnext = tkinter.PhotoImage(file="next.png")
nextbutton = tkinter.Button(win, image=imgnext, bg="#FF4766", relief="flat")
nextbutton.pack()
nextbutton.place(rely=0.45, relx=0.57)

imgprev = tkinter.PhotoImage(file="previous.png")
prevbutton = tkinter.Button(win, image=imgprev, bg="#FF4766", relief="flat")
prevbutton.pack()
prevbutton.place(rely=0.45, relx=0.30)

win.mainloop()

有什么方法可以让它至少出现在 Alt-Tab 中?

【问题讨论】:

  • 这不能回答您的问题,但是从您在win = Win() 之后的评论来看,我猜您在课堂内创建图像时遇到了一些问题来正确渲染它们。这是因为 PhotoImage 实例的过早垃圾收集。请参阅Why do my Tkinter images not appear? 获取指导。
  • @Kevin 我之前在试图解决图像问题时看过那篇文章,但当时并没有太大帮助。也许我没有正确应用该页面中的内容。
  • 您是将项目作为脚本运行还是冻结?

标签: python user-interface python-3.x tkinter


【解决方案1】:

经过一番研究,我发现有一种方法可以做到这一点,但它涉及使用 ctypes 并且是仅限 Windows 的解决方案:

import tkinter as tk
import tkinter.ttk as ttk
from ctypes import windll

GWL_EXSTYLE=-20
WS_EX_APPWINDOW=0x00040000
WS_EX_TOOLWINDOW=0x00000080

def set_appwindow(root):
    hwnd = windll.user32.GetParent(root.winfo_id())
    style = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
    style = style & ~WS_EX_TOOLWINDOW
    style = style | WS_EX_APPWINDOW
    res = windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, style)
    # re-assert the new window style
    root.wm_withdraw()
    root.after(10, lambda: root.wm_deiconify())

def main():
    root = tk.Tk()
    root.wm_title("AppWindow Test")
    button = ttk.Button(root, text='Exit', command=lambda: root.destroy())
    button.place(x=10,y=10)
    root.overrideredirect(True)
    root.after(10, lambda: set_appwindow(root))
    root.mainloop()

if __name__ == '__main__':
    main()

这涉及使用 ctypes 来操作 windows 样式,但是您需要根据应用程序环境使用正确的 Get/Set 函数。 对于 32 位 Windows,您似乎需要使用:
GetWindowLongWSetWindowLongW

GetWindowLongASetWindowLongA

但需要 64 位:
GetWindowLongPtrWSetWindowLongPtrW

GetWindowLongPtrASetWindowLongPtrA
this

或者,如果您希望默认使用此行为:

import tkinter as tk

from ctypes import windll

class Tk(tk.Tk):
    def overrideredirect(self, boolean=None):
        tk.Tk.overrideredirect(self, boolean)
        GWL_EXSTYLE=-20
        WS_EX_APPWINDOW=0x00040000
        WS_EX_TOOLWINDOW=0x00000080
        if boolean:
            print("Setting")
            hwnd = windll.user32.GetParent(self.winfo_id())
            style = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
            style = style & ~WS_EX_TOOLWINDOW
            style = style | WS_EX_APPWINDOW
            res = windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, style)
        self.wm_withdraw()
        self.wm_deiconify()

【讨论】:

  • 非常感谢!添加用于最小化窗口的函数会导致 overrideredirect 设置为 False,无论我做什么,之后它都保持不变。你能告诉我如何将该功能添加到此代码中
  • 请各位。对于想要实现这一目标的人,请仔细阅读此答案。以后你会感谢詹姆斯肯特的,相信我。他提供的第一段代码完美运行,对我来说没有任何问题
  • 这对我有帮助,谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-05-03
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-13
  • 2021-11-03
  • 2015-08-27
相关资源
最近更新 更多