我对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.
有很多方法可以实现你想要做的事情。但在此之前,我们必须看看其他事情。
在您的主文件中,您似乎已经设置了一个过程,当用户按下按钮时,会出现一个特定的框架。它看起来很像 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()
那么我们在这里做了什么:
A
类的实例时,我们在B
类中提供变量类的实例。每当 A
的实例需要进行计算时,它就可以从该变量对象中检索值。