如何在Tkinter窗口标题栏的最小化、最大化按钮旁添加功能按钮
Hey there! Great question—adding a custom button alongside the minimize/maximize/close buttons in Tkinter isn't straightforward out of the box, since the title bar is controlled by your operating system, not Tkinter itself. But we have two reliable approaches to make this work:
Approach 1: Custom Title Bar (Cross-Platform)
This is the most flexible, cross-platform solution. We'll hide the default system title bar and build our own, which includes all the standard window controls plus your custom button. Here's a complete working example:
import tkinter as tk from tkinter import ttk def custom_function(): """The function your custom button will call""" print("Custom button clicked!") def move_window(event): """Allow dragging the custom title bar to move the window""" root.geometry(f"+{event.x_root - offset_x}+{event.y_root - offset_y}") def get_offset(event): """Calculate the offset between mouse click and window top-left corner""" global offset_x, offset_y offset_x = event.x offset_y = event.y def minimize_window(): root.iconify() def maximize_window(): if root.state() == "normal": root.state("zoomed") else: root.state("normal") def close_window(): root.destroy() # Initialize main window root = tk.Tk() root.title("Custom Title Bar Demo") root.geometry("600x400") # Hide default title bar root.overrideredirect(True) # Create custom title bar frame title_bar = ttk.Frame(root, style="TitleBar.TFrame") title_bar.pack(fill=tk.X) # Style the title bar style = ttk.Style() style.configure("TitleBar.TFrame", background="#2c3e50") style.configure("TitleText.TLabel", background="#2c3e50", foreground="white", font=("Arial", 10)) style.configure("TitleButton.TButton", background="#2c3e50", foreground="white", borderwidth=0) # Add window title label title_label = ttk.Label(title_bar, text="Custom Title Bar Demo", style="TitleText.TLabel") title_label.pack(side=tk.LEFT, padx=10, pady=5) # Add your custom button first custom_btn = ttk.Button(title_bar, text="My Button", style="TitleButton.TButton", command=custom_function) custom_btn.pack(side=tk.RIGHT, padx=2, pady=2) # Add standard window controls close_btn = ttk.Button(title_bar, text="X", style="TitleButton.TButton", command=close_window) close_btn.pack(side=tk.RIGHT, padx=2, pady=2) maximize_btn = ttk.Button(title_bar, text="□", style="TitleButton.TButton", command=maximize_window) maximize_btn.pack(side=tk.RIGHT, padx=2, pady=2) minimize_btn = ttk.Button(title_bar, text="—", style="TitleButton.TButton", command=minimize_window) minimize_btn.pack(side=tk.RIGHT, padx=2, pady=2) # Bind title bar dragging title_bar.bind("<ButtonPress-1>", get_offset) title_bar.bind("<B1-Motion>", move_window) # Add main content frame main_content = ttk.Frame(root) main_content.pack(fill=tk.BOTH, expand=True, padx=1, pady=1) # Add some content to test ttk.Label(main_content, text="Main window content goes here!").pack(pady=20) root.mainloop()
Key notes about this approach:
- We use
overrideredirect(True)to hide the system title bar. - The custom title bar is a
ttk.Framestyled to match system title bars (you can tweak the colors/fonts to your liking). - We add drag functionality so users can move the window by clicking and dragging the title bar.
- All standard window controls (minimize, maximize, close) are recreated, plus your custom button that triggers
custom_function().
Approach 2: Windows-Only (Modify System Title Bar)
If you're only targeting Windows, you can use the pywin32 library to add a button-related option to the system title bar menu. First, install the library with pip install pywin32, then use this example:
import tkinter as tk import win32api import win32con import win32gui from ctypes import windll, c_int, c_uint, c_void_p, POINTER def custom_function(): print("Custom title bar option clicked!") def add_title_bar_option(hwnd): # Get the system menu handle hmenu = win32gui.GetSystemMenu(hwnd, False) # Add a separator and our custom menu item win32gui.AppendMenu(hmenu, win32con.MF_SEPARATOR, 0, "") custom_item_id = 1000 win32gui.AppendMenu(hmenu, win32con.MF_STRING, custom_item_id, "My Custom Action") # Hook into window messages to detect when our option is clicked def window_proc(hwnd, msg, wparam, lparam): if msg == win32con.WM_SYSCOMMAND: if wparam == custom_item_id: custom_function() return 0 return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) # Set the new window procedure windll.user32.SetWindowLongPtrW.argtypes = [c_void_p, c_int, c_void_p] windll.user32.SetWindowLongPtrW.restype = c_void_p old_proc = windll.user32.SetWindowLongPtrW(hwnd, win32con.GWL_WNDPROC, POINTER(c_void_p)(window_proc)) return old_proc root = tk.Tk() root.title("Windows Title Bar Option Demo") root.geometry("600x400") # Get the window handle hwnd = win32gui.GetParent(root.winfo_id()) # Add the custom option to the system title bar menu add_title_bar_option(hwnd) root.mainloop()
This adds a custom item to the menu that pops up when you right-click the title bar. If you want a visible button directly next to minimize/maximize/close, you'd need more advanced Win32 API calls to draw directly on the title bar—this simpler version adds a menu option instead.
Final Recommendation
For cross-platform apps, Approach 1 (custom title bar) is the way to go—it works on Windows, Mac, and Linux, and gives you full control over the title bar's appearance. Approach 2 is only useful if you're building a Windows-exclusive app and want to leverage the native system title bar.
内容的提问来源于stack exchange,提问作者ALEX MATHEW

