You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter OptionMenu填充USB端口名时触发‘bad screen distance’错误

解决CTkOptionMenu触发Tkinter.TclError: 'bad screen distance'错误

错误原因分析

你的代码存在几个核心问题导致报错:

  • 类方法定义缺失参数:list_uart_ports作为类内方法,未添加self参数,无法被类实例正常调用。
  • CTkOptionMenu参数传递错误:第二个参数应传入StringVar对象(self.selected_usb_port),而非调用get()获取的字符串值;且仅在无可用端口时创建组件,有端口场景下未初始化self.usb_ports_option_menu,导致后续布局代码调用未定义变量。
  • 布局管理器冲突:同时使用grid()和place()对同一组件进行布局,Tkinter不允许同一组件绑定两种几何管理器,这是触发"bad screen distance"的直接原因。
  • 父组件未定义:代码中使用self.topmenu作为OptionMenu的父容器,但未初始化该变量,应直接使用self(App继承自CTk,主窗口实例本身即可作为父容器)。

修复后的完整代码

import serial.tools.list_ports
import customtkinter as ctk

class App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.selected_usb_port = ctk.StringVar(self)
        self.usb_ports_with_dev = self.list_uart_ports()
        
        # 统一初始化CTkOptionMenu,覆盖有无端口的场景
        if self.usb_ports_with_dev:
            print("USB Ports with '/dev/':", self.usb_ports_with_dev)
            self.selected_usb_port.set(self.usb_ports_with_dev[0])
            self.usb_ports_option_menu = ctk.CTkOptionMenu(
                self, 
                variable=self.selected_usb_port, 
                values=self.usb_ports_with_dev,
                dynamic_resizing=True
            )
        else:
            self.selected_usb_port.set("No ports available")
            self.usb_ports_option_menu = ctk.CTkOptionMenu(
                self, 
                variable=self.selected_usb_port, 
                values=["No ports available"],
                dynamic_resizing=True
            )
        
        # 选择一种布局方式,示例使用place
        self.usb_ports_option_menu.place(x=525, y=25)
        # 若使用grid,需先配置网格权重,示例:
        # self.grid_rowconfigure(0, weight=1)
        # self.grid_columnconfigure(1, weight=1)
        # self.usb_ports_option_menu.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")

    def list_uart_ports(self):
        uart_ports = []
        ports = serial.tools.list_ports.comports()
        for port, desc, hwid in sorted(ports):
            if "USB" in desc:  
                if "ttyUSB" in port or "COM" in port:  
                    uart_ports.append(port)
        return uart_ports

if __name__ == "__main__":
    app = App()
    app.mainloop()

关键修复点说明

  • 给list_uart_ports添加self参数,改为类的实例方法,调用时使用self.list_uart_ports()。
  • 调整CTkOptionMenu参数:通过variable绑定StringVar对象,端口列表传入values参数(CTkOptionMenu要求用values接收选项列表,而非直接解包传参)。
  • 在if/else分支中统一初始化self.usb_ports_option_menu,避免变量未定义报错。
  • 移除冲突的布局代码,仅保留place()或grid()其中一种布局方式。
  • 将父容器改为self,确保组件正确挂载到主窗口。

内容的提问来源于stack exchange,提问作者DHARANI MOHAN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 01:22:16