【问题标题】:Tkinter, Linux: How to view window in windows task bar which has no title bar?Tkinter,Linux:如何在没有标题栏的Windows任务栏中查看窗口?
【发布时间】:2021-11-03 13:59:54
【问题描述】:

我创建了一个窗口:

root = Tk()

并删除了标题栏:

root.attributes("-type", "splash")

现在窗口不在任务栏上。如何在任务栏中显示?

系统详情:

  • Ubuntu:21.04
  • Python:3.9.5
  • Tcl 版本:8.6
  • <tk.Tk>._windowingsystem: "x11"

这个问题已经回答了 Windows here

【问题讨论】:

    标签: python tkinter x11 taskbar


    【解决方案1】:

    一种方法是直接使用libX11 并告诉它不要在普通的tk.Tk() 窗口上绘制标题栏,如下所示:

    # Mostly taken from: https://www.tonyobryan.com//index.php?article=9
    # Inspired by: https://github.com/EDCD/EDMarketConnector/blob/main/theme.py
    import tkinter as tk
    import ctypes
    
    # Defining types
    CHAR = ctypes.c_char
    UCHAR = ctypes.c_ubyte
    BOOL = ctypes.c_bool
    INT = ctypes.c_int
    UINT = ctypes.c_uint
    LONG = ctypes.c_long
    PTR = ctypes.c_void_p
    
    CHAR_PTR = ctypes.POINTER(CHAR)
    UINT_PTR = ctypes.POINTER(UINT)
    ULONG = ctypes.c_ulong
    
    class HINTS(ctypes.Structure):
        _fields_ = (("flags", ULONG),
                    ("functions", ULONG),
                    ("decorations", ULONG),
                    ("inputMode", LONG),
                    ("status", ULONG))
    
    DISPLAY = PTR
    ATOM = LONG
    WINDOW = LONG
    WINDOW_PTR = ctypes.POINTER(WINDOW)
    HINTS_PTR = ctypes.POINTER(HINTS)
    
    def _errcheck_not_zero(value, func, args):
        if value == 0:
            args_str = ", ".join(map(str, args))
            raise OSError(f"{func.__name__}({args_str}) => {value}")
        return args
    
    def string_to_c(data:str) -> CHAR_PTR:
        return ctypes.create_string_buffer(data.encode())
    
    libx11 = ctypes.cdll.LoadLibrary("libX11.so.6")
    
    # Constants
    PropModeReplace = 0
    XA_ATOM = 4
    
    # Defining functions
    XInternAtom = libx11.XInternAtom
    XInternAtom.argtypes = (PTR, CHAR_PTR, BOOL)
    XInternAtom.restype = ATOM
    XInternAtom.errcheck = _errcheck_not_zero
    
    XOpenDisplay = libx11.XOpenDisplay
    XOpenDisplay.argtypes = (CHAR_PTR, )
    XOpenDisplay.restype = DISPLAY
    XOpenDisplay.errcheck = _errcheck_not_zero
    
    XChangeProperty = libx11.XChangeProperty
    XChangeProperty.argtypes = (DISPLAY, WINDOW, ATOM, ATOM, INT, INT, HINTS_PTR, INT)
    XChangeProperty.restype = INT
    XChangeProperty.errcheck = _errcheck_not_zero
    
    XQueryTree = libx11.XQueryTree
    XQueryTree.argtypes = (DISPLAY, WINDOW, WINDOW_PTR, WINDOW_PTR, WINDOW_PTR, UINT_PTR)
    XQueryTree.restype = INT
    XQueryTree.errcheck = _errcheck_not_zero
    
    XFlush = libx11.XFlush
    XFlush.argtypes = (DISPLAY, )
    XFlush.restype = INT
    XFlush.errcheck = _errcheck_not_zero
    
    
    if __name__ == "__main__":
        root = tk.Tk()
    
        # This is needed:
        root.update_idletasks()
        # Get the handle of the window
        handle:int = root.winfo_id()
    
        # Get the default display
        display = XOpenDisplay(None)
    
        # Get the parent of the window
        parent = WINDOW()
        XQueryTree(display, handle, ctypes.byref(WINDOW()),
                   ctypes.byref(parent), ctypes.byref(WINDOW()),
                   ctypes.byref(UINT()))
    
        # Change the motif hints of the window
        motif_hints = XInternAtom(display, string_to_c("_MOTIF_WM_HINTS"), False)
        hints = HINTS()
        hints.flags = 2 # Specify that we're changing the window decorations.
        hints.decorations = False
        XChangeProperty(display, parent, motif_hints, XA_ATOM, 32,
                        PropModeReplace, ctypes.byref(hints), 5)
        # Flush the changes
        XFlush(display)
    
        # Normal `tkinter` code can follow
        root.mainloop()
    

    它使用root.update_idletasks()XQueryTree(...) 来获取窗口的句柄。然后它会修改"_MOTIF_WM_HINTS",以便x11 会删除所有的窗口装饰,包括标题栏。

    【讨论】:

      猜你喜欢
      • 2015-08-27
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 2023-04-02
      • 2019-03-13
      • 2010-10-20
      • 2011-05-03
      相关资源
      最近更新 更多