介绍
我正在尝试在python中使用tkinter创建一个GUI应用程序,该应用程序具有2个相互关联的框架。通常的想法是创建一个角色选择菜单(如游戏中一样)。一切都进行得很好,直到达到更改不同类中的按钮文本的程度为止。
目标
由类A表示的第一帧将是应用程序的主页,并且应该在屏幕上显示10个按钮。
仅当单击A类中的任何按钮时,才会向用户显示由B类代表的第二帧。
B类应显示按钮列表。单击任何B类按钮时,必须将单击该按钮的文本传递给A类按钮的文本。
项目详情
此应用程序应该像游戏角色选择菜单一样工作。试想一下,我们通常会看到框架之间的这种交互方式。
有一个屏幕显示每个游戏的可能玩家数量(在此应用程序中,类A的按钮将代表这一点),并且有一个屏幕显示所有可供选择的角色(类B的按钮) );
在A类框架中,将有播放器选项:“播放器1,播放器2,播放器3 ...”。因此,当单击这些按钮之一(播放器1,播放器2,播放器3 ...)时,应显示所有字符的窗口(类B);
当选择(在B类按钮中的一个通过点击)所需的字符,所选择的字符必须被传递到主屏幕和上作为我不使用的图像但在A类中选择的按钮上显示,欲表示按钮文字中的字符;
因此,如果我单击主屏幕上的“ Player 1”选项,然后在选择屏幕上选择“ Character 4”,则“ Player 1”的文本应在主屏幕上更改为“ Character 4”,依此类推上;
通用代码
我对如何构建该程序并详细说明了我希望它如何工作进行了通用表示。
import tkinter as tk
# Creates the main window
class A(tk.Frame):
"""The class A frame is the main page of the application,
when running the program, it will be the first thing shown to the user."""
def __init__(self, master):
tk.Frame.__init__(self, master)
self.bt_identities_a = [] # this list will be used to save the identities of each button created in class A
# Creates multiple buttons
for i in range(10):
self.bt_a = tk.Button(self, text=f"Player A{i}", command=lambda x=i: self.open_window_of_class_b(x))
self.bt_a.grid()
self.bt_identities_a.append(self.bt_a) # adds the button identity to the list
def open_window_of_class_b(self, n):
"""This is the method responsible for executing class B
and for recognizing which button was clicked in class A
All actions to be performed by the buttons in class B
from now on must be associated with exactly that one
button that was clicked in class A.
"""
# Run class B
B()
# get the button id that was clicked
bt_id = self.bt_identities_a[n]
...
# Creates the secondary window
class B(tk.Toplevel):
"""The class B frame is a secondary page that will only be opened if one of the Class A buttons is clicked."""
def __init__(self):
tk.Toplevel.__init__(self)
self.bt_identities_b = [] # this list will be used to save the identities of each button created in class B
# Creates multiple buttons
for j in range(10):
self.bt_b = tk.Button(self, text=f"Character B{j}",
command=lambda x=j: self.changes_the_text_of_a_button_in_class_a(x))
self.bt_b.grid()
self.bt_identities_b.append(self.bt_b) # adds the button identity to the list
def changes_the_text_of_a_button_in_class_a(self, n):
"""This method should recognize which of the Class B buttons that was clicked,
take the text from this exact button and pass the text to the Class A button
that was clicked just before."""
# get the button id that was clicked
bt_id = self.bt_identities_b[n]
...
root = tk.Tk()
root.geometry("300x300")
app = A(root)
app.pack(fill="both", expand=True)
app.mainloop()
我的真实代码
如果需要的话,这是我到目前为止从我的应用程序获得的完整代码。
import tkinter as tk
from itertools import product
# Creating main page
class MainApplication(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
# produce the set of coordinates of the main page buttons
self.row_amount = 2
self.column_amount = 5
self.main_positions = product(range(self.row_amount), range(self.column_amount))
self.main_buttons_identities = []
# Creating main page header
self.lb = tk.Label(self, width=111, height=4, bg="#2c3e50", text="Champions", fg="white", font=50,
justify=tk.CENTER)
self.lb.grid(row=0, column=0, columnspan=5, pady=(0, 50), sticky="snew")
# Creating Done button
self.button = tk.Button(self, width=30, height=3, bg="#2c3e50", relief=tk.RIDGE, text="Done",
fg="white", font=20, command=root.destroy)
self.button.grid(row=3, columnspan=5, pady=(0, 150))
# Creating multiple buttons
for i, item in enumerate(self.main_positions):
self.button_main = tk.Button(self, width=16, height=8, bg="#2c3e50", relief=tk.RIDGE, fg="white",
justify=tk.CENTER, text=f"Champion {i +1}",
command=lambda c=i: [ChampionWindow(), self.clicked_main(c)])
self.button_main.grid(row=item[0] + 1, column=item[1], pady=(0, 50))
self.main_buttons_identities.append(self.button_main)
def clicked_main(self, current_index):
current = self.main_buttons_identities[current_index]
print(current["text"])
# Creating champion select window
class ChampionWindow(tk.Toplevel):
def __init__(self, *args, **kwargs):
tk.Toplevel.__init__(self, *args, **kwargs)
# produce the set of coordinates of the char selection page buttons
self.row_amount = 30
self.column_amount = 5
self.champion_position = product(range(self.row_amount), range(self.column_amount))
self.champions_buttons_identities = []
# scroll bar
self.ch_canvas = tk.Canvas(self, bg="blue", width=470, height=500)
self.ch_frame = tk.Frame(self.ch_canvas, bg="#273c75")
self.vscrollbar = tk.Scrollbar(self, orient="vertical", command=self.ch_canvas.yview)
self.ch_canvas.configure(yscrollcommand=self.vscrollbar.set)
self.ch_canvas.grid(sticky="snew")
self.vscrollbar.grid(row=0, column=3, sticky="sn")
self.ch_canvas.create_window((0, 0), window=self.ch_frame, anchor="nw")
self.ch_frame.bind("<Configure>", self.scroll)
# Creating multiple buttons
for i, itm in enumerate(self.champion_position):
self.button_champion = tk.Button(self.ch_frame, width=12, height=6, bg="#2c3e50",
relief=tk.RIDGE, fg="white", justify=tk.CENTER,
command=lambda c=i: [self.clicked_champion(c), self.destroy()],
text=f"Pick champ {i+1}")
self.button_champion.grid(row=itm[0], column=itm[1])
self.champions_buttons_identities.append(self.button_champion)
def scroll(self, ch_event):
self.ch_canvas.configure(scrollregion=self.ch_canvas.bbox("all"))
def clicked_champion(self, champ_index):
champ = self.champions_buttons_identities[champ_index]
print(champ["text"])
if __name__ == "__main__":
root = tk.Tk()
root.title("Champion")
root.geometry("1000x570+450+200")
root.resizable(False, False)
app = MainApplication(root)
app.configure(background="#34495e")
app.pack(fill="both", expand=True)
app.mainloop()
GUI图像
为了更容易理解我要做什么,我将链接主窗口和字符选择窗口中的图像。
主窗口(显示播放器)
字符选择窗口(显示可用字符)
您可以简单地将clicked按钮的实例传递给ChampionWindow
类:
class MainApplication(tk.Frame):
def __init__(self, master, *args, **kwargs):
...
# Creating multiple buttons
for i, item in enumerate(self.main_positions):
button_main = tk.Button(self, width=16, height=8, bg="#2c3e50", relief=tk.RIDGE, fg="white",
justify=tk.CENTER, text=f"Champion {i +1}",
command=lambda c=i: self.clicked_main(c))
button_main.grid(row=item[0] + 1, column=item[1], pady=(0, 50))
self.main_buttons_identities.append(button_main)
def clicked_main(self, current_index):
current = self.main_buttons_identities[current_index]
print(current["text"])
ChampionWindow(current) # pass clicked button to ChampionWindow
然后,在ChampionWindow
单击某个按钮的按钮之一时更新其中的传递的文本:
# Creating champion select window
class ChampionWindow(tk.Toplevel):
def __init__(self, button, *args, **kwargs):
tk.Toplevel.__init__(self, *args, **kwargs)
self.button = button # save the button for later use
...
def clicked_champion(self, champ_index):
champ = self.champions_buttons_identities[champ_index]
print(champ["text"])
self.button["text"] = champ["text"] # update passed button
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句