多个交互式matplotlib在python 2.7和3.6中表现不同

时间:2018-01-11 00:47:50

标签: python python-2.7 matplotlib plot

我有一个python脚本,它连续循环,用户输入指示它从文件中获取数据,然后使用matplotlib绘制它。我的希望是让剧情出现并坚持(并继续保持互动),同时脚本继续在控制台中请求下一轮用户输入和绘图。因此,用户最终可能会打开几个完全正常运行的绘图窗口。

我实际上已经在我的python 2.7 anaconda构建中使用以下示例代码进行工作,该代码只是在每个循环中绘制一个随机数据集。

import sys
import matplotlib.pyplot as plt
import matplotlib
import numpy as np

print('matplotlib version: '+matplotlib.__version__)
version = sys.version_info[0]

def plot_data(data):
    fig = plt.figure(figsize=(6,6))
    plt.plot(data)
    plt.ion()
    plt.show()
    plt.pause(0.001)

while True:
    if version < 3:
        option = raw_input('type (1) to plot next data, (q) to quit\n')
    else:
        option = input('type (1) to plot next data, (q) to quit\n')
    if option == '1':
        data = np.random.choice(1000,100, replace = False)
        plot_data(data)
    elif option == 'q':
        break

使用我的python 3.6版本运行代码,该图显示但在非响应状态下被冻结,直到我返回控制台并输入q退出我的用户输入循环。在python 2.7中,绘图窗口通过多个输入循环和绘图调用完全起作用。所以我希望有人知道这里有什么不同。我正在打印matplotlib版本,看起来我的2.7和3.6环境都使用相同的matplotlib 2.0.2所以也许它在GUI处理程序中?

1 个答案:

答案 0 :(得分:0)

我不确定使用while循环和plt.ion()的问题的设置是否真的应该有效。至少对我来说使用python 2.7和matplotlib 2.1它没有 我希望这是可以预料到的,因为只要等待用户输入,应用程序就会冻结并变得无响应。

在任何情况下,由于混合控制台和GUI应用程序总是有点微妙,我会选择完全在GUI的事件循环中工作。

您可以将"key_press_event"连接到"1""q"键,并在打开的matplotlib窗口中显示新数据。

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(6,6))
ax = plt.subplot(111)

def plot_data(ax, data):
    ax.clear()
    ax.plot(data)
    ax.figure.canvas.draw_idle()

def press(event=None):
    if event:
        if event.key == "1":
            data = np.random.choice(1000,100, replace = False)
            plot_data(ax, data)
        elif event.key == "q":
            plt.close()

cid= fig.canvas.mpl_connect("key_press_event", press)
plt.show()

如果你想创建几个数字,这看起来像

import matplotlib.pyplot as plt
import numpy as np

def create_figure(data):
    fig, ax = plt.subplots(figsize=(6,6))
    ax.plot(data)
    cid = fig.canvas.mpl_connect("key_press_event", press)
    fig.show()

def plot_data():
    data = np.random.choice(1000,100, replace = False)
    create_figure(data)

def press(event=None):
    if event:
        if event.key == "1":
            plot_data()
        elif event.key == "q":
            plt.close("all")
    else:
        plot_data()

press()
plt.show()

对于更复杂的输入,您可以创建一个小GUI,它收集输入并调用绘图功能。例如,可以为此目的使用Tkinter。

from Tkinter import * # use from tkinter import *  if using python3
import matplotlib.pyplot as plt
import numpy as np

def create_figure(data):
    fig, ax = plt.subplots(figsize=(6,6))
    ax.plot(data)
    fig.show()

def plot_data(n, amp):
    try:
        n = int(n)
        amp = float(amp)
        data = amp*np.random.rand(n)
        create_figure(data)
    except:
        pass

def closeall():
    for i in plt.get_fignums():
        plt.close(i)

def create_input():
    root = Tk()
    Label(text="Number of datapoints").grid(row=1,column=0, sticky=W)
    Label(text="Amplitude").grid(row=2,column=0, sticky=W)
    tb1=Entry(root,textvariable=StringVar(root, value='24'))
    tb1.grid(row=1,column=1, sticky=W+E)
    tb2=Entry(root,textvariable=StringVar(root, value='6'))
    tb2.grid(row=2,column=1, sticky=W+E)
    b1=Button(root,text="   Plot   ",command= lambda : plot_data(tb1.get(),tb2.get()))
    b1.grid(row=4,column=1, sticky=W+E)
    b2=Button(root,text="Close All",command=closeall)
    b2.grid(row=5,column=1, sticky=W+E)
    root.mainloop()

create_input()

enter image description here