python-3.x Tkinter单选按钮在顶层窗口中无法正常工作

yws3nbqq  于 2023-04-22  发布在  Python
关注(0)|答案(1)|浏览(146)

我正在用Python中的Tkinter构建一个GUI,我遇到了单选按钮的问题。我在LabelFrame小部件中有两个单选按钮,我使用StringVar来跟踪所选值。然而,当我运行程序时,两个单选按钮最初都未选中,但几秒钟后都被选中。此外,对所选值的更改并不总是反映在GUI中。
下面是我的代码:

import tkinter as tk

class MenuSettings:
    def __init__(self, parent, settings):
        
        window = tk.Toplevel(parent)
        window.title("settings")

        database_frame = tk.LabelFrame(
            window, text="choose drive: ", font=("Arial", 12))
        database_frame.pack(fill=tk.X, padx=10, pady=10)

        database_var = tk.StringVar(value=settings.db_path)

        database_radio_g = tk.Radiobutton(
            database_frame, text="G:", value="PATH_G", variable=database_var, 
            font=("Arial", 12))
        database_radio_g.pack(side="left", padx=10)

        database_radio_server = tk.Radiobutton(
            database_frame, text="Server", value="PATH_SERVER", variable=database_var, 
            font=("Arial", 12))
        database_radio_server.pack(side="left", padx=10)

        #-----------------------------------------------------------------------------
        # following code is necessary
        #-----------------------------------------------------------------------------
        #def on_database_var_changed(*args):
        #    print('database_var changed:', database_var.get())

        #database_var.trace('w', on_database_var_changed)       

from wotan.CLS import cls

settings = cls.Settings.getInstance()

class Application(tk.Tk):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.title("Application")
        self.configure(background='black')

        self._show_menu_settings()

    def _show_menu_settings(self):
        settings_window=MenuSettings(self, settings)


def main():
  app = Application()
  app.mainloop()

if __name__ == '__main__':
    main()

settings是一个单例类,用于从本地存储的文本文件中读取一些变量。Trace语句(包括函数)在类MenuSettings中被注解掉
我已经尝试了几种方法,比如为单选按钮设置value选项,删除代码的其他部分以隔离问题,使用window.update()和window.update_idletasks(),但似乎都不起作用。
我发现的唯一解决方案是添加一个跟踪函数来打印StringVar,这对于应用程序来说不是一个理想的解决方案。有人有任何建议来解决这个问题吗?

hlswsv35

hlswsv351#

您需要在database_var(在MenuSettings中)和settings_window(在Application中)上使用示例变量来避免垃圾回收:

class MenuSettings:
    def __init__(self, parent, settings):
        ...
        # use instance variable
        self.database_var = tk.StringVar(value=settings.db_path)

        database_radio_g = tk.Radiobutton(
            database_frame, text="G:", value="PATH_G", variable=self.database_var,
            font=("Arial", 12))
        database_radio_g.pack(side="left", padx=10)

        database_radio_server = tk.Radiobutton(
            database_frame, text="Server", value="PATH_SERVER", variable=self.database_var,
            font=("Arial", 12))
        database_radio_server.pack(side="left", padx=10)

...

class Application(tk.Tk):
    ...

    def _show_menu_settings(self):
        # use instance variable
        self.settings_window = MenuSettings(self, settings)
...

我建议MenuSettings继承tk.Toplevel,这样就不需要在settings_window上使用示例变量。

相关问题