本文介绍了Tkinter,Linux:如何在没有标题栏的 Windows 任务栏中查看窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个窗口:

root = Tk()

并移除标题栏:

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

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

Now the window is not on the task bar. How can I show it in the task bar?

系统详情:

  • Ubuntu:21.04
  • Python:3.9.5
  • Tcl 版本:8.6
  • ._windowingsystem:x11"

此问题已在 Windows 此处

This question has already been answered for Windows here

推荐答案

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

One way is using libX11 directly and telling it not to draw the title bar on a normal tk.Tk() window like this:

# 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 将删除包括标题栏在内的所有窗口装饰.

It uses root.update_idletasks() and XQueryTree(...) to get the handle of the window. Then it modifies the "_MOTIF_WM_HINTS" so that x11 would remove all of the window decorations including the title bar.

这篇关于Tkinter,Linux:如何在没有标题栏的 Windows 任务栏中查看窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 14:34