【问题标题】:Delete the canvas in Pysimplegui在 Pysimplegui 中删除画布
【发布时间】:2021-12-08 12:32:14
【问题描述】:

我是编程新手,我试图在这里找到相关问题的解决方案,但它让我无处可去,我现在开始用头撞墙。

问题如下:我需要为一个大学项目创建一个带有 GUI 的程序。这个想法是我从大数据集中获取数据,然后用户可以输入国家名称,所选国家的数据将形成一个图。我有 2 个要使用不同数据的图,每种类型都有 2 个单独的按钮:

```
    #function that graphs the first plot
def vaccine_cases_plot(vaccine_list, cases_list):
plt.scatter(
    y = vaccine_list,
    x = cases_list)
plt.ylabel("Percentage of fully vaccinated people")
plt.xlabel("Number of new cases per Million as of 01.12.2021")
plt.ioff()
return plt.gcf()

   #function that graphs the second plot
def vaccine_gdp_plot(vaccine_list, gdp_list):
plt.scatter(
    y = vaccine_list,
    x = gdp_list)
plt.ylabel("Percentage of fully vaccinated people")
plt.xlabel("GDP per capita in 2019(USD)")
plt.ioff()
return plt.gcf()

    #helper function to display plot on canvas   
    plt.gcf().subplots_adjust(left=0.15)
    matplotlib.use("TkAgg")
    def draw_figure(canvas, figure):
       figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
       figure_canvas_agg.get_tk_widget().pack(side="right", fill="both", expand=1)
       figure_canvas_agg.draw()
       return figure_canvas_agg

   #empty lists where data for countries, selected by user, will be stored 
   vaccines_to_plot = []
   cases_to_plot = []
   gdp_to_plot = []


    #pysimplegui interface layout
    interface_column = [
[
    sg.Text("Select a countries you would like to see on the graph:", font=("Arial", 14))
],
[
    sg.In(size =(25, 1), enable_events=True, key="country_selected"),
    sg.Button("Add country")
],
[
    sg.Text("Selected countries are: ", size=(20,10), font=("Arial", 14), key = "selected_countries")
],
[
    sg.Button("Clear selection", key = "clear")
],
[
    sg.Button("GDP vs. Vaccination rate", key = "gdp_vaccine"),
    sg.Button("Vaccination vs. new cases per day", key = "vaccine_cases")
   
],
[
    sg.Text(font=("Arial", 12), key="warning_message")
]
     ]

   graph_column = [
[sg.Canvas(size=(500,500), key="canvas")]

]

layout = [
[
    sg.Column(interface_column),
    sg.VSeperator(),
    sg.Column(graph_column),
]
]
window = sg.Window("Vaxxi-nation", layout, margins=(50, 50), finalize=True)
canv = window["canvas"].TKCanvas

#main loop
while True:
    event, values = window.read()

    if event == sg.WIN_CLOSED:
        break

#User inputs name of the country, respective data goes to the lists, name of the country is 
 displayed
    if event == "Add country":
        selected_country = values["country_selected"]
    if selected_country in new_cases_per_m and selected_country in fully_vaccinated and 
  selected_country in countries_gdp:
        try:
            vaccines_to_plot.append(float(fully_vaccinated[selected_country]))
            cases_to_plot.append(float(new_cases_per_m[selected_country]))
            gdp_to_plot.append(round(float(countries_gdp[selected_country]), 2))
            display = window["selected_countries"]
            display.update(display.get() + selected_country + '\n')
        except:
            window["warning_message"].update("One of the datasets doesn't have data for this country")
    else:
        window["warning_message"].update("One of the datasets doesn't have data for this country")

#Button to graph the first plot
    if event == "gdp_vaccine":
        draw_figure(canv, vaccine_gdp_plot(vaccines_to_plot, gdp_to_plot))
#button to graph the second plot
    if event == "vaccine_cases":
        draw_figure(canv, vaccine_cases_plot(vaccines_to_plot, cases_to_plot))
    if event == "clear":
        display.update('')
        vaccines_to_plot = []
        cases_to_plot = []
        gdp_to_plot = []
        
event, values = window.read()      
window.close()
```

现在,当我第一次按下其中一个按钮时,绘图会按照我想要的方式显示在画布上。但是,如果我想显示另一个图,而不是重写前一个图,它会创建一个新图,用它替换旧图,并在右侧制作一个新图的副本。

我想要的是,当按下新按钮(或再次按下旧按钮)时,新图应替换旧图。我寻找了很多方法来做到这一点,但我觉得应该有一些简单而明显的东西,我在这里看不到。我尝试并放弃的最后一件事是每次按下按钮时删除画布,然后重新绘制它。我试着这样做:

#first button is clicked
    if event == "gdp_vaccine":
        canv.TKCanvas.delete("all")
        draw_figure(canv, vaccine_gdp_plot(vaccines_to_plot, gdp_to_plot))

但它实际上什么也没做(尽管没有引发错误)。我将非常感谢这里的任何帮助,因为我已经为此苦苦挣扎了一整天,而且这件事不可能那么复杂。

【问题讨论】:

  • PySimpleGUI GitHub 问题是提出问题而不是敲你脑袋的好地方。正如文件所说,“不要沉默地受苦”。谢天谢地,Jason 来到了这里,并在 GitHub 上负责管理问题。随着时间的推移,Matplotlib 实现从 Canvas 转移到 Image 和 Graph 元素。有 16 个演示程序展示了将 PySimpleGUI 与 Matplotlib 集成的各种方法。通常,演示越新,随着项目的发展和学习,效果就越好。

标签: python matplotlib pysimplegui


【解决方案1】:

以下代码只是删除sg.Canvas中的所有项目,而不是sg.Canvas中matplotlib图形的画布。

canv.TKCanvas.delete("all")

阅读您冗长且不完整的代码并不容易。

这是我演示两个图表并一次又一次重绘的代码,也许它可以帮助你。

import math

from matplotlib import use as use_agg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import PySimpleGUI as sg

def pack_figure(graph, figure):
    canvas = FigureCanvasTkAgg(figure, graph.Widget)
    plot_widget = canvas.get_tk_widget()
    plot_widget.pack(side='top', fill='both', expand=1)
    return plot_widget

def plot_figure(index, theta):
    fig = plt.figure(index)         # Active an existing figure
    ax = plt.gca()                  # Get the current axes
    x = [degree for degree in range(1080)]
    y = [math.sin((degree+theta)/180*math.pi) for degree in range(1080)]
    ax.cla()                        # Clear the current axes
    ax.set_title(f"Sensor Data {index}")
    ax.set_xlabel("X axis")
    ax.set_ylabel("Y axis")
    ax.set_xscale('log')
    ax.grid()
    plt.plot(x, y)                  # Plot y versus x as lines and/or markers
    fig.canvas.draw()               # Rendor figure into canvas

# Use Tkinter Agg
use_agg('TkAgg')

layout = [[sg.Graph((640, 480), (0, 0), (640, 480), key='Graph1'), sg.Graph((640, 480), (0, 0), (640, 480), key='Graph2')]]
window = sg.Window('Matplotlib', layout, finalize=True)


# Initial
graph1 = window['Graph1']
graph2 = window['Graph2']
plt.ioff()                          # Turn the interactive mode off
fig1 = plt.figure(1)                # Create a new figure
ax1 = plt.subplot(111)              # Add a subplot to the current figure.
fig2 = plt.figure(2)                # Create a new figure
ax2 = plt.subplot(111)              # Add a subplot to the current figure.
pack_figure(graph1, fig1)           # Pack figure under graph
pack_figure(graph2, fig2)
theta1 = 0                          # theta for fig1
theta2 = 90                         # theta for fig2
plot_figure(1, theta1)
plot_figure(2, theta2)

while True:

    event, values = window.read(timeout=10)

    if event == sg.WINDOW_CLOSED:
        break
    elif event == sg.TIMEOUT_EVENT:
        theta1 = (theta1 + 40) % 360
        plot_figure(1, theta1)
        theta2 = (theta2 + 40) % 260
        plot_figure(2, theta2)

window.close()

【讨论】:

  • 对代码带来的不便深表歉意 - 我会尽量让它更简洁。我将绘图显示更改为 sg.Graph 而不是 sg.Canvas,并按照您提供的示例进行操作 - 它有效。非常感谢你!再次抱歉提出一个更愚蠢的问题 - 我的大脑正在融化,现在它被保存了,所以我想,再次感谢你!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 2016-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多