【问题标题】:How to overwrite a plot after pressing a button in pyplot?按下pyplot中的按钮后如何覆盖绘图?
【发布时间】:2018-04-04 18:19:01
【问题描述】:

我有一些 csv 文件,其中包含我想要绘制的数据。我想使用键盘上的箭头键覆盖绘图。

我的代码:

import os, pandas, glob
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import filedialog

counter = 0

class Plotter:
    def __init__(self, filepath):
        self.plotter(filepath)

    def press(self, event):
        print('press', event.key)
        global counter
        if event.key == 'down':
            if (counter + 1) < len(files):
                counter = counter + 1
                self.plotter(files[counter])

        if event.key == 'up':
            if not (counter - 1) < 0:
                counter = counter - 1
                self.plotter(files[counter])

    def plotter(self, filepath):
        data = pandas.read_csv(filepath)
        fig = plt.figure()
        fig.canvas.mpl_connect('key_press_event', self.press)
        ax = fig.add_subplot(111)
        ax.plot(data.x, data.y1, 'r-')

        ax2 = ax.twinx()
        ax2.plot(data.x, data.y2, '--')

        plt.show()


if __name__ == '__main__':
    root = tk.Tk()
    root.withdraw()

    dir_path = filedialog.askdirectory()
    files = list(glob.glob(os.path.join(dir_path, 'test*.csv')))
    print(files[counter])
    Plot = Plotter(files[counter])

我的问题是:当我按下按钮时,会打开一个新窗口,而不是覆盖绘图。

有什么建议吗?

[编辑](我想保留以前的代码,因为这种方法的错误是不同的)我在 DavidG 的评论之后的代码看起来像:

import os, pandas, glob
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import filedialog

counter = 0

class Plotter:
    def __init__(self, filepath):
        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('key_press_event', self.press)
        self.plotter(filepath)

    def press(self, event):
        print('press', event.key)
        global counter
        if event.key == 'down':
            if (counter + 1) < len(files):
                counter = counter + 1
                self.plotter(files[counter])

        if event.key == 'up':
            if not (counter - 1) < 0:
                counter = counter - 1
                self.plotter(files[counter])

    def plotter(self, filepath):
        data = pandas.read_csv(filepath)

        ax = self.fig.add_subplot(111)
        ax.plot(data.x, data.y1, 'r-')

        ax2 = ax.twinx()
        ax2.plot(data.x, data.y2, '--')

        plt.show()


if __name__ == '__main__':
    root = tk.Tk()
    root.withdraw()

    dir_path = filedialog.askdirectory()
    files = list(glob.glob(os.path.join(dir_path, 'test*.csv')))
    print(files[counter])
    Plot = Plotter(files[counter])

当我按下或按下时,这里没有任何反应。

【问题讨论】:

  • 在每次调用plotter 时,您都会使用fig = plt.figure() 创建一个新图形。您可能想创建一个带有子图的图形,然后不断更新该图形
  • 我添加了另一种方法,我只创建了一次新图形。这一次,当我按下一个按钮时,什么也没有发生。
  • 使用plt.savefig('single_image.png')?

标签: python python-3.x matplotlib


【解决方案1】:

您不能多次致电plt.show()。在 init 方法中创建你的 complete 图并显示它。仅更新 plotter 方法中的绘图。

class Plotter:
    def __init__(self, filepath):
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111)
        self.ax2 = ax.twinx()
        self.fig.canvas.mpl_connect('key_press_event', self.press)
        self.plotter(filepath)
        plt.show()

    def plotter(self, filepath):
        data = pandas.read_csv(filepath)
        self.ax.plot(data.x, data.y1, 'r-')
        self.ax2.plot(data.x, data.y2, '--')
        self.fig.canvas.draw()

或者甚至更好地在 init 方法中自己创建图,只用新数据更新它们。

class Plotter:
    def __init__(self, filepath):
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111)
        self.ax2 = ax.twinx()
        self.line1, = self.ax.plot([], [], 'r-')
        self.line2, = self.ax2.plot([], [], '--')
        self.fig.canvas.mpl_connect('key_press_event', self.press)
        self.plotter(filepath)
        plt.show()

    def plotter(self, filepath):
        data = pandas.read_csv(filepath)
        self.line1.set_data(data.x, data.y1)
        self.line2.set_data(data.x, data.y2)
        self.fig.canvas.draw()

【讨论】:

    【解决方案2】:

    我可以通过在我的绘图仪函数末尾添加一个 plt.draw() 来解决这个问题。

    所以代码看起来像:

    import os, pandas, glob
    import matplotlib.pyplot as plt
    import tkinter as tk
    from tkinter import filedialog
    
    counter = 0
    
    class Plotter:
        def __init__(self, filepath):
            self.fig = plt.figure()
            self.fig.canvas.mpl_connect('key_press_event', self.press)
            self.plotter(filepath)
            plt.show()
    
        def press(self, event):
            print('press', event.key)
            global counter
            if event.key == 'down':
                if (counter + 1) < len(files):
                    counter = counter + 1
                    self.plotter(files[counter])
    
            if event.key == 'up':
                if not (counter - 1) < 0:
                    counter = counter - 1
                    self.plotter(files[counter])
    
        def plotter(self, filepath):
            data = pandas.read_csv(filepath)
            print(files[counter])
            plt.clf()
            ax = self.fig.add_subplot(111)
            ax.plot(data.x, data.y1, 'r-')
    
            ax2 = ax.twinx()
            ax2.plot(data.x, data.y2, '--')
            fname = os.path.split(filepath)[1]
            ax.set_title(fname)
            plt.draw()
            plt.show()
    
    if __name__ == '__main__':
        root = tk.Tk()
        root.withdraw()
    
        dir_path = filedialog.askdirectory()
        files = list(glob.glob(os.path.join(dir_path, 'test*.csv')))
        print(files[counter])
        Plot = Plotter(files[counter])
    

    这应该与我的第二个代码 sn-p 中的代码基本相同。只需添加 plt.draw()

    【讨论】:

      【解决方案3】:

      我整理了您的代码的简化版本,当按钮被向上或向下按下时,它会随机绘制线条。您不需要每次都重新定义 ax 对象,您需要清除它,在我的构建中似乎也有必要刷新(如果您使用的是 GUI)-(Efficient way to update matplotlib figure in gui? 并在修改轴时重绘画布对象(参见代码中的 cmets)。

      import matplotlib.pyplot as plt
      import Tkinter as tk
      import numpy as np
      
      class Plotter:
          def __init__(self, fig, ax):
              self.fig = fig
              self.ax = ax
              self.plotter(ax)
              self.fig.canvas.mpl_connect('key_press_event', self.press)
      
          def press(self, event):
              print('press', event.key)
              if event.key == 'down':
                  self.plotter(self.ax)
                  # flush and redraw
                  fig.canvas.flush_events()
                  fig.canvas.draw()
      
              if event.key == 'up':
                  self.plotter(self.ax)
                  # flush and redraw
                  fig.canvas.flush_events()
                  fig.canvas.draw()
      
          def plotter(self, ax):
      
              x1 = np.random.choice(range(0,5), 2)
              y1 = np.random.choice(range(0,5), 2)
              print x1, y1
              # clear the ax and use new data
              ax.clear()
              ax.plot(x1, y1, 'r-')
      
      
      fig, ax = plt.subplots(1,1)
      root = tk.Tk()
      root.withdraw()
      Plot = Plotter(fig, ax)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-03
        • 2015-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多