使用 Tkinter Notebooks 时,如何将一个选项卡中的 StringVar 用于另一个选项卡对象,同时允许 f 字符串使用和实时更新

问题描述 投票:0回答:1

我正在创建一个小项目来帮助创建 BG3 mods。我的最终目标是拥有多个选项卡,我可以在其中输入数据,并在我保存时导出文件。

我能够毫无问题地执行保存和选项卡创建。我想要发生的是在 ConfigTab 中输入 mod 将创建的自定义类的名称(如果有帮助的话,这是用于 DND 的)。然后在 LocalizationTab 中我希望有一个带有输入字段的标签。标签将从 ConfigTab 中读取类名称并显示为类名称描述:;所以在配置中我会输入战士,在本地化中它将显示战士描述:

我可以调用 StringVar 进行实时更新,但这不允许我使用 f 字符串或其他串联功能。如果我使用 get() 方法,我只会收到在创建窗口时设置为类名的值。因此,如果我使用 classname.set("Warrior"),classname.get() 将返回一个字符串,我可以使用 f-string,并且可以让它显示 Warrior Description。但是,get() 是一次性调用,如果我更改配置选项卡中的数据,则不会更新。

下面是一个准系统的实现,展示了我目前的总体思路。最终项目中将引用多个字段,而不仅仅是类名字段。

主程序.py

import tkinter as tk
import tkinter.ttk as ttk

from ClassConfigTab import ClassConfigTab
from LocalizationTab import LocalizationTab

# Create tkinter window
root = tk.Tk()
root.title("BG3 Mod Creation Tool")
root.geometry("650x150")

# Create notebook
nb = ttk.Notebook(root)
config_tab = ClassConfigTab(nb)
localization_tab = LocalizationTab(config_tab, nb)
nb.add(config_tab, text='Configure class')
nb.add(localization_tab, text='Localization')

# Load window
nb.pack(expand=1, fill="both")
root.mainloop()

ClassConfigTab.py

import tkinter as tk
from tkinter import ttk


class ClassConfigTab(ttk.Frame):
    """Content for the required tab for creating a class mod."""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.classname = tk.StringVar(name="classname")
        self.classname.set("Warrior")

        self.place_widgets()

    def place_widgets(self):
        entry_classname = ttk.Entry(self, width=50, textvariable=self.classname)

        # Place widgets
        entry_classname.grid(column=0,
                             row=1,
                             padx=10,
                             pady=0,
                             sticky=tk.W)

LocalizationTab.py

import tkinter as tk
from tkinter import ttk


class LocalizationTab(ttk.Frame):
    """This will contain what is going to be shown on the localization tab."""

    def __init__(self, config_tab, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # This updates automatically but can't use f-string.
        self.label_main_name = ttk.Label(self,
                                         textvariable=config_tab.classname)
        # This loads the StringVar value on window creation, but does not auto update.
        self.label_main_name_two = ttk.Label(self,
                                             text=config_tab.classname.get())

        self.place_widgets()

    def place_widgets(self):
        self.label_main_name.grid(column=0,
                                  row=0,
                                  padx=10,
                                  pady=5,
                                  sticky=tk.W)
        self.label_main_name_two.grid(column=1,
                                      row=0,
                                      padx=10,
                                      pady=5,
                                      sticky=tk.W)

我在 StackOverflow 上进行了搜索,发现了其他类似的问题。他们引用了使用过的跟踪、绑定事件,甚至只是有一个按下即可刷新数据的按钮。

我尝试过跟踪和绑定,但没有运气。也许我实现它的方式不正确,我很抱歉,但我的文件中没有代码来显示我的尝试。

python tkinter label tkinter-entry
1个回答
0
投票

正如您所说,您可以在 tkinter 变量上使用

trace()

class LocalizationTab(ttk.Frame):
    """This will contain what is going to be shown on the localization tab."""

    def __init__(self, config_tab, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.label_main_name = ttk.Label(self)
        # call self.update_label() whenever the variable is updated
        config_tab.classname.trace_add("write", self.update_label)

        self.place_widgets()
        self.update_label()  # update label initially

    def place_widgets(self):
        self.label_main_name.grid(column=0,
                                  row=0,
                                  padx=10,
                                  pady=5,
                                  sticky=tk.W)

    def update_label(self, *args):
        self.label_main_name["text"] = f"{config_tab.classname.get()} Description:"
© www.soinside.com 2019 - 2024. All rights reserved.