按pyplot中的按钮后如何覆盖绘图?

时间:2018-04-04 18:19:01

标签: python python-3.x matplotlib

我有一些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])

当我按下或向上按下时没有任何反应。

3 个答案:

答案 0 :(得分:0)

我整理了一个简化版的代码,当按下按钮时,它会绘制随机行。你不需要每次都重新定义ax对象,你需要清除它,我的构建似乎也需要刷新(如果你使用的是GUI) - (Efficient way to update matplotlib figure in gui?并在修改时重绘画布axes对象(参见代码中的注释)。

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)

答案 1 :(得分:0)

您不能多次拨打plt.show()。在init方法中创建完整图并显示它。仅使用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 :(得分:0)

我可以通过在绘图仪功能结束时添加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])

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