python-tkinter与span-widge交互绘图和列表框

2024-03-29 09:34:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试执行以下步骤:
1插入值对列表[xmin,xmax]
2创建span对象的初始列表
三。绘制跨距并将标签写入列表框
4添加要绘制的跨距(通过onlick事件)并更新列表框
5移除和高光跨度

下面是一个示例代码:

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib.widgets import SpanSelector
import tkinter as tk
import numpy as np

class App:
     def __init__(self, master, l_val_pair):
         # Create a container
         frame = tk.Frame(master)

         # Create fields
         self.button_left = tk.Button(frame,text="Export")
         self.button_left.pack(side="left")
         self.button_right = tk.Button(frame,text="Delete", command = 
                                       lambda: self.delete(self.l_spans))
         self.button_right.pack(side="left")

         self.listbox = tk.Listbox(master)
         self.listbox.pack(side='bottom', fill=tk.X) 

         #define figure
         self.fig = Figure()
         self.ax = self.fig.add_subplot(111)

         #sample data for a line
         self.x = np.arange(0.0, 5.0, 0.01)
         self.y = np.sin(2*np.pi*self.x) + 0.5*np.random.randn(len(self.x))

         #plot line and list of spans
         self.ax.plot(self.x,self.y)

         self.l_spans = [self.ax.axes.axvspan(
                 val_pair[0],val_pair[1], facecolor='red', alpha=0.3, label=val_pair) 
                    for val_pair in l_val_pair]

         #create a listbox      
         [self.listbox.insert(tk.END, item.get_label()) for item in self.l_spans]
         self.listbox.bind('<<ListboxSelect>>', self.highlight_span)         

         #plot figure
         self.canvas = FigureCanvasTkAgg(self.fig,master=master)
         self.canvas.show()
         self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
         frame.pack()

         #use span selector
         self.span = SpanSelector(self.ax, self.sel_span, 'horizontal', useblit=True,
                             rectprops=dict(alpha=0.5, facecolor='red'), span_stays=False)

         #connect
         self.canvas.mpl_connect('key_press_event', self.span)


     def sel_span(self,xmin, xmax):
         indmin, indmax = np.searchsorted(self.x, (xmin, xmax))
         indmax = min(len(self.x) - 1, indmax)

         span = self.ax.axes.axvspan(xmin=self.x[indmin], xmax=self.x[indmax], 
                              alpha = 0.5, facecolor='red')

         #add actual span to list of spans
         self.l_spans.append(span)

         #update view (spans and listbox) with central list of spans          
         self.update_view()


     def update_view(self):
         #clear visualisation
         self.listbox.delete(0,tk.END)
         [span.remove() for span in self.l_spans]


         #fill with new data
         [self.listbox.insert(tk.END, span.get_label()) for span in self.l_spans]
         [span.draw(self.ax) for span in self.l_spans] #HERE IS THE PROBLEM!!!

         #update view
         #...


     def highlight_span():
         pass

     def delete(self,item):
         pass

list_vals= [[1,2],[2.5,4]]
root = tk.Tk()
app = App(root, list_vals)
root.mainloop()

函数更新视图出现问题:
我需要插入的渲染器是什么跨度.绘图()?

我不确定我的方法是否好,因为我没有tkinter的经验。你怎么认为?


Tags: importselfmasterfordefnpvalax
1条回答
网友
1楼 · 发布于 2024-03-29 09:34:52

我已经简化了您的代码,删除了(在我看来)不完全必要的update_view方法。我已经在sel_span方法中添加了所有相关内容,每次在图中选择一个区域时都会调用该方法。在

我还创建了另一个方法remove_spans来删除所选区域并清除下面的列表框。我还绑定了Delete按钮,这样如果按下按钮,选择和文本框将被清除。在

我还删除了listbox与ListboxSelect事件的绑定,因为当调用insert方法时,listbox将被更新。在

最后:我已经将您的xminxmax值添加到列表框中,而不是添加span.get_label()项。下面是示例代码:

class App:
    def __init__(self, master, l_val_pair):
         # Create a container
        frame = tk.Frame(master)

        # Create fields
        self.button_left = tk.Button(frame,text="Export")
        self.button_left.pack(side="left")
        self.button_right = tk.Button(frame,text="Delete", command = self.remove_spans)
        self.button_right.pack(side="left")

        self.listbox = tk.Listbox(master)
        self.listbox.pack(side='bottom', fill=tk.X) 

        #define figure
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)

        #sample data for a line
        self.x = np.arange(0.0, 5.0, 0.01)
        self.y = np.sin(2*np.pi*self.x) + 0.5*np.random.randn(len(self.x))

        #plot line and list of spans
        self.ax.plot(self.x,self.y)

        self.l_spans = [self.ax.axes.axvspan(val_pair[0],val_pair[1], facecolor='red', alpha=0.3, label=val_pair) 
                    for val_pair in l_val_pair]

        #create a listbox      
        [self.listbox.insert(tk.END, item.get_label()) for item in self.l_spans]          

        #plot figure
        self.canvas = FigureCanvasTkAgg(self.fig,master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
        frame.pack()

        #use span selector
        self.span = SpanSelector(self.ax, self.sel_span, 'horizontal', useblit=True,
                             rectprops=dict(alpha=0.5, facecolor='red'), span_stays=False)

        #connect
        self.canvas.mpl_connect('key_press_event', self.span)


    def sel_span(self, xmin, xmax):
        #clear visualisation
        self.remove_spans()
        indmin, indmax = np.searchsorted(self.x, (xmin, xmax))
        indmax = min(len(self.x) - 1, indmax)
        span = self.ax.axes.axvspan(xmin=self.x[indmin], xmax=self.x[indmax], 
                              alpha = 0.5, facecolor='red')

        #add actual span to list of spans
        self.l_spans.append(span)

        #for span in self.l_spans:
        self.listbox.insert(tk.END, xmin)
        self.listbox.insert(tk.END, xmax)


    def remove_spans(self):
        self.listbox.delete(0,tk.END)

        for span in self.l_spans:
           try:
               span.remove()
           except:
               pass
        self.canvas.draw_idle()


list_vals= [[1,2],[2.5,4]]
root = tk.Tk()
app = App(root, list_vals)
root.mainloop()

编辑: 注释进一步澄清了用例,因此这里是代码的修改版本。我重新引入了对<<ListboxSelect>>事件的绑定,并编写了highlight_span方法,该方法:

  • 在列表中选定的检查范围
  • 在图中以绿色突出显示它(只是为了使它更可见)

我还更改了代码,使旧的选择不会从列表框中删除:

^{pr2}$

我希望这有帮助。在

相关问题 更多 >