Python tkinter 从不同的类和框架访问数据

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

我对Python编程比较陌生,最终想为我们部门创建计算GUI。因此我开始使用 tkinter 或 customtkinter。我的想法是拥有一个 Main.py 程序来配置应用程序的总体结构。然后我想创建一些具有不同类的子文件A和B来配置App的子框架。因此,代码应该更清晰易懂,其他同事也可以更轻松地实现自己的框架/想法。

问题: 我在B类中有一个在A类中需要的输入框。作为文件A的计算方法中的一个简单示例,我想总结value_1和value_2的条目,但如何访问A类中的value_2?

A.py

import customtkinter
import tkinter
from B import *

class A:
    def __init__(self, root, frame):
        self.root = root
        self.frame = frame


        self.value_1_label = customtkinter.CTkLabel(self.frame, text="Value_1").place(x=20, y=150)
        self.value_1_entry = customtkinter.CTkEntry(self.frame)
        self.value_1_entry.place(x=120, y=150)

        self.berechnung_button = customtkinter.CTkButton(self.frame, text="Calculate", fg_color="#204A94", command=self.calculate)
        self.berechnung_button.place(x=20, y=700)

    def calculate(self):
        pass

B.py


import customtkinter
import tkinter

class B:
    def __init__(self, root, frame):

        self.root = root
        self.frame = frame

        self.value_2_label = customtkinter.CTkLabel(self.frame, text="Value_2").place(x=20, y=170)
        self.value_2_entry = customtkinter.CTkEntry(self.frame)
        self.value_2_entry.place(x=120, y=170)

主要.py

import customtkinter
import tkinter
from tkinter import *
from A import *
from B import *

class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        self.title("Main")
        self.geometry("1024x768")
        self.grid_rowconfigure(0,weight=1)
        self.grid_columnconfigure(1, weight=1)

        self.navigation_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color="#204A94")
        self.navigation_frame.grid(row=0, column=0, sticky="nsew")
        self.navigation_frame.grid_rowconfigure(3, weight=1)

        self.main_button = customtkinter.CTkButton(self.navigation_frame, text="Home",command=self.main_button_event)
        self.main_button.grid(row=1, column=0, sticky="ew")

        self.main_button = customtkinter.CTkButton(self.navigation_frame, text="A",command=self.A_button_event)
        self.main_button.grid(row=1, column=0, sticky="ew")

        self.general_button = customtkinter.CTkButton(self.navigation_frame, text="B",command=self.B_button_event)
        self.general_button.grid(row=2, column=0, sticky="ew")

        self.main_frame = customtkinter.CTkFrame(self, fg_color="transparent", corner_radius=0)
        self.main_frame.grid_columnconfigure(0, weight=1)

        self.A_frame = customtkinter.CTkFrame(self, fg_color="transparent", corner_radius=0)
        self.A_frame.grid_columnconfigure(0, weight=1)
        self.cl_A = A(self, self.A_frame)

        self.B_frame = customtkinter.CTkFrame(self, fg_color="transparent", corner_radius=0)
        self.B_frame.grid_columnconfigure(0, weight=1)
        self.cl_B = B(self, self.B_frame)


    def select_frame_by_name(self, name):
        if name == "main":
            self.main_frame.grid(row=0, column=1, sticky="nsew")
        else:
            self.main_frame.grid_forget()
        if name == "A":
            self.A_frame.grid(row=0, column=1, sticky="nsew")
        else:
            self.A_frame.grid_forget()
        if name == "B":
            self.B_frame.grid(row=0, column=1, sticky="nsew")
        else:
            self.B_frame.grid_forget()


    def main_button_event(self):
        self.select_frame_by_name("main")

    def A_button_event(self):
        self.select_frame_by_name("A")

    def B_button_event(self):
        self.select_frame_by_name("B")


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

我尝试在文件 A 中创建一个类实例: self.cl_B = B(root, frame) ,然后使用 value_2 = self.cl_B.value_2_entry.get() 但类实例只是向我显示文件 B 中的框架A.

python tkinter customtkinter
1个回答
0
投票

有很多方法可以实现你想要做的事情。但在此之前,我们必须看看其他事情。

在您的主文件中,您似乎已经设置了一个过程,当用户按下按钮时,会出现一个特定的框架。它看起来很像 Notebook widget 的工作原理。所以我将在我的示例中使用它。

其他更改:我们将使 GUI 元素也执行计算,而通常最好将这些角色分开。这样您就可以独立地更改计算的接口。在您的示例中,您的实例创建了 GUI,但在我的回答中,为了简化代码,我们将把它放在一起。

(我知道对于很多人来说组合比继承更好,但有时我发现继承没那么麻烦)

A.py

import tkinter as tk
import tkinter.ttk as ttk

class A(ttk.Frame):

    def __init__(self, master, b_variable: tk.IntVar, *args, **kwargs) -> None:
        super().__init__(master, *args, **kwargs)

        self.b_variable = b_variable

        value_1_label = ttk.Label(self, text="Value_1")
        self.value_1 = tk.IntVar()
        value_1_entry = ttk.Entry(self, textvariable=self.value_1)
        computation_button = ttk.Button(self, text="Calculate", command=self.calculate)

        self.value_2 = tk.StringVar()
        value_2_display = ttk.Entry(self, state="readonly", textvariable=self.value_2)
        self.value_2.set('No computation yet')

        value_1_label.grid(row=0, column=0, padx=5, pady=5)
        value_1_entry.grid(row=0, column=1, padx=5, pady=5, sticky="w")
        computation_button.grid(row=1, column=0, padx=5, pady=5)
        value_2_display.grid(row=1, column=1, padx=5, pady=5, sticky="ew")

        self.columnconfigure(1, weight=1)

    def calculate(self) -> None:
        # Whatever the computation you want to do is here
        self.value_2.set(f"Here is the computation of {self.value_1.get()} and {self.b_variable.get()}")

B.py

import tkinter as tk
import tkinter.ttk as ttk

class B(ttk.Frame):

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

        value_2_label = ttk.Label(self, text="Value_2")
        self.value_2 = tk.IntVar()
        value_2_entry = ttk.Entry(self, textvariable=self.value_2)

        value_2_label.grid(row=0, column=0, padx=5, pady=5)
        value_2_entry.grid(row=0, column=1, padx=5, pady=5)

主要.py

import tkinter as tk
import tkinter.ttk as ttk

import A
import B

class Main(ttk.Notebook):

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

        home_page = ttk.Frame(self)
        page_b = B.B(self)
        page_a = A.A(self, page_b.value_2)

        self.add(home_page, text="Home")
        self.add(page_a, text="A")
        self.add(page_b, text="B")

class App(tk.Tk):

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

        self.title("Main")
        
        main_frame = Main(self)
        main_frame.grid(row=0, column=0, sticky="nsew")
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

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

那么我们在这里做了什么:

  • 我们使用 Tk 的变量类来保存不同条目的值
  • 当我们创建
    A
    类的实例时,我们在
    B
    类中提供变量类的实例。每当
    A
    的实例需要进行计算时,它就可以从该变量对象中检索值。
© www.soinside.com 2019 - 2024. All rights reserved.