在 Tkinter 中,geometry 方法用于设置窗口的大小和位置。下面详细解析 geometry 的用法和格式。

基本语法

import tkinter as tk

root = tk.Tk()

# 基本格式: "宽度x高度±X±Y"
root.geometry("400x300")          # 只设置大小
root.geometry("400x300+100+50")   # 设置大小和位置
root.geometry("+100+50")          # 只设置位置

root.mainloop()

完整解析示例

import tkinter as tk
import time

class GeometryDemo:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Geometry 完整解析")
        
        # 初始几何设置
        self.root.geometry("600x500+200+100")
        
        self.create_controls()
        self.create_display()
        self.update_display()
    
    def create_controls(self):
        """创建控制面板"""
        control_frame = tk.LabelFrame(self.root, text="几何布局控制", padx=10, pady=10)
        control_frame.pack(pady=10, padx=10, fill="x")
        
        # 尺寸控制
        size_frame = tk.Frame(control_frame)
        size_frame.pack(fill="x", pady=5)
        
        tk.Label(size_frame, text="宽度:").grid(row=0, column=0, sticky="w")
        self.width_var = tk.StringVar(value="600")
        width_entry = tk.Entry(size_frame, textvariable=self.width_var, width=8)
        width_entry.grid(row=0, column=1, padx=5)
        
        tk.Label(size_frame, text="高度:").grid(row=0, column=2, sticky="w", padx=(20,0))
        self.height_var = tk.StringVar(value="500")
        height_entry = tk.Entry(size_frame, textvariable=self.height_var, width=8)
        height_entry.grid(row=0, column=3, padx=5)
        
        # 位置控制
        pos_frame = tk.Frame(control_frame)
        pos_frame.pack(fill="x", pady=5)
        
        tk.Label(pos_frame, text="X位置:").grid(row=0, column=0, sticky="w")
        self.x_var = tk.StringVar(value="200")
        x_entry = tk.Entry(pos_frame, textvariable=self.x_var, width=8)
        x_entry.grid(row=0, column=1, padx=5)
        
        tk.Label(pos_frame, text="Y位置:").grid(row=0, column=2, sticky="w", padx=(20,0))
        self.y_var = tk.StringVar(value="100")
        y_entry = tk.Entry(pos_frame, textvariable=self.y_var, width=8)
        y_entry.grid(row=0, column=3, padx=5)
        
        # 按钮区域
        btn_frame = tk.Frame(control_frame)
        btn_frame.pack(pady=10)
        
        tk.Button(btn_frame, text="应用几何设置", 
                 command=self.apply_geometry).pack(side="left", padx=5)
        tk.Button(btn_frame, text="居中显示", 
                 command=self.center_window).pack(side="left", padx=5)
        tk.Button(btn_frame, text="最大化", 
                 command=self.maximize_window).pack(side="left", padx=5)
        tk.Button(btn_frame, text="最小化", 
                 command=self.minimize_window).pack(side="left", padx=5)
        tk.Button(btn_frame, text="恢复正常", 
                 command=self.normal_window).pack(side="left", padx=5)
    
    def create_display(self):
        """创建信息显示区域"""
        display_frame = tk.LabelFrame(self.root, text="几何信息显示", padx=10, pady=10)
        display_frame.pack(pady=10, padx=10, fill="both", expand=True)
        
        # 当前几何信息
        info_frame = tk.Frame(display_frame)
        info_frame.pack(fill="x", pady=5)
        
        self.geometry_var = tk.StringVar()
        geo_label = tk.Label(info_frame, textvariable=self.geometry_var, 
                            font=("Courier", 12), bg="lightyellow", relief="sunken")
        geo_label.pack(fill="x", padx=5, pady=5)
        
        # 详细信息表格
        details_frame = tk.Frame(display_frame)
        details_frame.pack(fill="both", expand=True)
        
        self.info_text = tk.Text(details_frame, height=12, font=("Courier", 10))
        scrollbar = tk.Scrollbar(details_frame, orient="vertical", command=self.info_text.yview)
        self.info_text.configure(yscrollcommand=scrollbar.set)
        
        self.info_text.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 自动更新开关
        auto_frame = tk.Frame(display_frame)
        auto_frame.pack(fill="x", pady=5)
        
        self.auto_update = tk.BooleanVar(value=True)
        auto_cb = tk.Checkbutton(auto_frame, text="自动更新信息", 
                                variable=self.auto_update)
        auto_cb.pack(side="left")
        
        tk.Button(auto_frame, text="手动更新", 
                 command=self.update_display).pack(side="left", padx=10)
    
    def apply_geometry(self):
        """应用几何设置"""
        try:
            width = self.width_var.get()
            height = self.height_var.get()
            x = self.x_var.get()
            y = self.y_var.get()
            
            geometry_str = f"{width}x{height}+{x}+{y}"
            self.root.geometry(geometry_str)
            
            if self.auto_update.get():
                self.update_display()
                
        except Exception as e:
            self.show_error(f"几何设置错误: {e}")
    
    def center_window(self):
        """窗口居中显示"""
        self.root.update_idletasks()  # 确保获取准确的窗口尺寸
        
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
        
        self.root.geometry(f"+{x}+{y}")
        
        # 更新输入框
        self.x_var.set(str(x))
        self.y_var.set(str(y))
        
        if self.auto_update.get():
            self.update_display()
    
    def maximize_window(self):
        """最大化窗口"""
        self.root.state('zoomed')  # Windows
        # self.root.attributes('-zoomed', True)  # Linux
        if self.auto_update.get():
            self.update_display()
    
    def minimize_window(self):
        """最小化窗口"""
        self.root.iconify()
    
    def normal_window(self):
        """恢复正常窗口状态"""
        self.root.state('normal')  # Windows
        # self.root.attributes('-zoomed', False)  # Linux
        if self.auto_update.get():
            self.update_display()
    
    def update_display(self):
        """更新显示信息"""
        # 获取当前几何字符串
        current_geometry = self.root.geometry()
        self.geometry_var.set(f"当前几何: {current_geometry}")
        
        # 获取详细信息
        info = self.get_detailed_info()
        
        # 更新文本显示
        self.info_text.delete("1.0", tk.END)
        self.info_text.insert("1.0", info)
    
    def get_detailed_info(self):
        """获取详细的几何信息"""
        # 解析几何字符串
        geometry = self.root.geometry()
        parts = geometry.split('+')
        
        if len(parts) >= 3:
            size_part = parts[0]
            x_pos = parts[1]
            y_pos = parts[2]
            
            size_parts = size_part.split('x')
            if len(size_parts) == 2:
                width = size_parts[0]
                height = size_parts[1]
            else:
                width = "N/A"
                height = "N/A"
        else:
            width = height = x_pos = y_pos = "N/A"
        
        # 获取其他窗口信息
        info = f"""几何布局解析:
══════════════════════════════════════
原始几何字符串: {geometry}

解析结果:
• 宽度: {width}
• 高度: {height}  
• X 位置: {x_pos}
• Y 位置: {y_pos}

窗口状态信息:
══════════════════════════════════════
实际宽度: {self.root.winfo_width()}
实际高度: {self.root.winfo_height()}
X 坐标: {self.root.winfo_x()}
Y 坐标: {self.root.winfo_y()}
根 X 坐标: {self.root.winfo_rootx()}
根 Y 坐标: {self.root.winfo_rooty()}

屏幕信息:
══════════════════════════════════════
屏幕宽度: {self.root.winfo_screenwidth()}
屏幕高度: {self.root.winfo_screenheight()}
屏幕色深: {self.root.winfo_screendepth()} bits
屏幕视觉: {self.root.winfo_screenvisual()}

窗口管理器信息:
══════════════════════════════════════
窗口ID: {self.root.winfo_id()}
父窗口: {self.root.winfo_parent()}
顶级窗口: {self.root.winfo_toplevel()}
窗口管理器: {self.root.winfo_manager()}

其他属性:
══════════════════════════════════════
是否映射: {self.root.winfo_ismapped()}
是否可见: {self.root.winfo_viewable()}
是否存在: {self.root.winfo_exists()}
"""
        return info
    
    def show_error(self, message):
        """显示错误信息"""
        self.info_text.delete("1.0", tk.END)
        self.info_text.insert("1.0", f"错误: {message}")
    
    def run(self):
        """运行应用"""
        # 启动自动更新
        self.auto_update_display()
        self.root.mainloop()
    
    def auto_update_display(self):
        """自动更新显示"""
        if self.auto_update.get():
            self.update_display()
        self.root.after(1000, self.auto_update_display)  # 每秒更新一次

# 运行演示
if __name__ == "__main__":
    app = GeometryDemo()
    app.run()

Geometry 字符串格式详解

import tkinter as tk

class GeometryFormat:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Geometry 格式详解")
        self.root.geometry("700x550")
        
        self.create_examples()
    
    def create_examples(self):
        """创建格式示例"""
        main_frame = tk.Frame(self.root)
        main_frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 格式说明
        format_frame = tk.LabelFrame(main_frame, text="Geometry 格式说明", padx=10, pady=10)
        format_frame.pack(fill="x", pady=5)
        
        format_text = """
Geometry 字符串格式: "宽度x高度±X±Y"

• "400x300"        - 只设置窗口大小 (400像素宽, 300像素高)
• "+100+50"        - 只设置窗口位置 (距离左边界100px, 上边界50px)  
• "400x300+100+50" - 同时设置大小和位置
• "400x300-100+50" - 使用负值定位 (距离右边界100px)

注意:
• 宽度和高度是窗口内容区域的大小,不包括边框和标题栏
• X 和 Y 是窗口左上角在屏幕上的坐标
• 可以使用负值进行特殊定位
"""
        
        format_label = tk.Label(format_frame, text=format_text, 
                               justify="left", font=("Courier", 10), bg="white")
        format_label.pack(fill="x")
        
        # 示例演示
        example_frame = tk.LabelFrame(main_frame, text="格式示例", padx=10, pady=10)
        example_frame.pack(fill="both", expand=True, pady=5)
        
        examples = [
            ("300x200", "设置大小为 300x200"),
            ("+0+0", "定位到屏幕左上角"),
            ("+100+100", "定位到 (100, 100)"),
            ("300x200+150+150", "大小 300x200,位置 (150, 150)"),
            ("-0+0", "定位到屏幕右上角"),
            ("+0-0", "定位到屏幕左下角"),
            ("-0-0", "定位到屏幕右下角"),
        ]
        
        for i, (geometry, description) in enumerate(examples):
            frame = tk.Frame(example_frame)
            frame.pack(fill="x", pady=2)
            
            tk.Label(frame, text=geometry, font=("Courier", 10), 
                    width=15, anchor="w").pack(side="left")
            tk.Label(frame, text=description, anchor="w").pack(side="left", padx=10)
            
            tk.Button(frame, text="应用", 
                     command=lambda g=geometry: self.apply_example(g)).pack(side="right")
        
        # 特殊功能
        special_frame = tk.LabelFrame(main_frame, text="特殊定位功能", padx=10, pady=10)
        special_frame.pack(fill="x", pady=5)
        
        btn_frame = tk.Frame(special_frame)
        btn_frame.pack()
        
        tk.Button(btn_frame, text="居中显示", 
                 command=self.center_example).pack(side="left", padx=5)
        tk.Button(btn_frame, text右上角", 
                 command=self.top_right_example).pack(side="left", padx=5)
        tk.Button(btn_frame, text="右下角", 
                 command=self.bottom_right_example).pack(side="left", padx=5)
        tk.Button(btn_frame, text="左下角", 
                 command=self.bottom_left_example).pack(side="left", padx=5)
    
    def apply_example(self, geometry):
        """应用示例几何设置"""
        self.root.geometry(geometry)
    
    def center_example(self):
        """居中示例"""
        self.root.geometry("300x200")
        self.center_window()
    
    def top_right_example(self):
        """右上角示例"""
        self.root.geometry("300x200-0+0")
    
    def bottom_right_example(self):
        """右下角示例"""
        self.root.geometry("300x200-0-0")
    
    def bottom_left_example(self):
        """左下角示例"""
        self.root.geometry("300x200+0-0")
    
    def center_window(self):
        """窗口居中"""
        self.root.update_idletasks()
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
        self.root.geometry(f"+{x}+{y}")

# 运行格式详解
if __name__ == "__main__":
    app = GeometryFormat()
    app.root.mainloop()

动态几何管理

import tkinter as tk
import time

class DynamicGeometry:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("动态几何管理")
        self.root.geometry("500x400+100+100")
        
        self.animation_running = False
        self.create_animation_controls()
        self.create_monitor()
        
        # 启动监控
        self.update_monitor()
    
    def create_animation_controls(self):
        """创建动画控制"""
        control_frame = tk.LabelFrame(self.root, text="几何动画", padx=10, pady=10)
        control_frame.pack(pady=10, padx=10, fill="x")
        
        # 动画类型选择
        type_frame = tk.Frame(control_frame)
        type_frame.pack(fill="x", pady=5)
        
        self.anim_type = tk.StringVar(value="resize")
        tk.Radiobutton(type_frame, text="大小变化", variable=self.anim_type, 
                      value="resize").pack(side="left")
        tk.Radiobutton(type_frame, text="位置移动", variable=self.anim_type, 
                      value="move").pack(side="left")
        tk.Radiobutton(type_frame, text="圆周运动", variable=self.anim_type, 
                      value="circle").pack(side="left")
        
        # 控制按钮
        btn_frame = tk.Frame(control_frame)
        btn_frame.pack(pady=10)
        
        tk.Button(btn_frame, text="开始动画", 
                 command=self.start_animation).pack(side="left", padx=5)
        tk.Button(btn_frame, text="停止动画", 
                 command=self.stop_animation).pack(side="left", padx=5)
        tk.Button(btn_frame, text="重置", 
                 command=self.reset_geometry).pack(side="left", padx=5)
    
    def create_monitor(self):
        """创建几何监控器"""
        monitor_frame = tk.LabelFrame(self.root, text="实时几何监控", padx=10, pady=10)
        monitor_frame.pack(pady=10, padx=10, fill="both", expand=True)
        
        self.monitor_text = tk.Text(monitor_frame, height=15, font=("Courier", 9))
        scrollbar = tk.Scrollbar(monitor_frame, command=self.monitor_text.yview)
        self.monitor_text.configure(yscrollcommand=scrollbar.set)
        
        self.monitor_text.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
    
    def start_animation(self):
        """开始动画"""
        if not self.animation_running:
            self.animation_running = True
            self.animation_step = 0
            self.animate_geometry()
    
    def stop_animation(self):
        """停止动画"""
        self.animation_running = False
    
    def reset_geometry(self):
        """重置几何设置"""
        self.stop_animation()
        self.root.geometry("500x400+100+100")
    
    def animate_geometry(self):
        """执行几何动画"""
        if not self.animation_running:
            return
        
        anim_type = self.anim_type.get()
        self.animation_step += 1
        
        if anim_type == "resize":
            # 大小变化动画
            width = 400 + int(100 * abs((self.animation_step % 60 - 30) / 30))
            height = 300 + int(100 * abs((self.animation_step % 60 - 30) / 30))
            x = self.root.winfo_x()
            y = self.root.winfo_y()
            self.root.geometry(f"{width}x{height}+{x}+{y}")
            
        elif anim_type == "move":
            # 位置移动动画
            width = 500
            height = 400
            x = 100 + int(200 * (self.animation_step % 100) / 100)
            y = 100 + int(200 * abs((self.animation_step % 60 - 30) / 30))
            self.root.geometry(f"{width}x{height}+{x}+{y}")
            
        elif anim_type == "circle":
            # 圆周运动
            import math
            center_x, center_y = 400, 300
            radius = 200
            angle = math.radians(self.animation_step * 6)  # 6度每步
            
            x = center_x + int(radius * math.cos(angle))
            y = center_y + int(radius * math.sin(angle))
            self.root.geometry(f"300x200+{x}+{y}")
        
        # 继续动画
        self.root.after(50, self.animate_geometry)
    
    def update_monitor(self):
        """更新监控信息"""
        current_time = time.strftime("%H:%M:%S")
        geometry = self.root.geometry()
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        x = self.root.winfo_x()
        y = self.root.winfo_y()
        
        info = f"[{current_time}] 几何: {geometry} | 尺寸: {width}x{height} | 位置: ({x}, {y})\n"
        
        self.monitor_text.insert("end", info)
        self.monitor_text.see("end")  # 自动滚动到底部
        
        # 限制行数
        lines = self.monitor_text.get("1.0", "end").split('\n')
        if len(lines) > 50:
            self.monitor_text.delete("1.0", "2.0")
        
        # 继续监控
        self.root.after(500, self.update_monitor)

# 运行动态几何示例
if __name__ == "__main__":
    app = DynamicGeometry()
    app.root.mainloop()

关键知识点总结

  1. 基本格式"宽度x高度±X±Y"
  2. 只设置大小"400x300"
  3. 只设置位置"+100+50"
  4. 负值定位: 从右边或底部计算位置
  5. 获取信息:
  • winfo_width()winfo_height() - 实际尺寸
  • winfo_x()winfo_y() - 位置坐标
  1. 屏幕信息winfo_screenwidth()winfo_screenheight()

Geometry 设置是 Tkinter 窗口管理的基础,合理使用可以创建出布局精美的应用程序界面。