python - 如何在 Tkinter 窗口中绘制 Matplotlib 图?
问题描述
我需要你的一些想法来尝试自己实施。我有一个Tk()
带有 2 个选项卡的主窗口,但我现在将专注于一个(group_stage_frame):
root = tk.Tk()
my_notebook = ttk.Notebook(root)
my_notebook.pack()
group_stage_frame = Frame(my_notebook, width=1080, height=1080)
knockout_stage_frame = Frame(my_notebook, width=1080, height=1080)
group_stage_frame.pack(fill="both", expand=1)
knockout_stage_frame.pack(fill="both", expand=1)
my_notebook.add(group_stage_frame, text="GROUP STAGE")
my_notebook.add(knockout_stage_frame, text="KNOCKOUT STAGE")
group_A_label = Label(group_stage_frame, text="GROUP A").grid(row=0, column=0)
buttonA1 = Button(group_stage_frame, text="Russia 5-0 Saudi Arabia", width=25, command=A1window).grid(row=1, column=0)
root.mainloop()
按钮A1功能:
def A1window():
def showPlayersA1():
heat_pass_map(df, clickedRussia.get())
heat_pass_map(df, clickedArabia.get())
rootA1 = tk.Toplevel()
rootA1.title("Russia 5-0 Saudi Arabia")
#events
with open(r'C:\Users\Catalin\Desktop\WorldCupData\data\events\7525.json', encoding = 'utf-8') as f:
data = json.load(f)
df = pd.json_normalize(data, sep = "_")
#lineup
with open(r'C:\Users\Catalin\Desktop\WorldCupData\data\lineups\7525.json', encoding = 'utf-8') as f:
lineup = json.load(f)
#Dropdown menu Russia lineup
clickedRussia = tk.StringVar()
clickedRussia.set("Choose any Russian player")
options_list_Russia = []
for i in range(14):
options_list_Russia.append(lineup[0]['lineup'][i]['player_name'])
dropRussia = tk.OptionMenu(rootA1, clickedRussia, *options_list_Russia)
dropRussia.config(width=50)
dropRussia.pack(side = "top", anchor = CENTER)
#Dropdown menu Saudi Arabia lineup
clickedArabia = tk.StringVar()
clickedArabia.set("Choose any Saudi Arabia player")
options_list_Arabia = []
for i in range(14):
options_list_Arabia.append(lineup[1]['lineup'][i]['player_name'])
dropArabia = tk.OptionMenu(rootA1, clickedArabia, *options_list_Arabia)
dropArabia.config(width=50)
dropArabia.pack(side = "top", anchor = CENTER)
buttonCompare = tk.Button(rootA1, text="COMPARE", command=showPlayersA1).pack(side = "top", anchor = CENTER)
我正在为每个国家/地区的选定玩家绘制热图和传球地图以比较图表:
def draw_pitch(ax):
# size of the pitch is 120, 80
#Create figure
#Pitch Outline & Centre Line
plt.plot([0,0],[0,80], color="black")
plt.plot([0,120],[80,80], color="black")
plt.plot([120,120],[80,0], color="black")
plt.plot([120,0],[0,0], color="black")
plt.plot([60,60],[0,80], color="black")
#Left Penalty Area
plt.plot([14.6,14.6],[57.8,22.2],color="black")
plt.plot([0,14.6],[57.8,57.8],color="black")
plt.plot([0,14.6],[22.2,22.2],color="black")
#Right Penalty Area
plt.plot([120,105.4],[57.8,57.8],color="black")
plt.plot([105.4,105.4],[57.8,22.5],color="black")
plt.plot([120, 105.4],[22.5,22.5],color="black")
#Left 6-yard Box
plt.plot([0,4.9],[48,48],color="black")
plt.plot([4.9,4.9],[48,32],color="black")
plt.plot([0,4.9],[32,32],color="black")
#Right 6-yard Box
plt.plot([120,115.1],[48,48],color="black")
plt.plot([115.1,115.1],[48,32],color="black")
plt.plot([120,115.1],[32,32],color="black")
#Prepare Circles
centreCircle = plt.Circle((60,40),8.1,color="black",fill=False)
centreSpot = plt.Circle((60,40),0.71,color="black")
leftPenSpot = plt.Circle((9.7,40),0.71,color="black")
rightPenSpot = plt.Circle((110.3,40),0.71,color="black")
#Draw Circles
ax.add_patch(centreCircle)
ax.add_patch(centreSpot)
ax.add_patch(leftPenSpot)
ax.add_patch(rightPenSpot)
#Prepare Arcs
# arguments for arc
# x, y coordinate of centerpoint of arc
# width, height as arc might not be circle, but oval
# angle: degree of rotation of the shape, anti-clockwise
# theta1, theta2, start and end location of arc in degree
leftArc = Arc((9.7,40),height=16.2,width=16.2,angle=0,theta1=310,theta2=50,color="black")
rightArc = Arc((110.3,40),height=16.2,width=16.2,angle=0,theta1=130,theta2=230,color="black")
#Draw Arcs
ax.add_patch(leftArc)
ax.add_patch(rightArc)
def heat_pass_map(data, player_name):
pass_data = data[(data['type_name'] == "Pass") & (data['player_name'] == player_name)]
action_data = data[(data['player_name']==player_name) & (data['type_name'] != 'Substitution')]
fig=plt.figure()
fig.set_size_inches(7, 5)
ax=fig.add_subplot(1,1,1)
draw_pitch(ax)
plt.axis('off')
#passes
for i in range(len(pass_data)):
# we also differentiate different half by different color
color = "blue" if pass_data.iloc[i]['period'] == 1 else "red"
ax.annotate("", xy = (pass_data.iloc[i]['pass_end_location'][0], pass_data.iloc[i]['pass_end_location'][1]), xycoords = 'data', xytext = (pass_data.iloc[i]['location'][0], pass_data.iloc[i]['location'][1]), textcoords = 'data', arrowprops=dict(arrowstyle="->",connectionstyle="arc3", color = color))
#heatmap
x_coord = [i[0] for i in action_data["location"]]
y_coord = [i[1] for i in action_data["location"]]
sns.kdeplot(x = x_coord, y = y_coord, shade = "True", thresh = 0, cmap = "Greens", n_levels = 10)
#create arrow legend
blue_arrow = mlines.Line2D([], [], c='blue', marker=r'$\rightarrow$', markersize=15, linestyle='None', label='First half pass')
red_arrow = mlines.Line2D([], [], c='red', marker=r'$\rightarrow$', markersize=15, linestyle='None', label='Second half pass')
plt.ylim(0, 80) # need this, otherwise kde plot will go outside
plt.xlim(0, 120)
plt.legend(handles=[blue_arrow, red_arrow], loc='upper right')
plt.title(str(player_name)+ "'s pass map")
plt.show()
所以,基本上,如果我能以某种方式将 2 个图绘制到我的 rootA1 窗口中,我想要一些想法。我阅读了有关画布小部件的信息,但我认为这并没有太大帮助,因为 rootA1(当我单击主机上的按钮时弹出的第二个框架)位于 A1window 函数中。
我想到的另一个想法是在 main 函数中创建 rootA1 并将其隐藏,直到我按下按钮。
想请教各位大佬的意见,谢谢!
解决方案
推荐阅读
- c# - 使用高级选项创建 Hive ODBC 驱动程序
- javascript - LinkButton,如何防止双击“asp:LinkButton”?或第一次单击后禁用“asp:LinkButton”
- java - Firebase 规则 - 只允许用户访问自己的数据
- python-3.6 - 我的不和谐机器人由于某种原因不断断开连接
- selenium - 如何使用 IE11 webdriver 启动 selenium 独立服务器?
- r - 在客户旅程中是否有用于接触点归因的 R 函数?
- javascript - 将内联 javascript 重写为外部函数 - 此参考
- python - nginx下带有wsgi(uwsgi)的python是否有一些小的默认缓存?
- php - 发布具有相似名称和相似值的数组
- javascript - 如何在 bootsrap 4 上添加活动和删除现有活动类崩溃