有人可以告诉我这段代码有什么问题吗?

时间:2019-10-25 14:24:52

标签: python-3.x matplotlib tkinter

我正在处理Idle,当我要求检查文件时,它说没有问题。但是,当我运行它时,它会使应用程序崩溃。我也在研究MAC,我不知道这是否会影响任何事情。谁能告诉我这段代码有什么问题吗?我还很新,所以可以提供任何帮助。 另外,当GUI具有动画数据条目并且GUI上也有一个调用动画的按钮时,我想做的主要是将matplotlib动画嵌入GUI中。理想情况下,将单击该按钮,并且动画将显示在两个条目上方。我已经在这个程序上工作了一段时间,但是嵌入动画/获取用于回调图形的按钮是最麻烦的部分。

import tkinter as tk 
from tkinter import * 
import time 
import pyaudio 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 
from matplotlib.figure import Figure 
from matplotlib import pyplot as plt 
import matplotlib.animation as animation 
import numpy as np 

import random 

fig = plt.figure() 
ax1 = fig.add_subplot(1,1,1) 


def get_data(): 
    while True: 


        return x, mylist 

class App(tk.Frame): 
    def __init__(self, root): 
        self.root = root 
        self.root.title("Testing") 
        self.setupTk() 
        self.quit_button = Button(master=self.root, text='Quit', command=self._quit) 
        self.quit_button.pack(side='right') 
        def _quit(self): 
            self.root.destroy() 

fig = plt.Figure() 

x = np.arange(0, 2*np.pi, 0.01)        # x-array 

def animate(i): 
    line.set_ydata(np.sin((x+i/10.0)))  # update the data 
    return line, 

root = tk.Tk() 
label = tk.Label(root,text="SHM Simulation").grid(column=0, row=0) 

canvas = FigureCanvasTkAgg(fig, master=root) 
canvas.get_tk_widget().grid(column=0,row=1) 
entry1= Entry(root, text='Frequency') 
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) 

entry2= Entry(root, text='Duration') 
canvas.get_tk.widget().pack(side=TOP, fill=BOTH, expand=1) 
entry2.pack() 

f=int(entry1.get()) 
t=float(entry2.get()) 

def callback(): 
    p=pyaudio.Pyaudio 
    fs=44100 
    volume=.7 
    samples=(np.sin(f*2*np.pi*np.arange(fs*t)/(fs).astype(np/float32))) 
    stream=p.open(format=pyaudio.paFloat32, 
                  channels=1, 
                  rate=fs, 
                  output=True) 
    stream.write(volume*samples) 

b=Button(root, text='Sound', command=callback) 
ax = fig.add_subplot(111) 
line, = ax.plot(x, np.sin(x)) 
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), interval=25, blit=False) 

def on_click(self): 

        if self.ani is None: 

           return self.start() 

        if self.running: 

            self.ani.event_source.stop() 
            self.btn.config(text='Un-Pause') 
        else: 

            self.ani.event_source.start() 
            self.btn.config(text='Pause') 
        self.running = not self.running 
        def start(self): 
            self.points = int(self.points_ent.get()) + 1 
            self.ani = animation.FuncAnimation( 
                self.fig, 
                self.update_graph, 
                frames=self.points, 
                interval=int(self.interval.get()), 
                repeat=False) 
            self.running = True 
            self.btn.config(text='Pause') 
            self.ani._start() 
            print('started animation') 
            def update_graph(self, i): 
                self.line.set_data(*get_data()) # update graph 

                if i >= self.points - 1: 

                    self.btn.config(text='Start') 
                    self.running = False 
                    self.ani = None 
                return self.line, 

def main(): 
    root = tk.Tk() 
    app = App(root) 
    app.pack() 
    root.mainloop() 

if __name__ == '__main__': 
    main 

1 个答案:

答案 0 :(得分:0)

由于我对pyaudio感兴趣,因此我尝试使您的代码可以使用我认为您想要的功能运行。您可以从此处构建,以将一个随机信号添加到正弦波或一起使用不同的信号。主要变化是所有功能现在都在App类中。为了使音频声音和情节能够同时运行,我在另一个线程中启动了音频。 希望这对您有用。

import threading
import random
import numpy as np
import tkinter as tk
from tkinter import Label, Button, Entry, TOP, BOTH
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import pyaudio

DEFAULT_FREQUENCY = 220
DEFAULT_DURATION = 5
VOLUME = 0.3
INTERVAL = 100

class App(tk.Frame):
    def __init__(self, root):
        self.root = root
        self.root.title("SHM Simulation - Testing")

        label = tk.Label(self.root, text="SHM Simulation")
        label.pack()

        self.fig, self.ax = plt.subplots(figsize=(5, 5))
        self.canvas = FigureCanvasTkAgg(self.fig, master=root)
        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        self.ax.set_ylim(-1.1, 1.1)
        self.ax.set_xlim(-0.1, 2 * np.pi + 0.1)

        self.quit_button = Button(master=self.root, text='Quit', command=self.quit)
        self.quit_button.pack(side='right')

        self.sound_button = Button(self.root, text='Sound off', command=self.toggle_sound)
        self.sound_button.pack(side='right')

        self.plot_button = Button(self.root, text='Start')
        self.plot_button.pack(side='right')
        self.plot_button.bind('<Button-1>', self.on_click)

        tk.Label(self.root, text='Frequency').pack(side='left')
        self.frequency_entry = Entry(self.root)
        self.frequency_entry.insert(0, DEFAULT_FREQUENCY)
        self.frequency_entry.pack(side='left')

        tk.Label(self.root, text='Duration').pack(side='left')
        self.duration_entry = Entry(self.root)
        self.duration_entry.insert(0, DEFAULT_DURATION)
        self.duration_entry.pack(side='left')

        self.ani = None
        self.running = False

        self.audio = pyaudio.PyAudio()
        self.sound = False
        self.samples = np.array([])

    def quit(self):
        self.audio.terminate()
        self.root.quit()

    def get_data(self, frame):
        self.ydata = np.sin(self.frequency * self.xdata + frame)

    def update_frame(self, frame):
        self.get_data(frame)
        self.line.set_data(self.xdata, self.ydata)

        if frame > self.duration - 1.1 * INTERVAL / 1000 :
            self.ani = None
            self.running = False
            self.plot_button.config(text='Start')

        return self.line,

    def start_animation(self):
        self.xdata = []
        self.ydata = []
        self.line, = self.ax.plot(self.xdata, self.ydata, lw=3)

        self.xdata = np.arange(0, 2 * np.pi, 0.01)

        duration_range = np.arange(0, self.duration, INTERVAL / 1000)
        self.ani = FuncAnimation(self.fig,
                                 self.update_frame,
                                 frames=duration_range,
                                 interval=INTERVAL,
                                 repeat=False)

        if self.sound:
            ''' start audio in a seperate thread as otherwise audio and
                plot will not be at the same time
            '''
            x = threading.Thread(target=self.play_sound)
            x.start()

    def callback(self, in_data, frame_count, time_info, status):
        out = self.samples[:frame_count]
        self.samples = self.samples[frame_count:]
        return (out*VOLUME, pyaudio.paContinue)

    def play_sound(self):
        fs = 44100
        self.samples = (np.sin(2 * np.pi * np.arange(fs * self.duration) *
                        self.frequency / fs)).astype(np.float32)

        stream = self.audio.open(format=pyaudio.paFloat32,
                                 channels=1,
                                 rate=fs,
                                 output=True,
                                 stream_callback=self.callback)

        stream.start_stream()

        # pause audio when self.running is False
        while stream.is_active():
            while not self.running:
                if stream.is_active:
                    stream.stop_stream()
                else:
                    pass

            if self.running and not stream.is_active():
                stream.start_stream()
            else:
                pass

        stream.stop_stream()
        stream.close()

    def toggle_sound(self):
        if self.sound:
            self.sound_button.configure(text='Sound Off')
        else:
            self.sound_button.configure(text='Sound On ')

        self.sound = not self.sound

    def on_click(self, event):
        if self.ani is None:
            try:
                self.ax.lines.pop(0)

            except IndexError:
                pass

            try:
                self.frequency = int(self.frequency_entry.get())
                self.duration = int(self.duration_entry.get())

            except ValueError:
                self.frequency = DEFAULT_FREQUENCY
                self.frequency_entry.insert(0, DEFAULT_FREQUENCY)
                self.duration = DEFAULT_DURATION
                self.duration_entry.insert(0, DEFAULT_DURATION)

            self.start_animation()
            self.running = True
            self.plot_button.config(text='Pause')
            print('animation started ...')
            return

        if self.running:
             self.ani.event_source.stop()
             self.plot_button.config(text='Run  ')

        else:
             self.ani.event_source.start()
             self.plot_button.config(text='Pause')

        self.running = not self.running


def main():
    root = tk.Tk()
    app = App(root)
    root.mainloop()


if __name__ == '__main__':
    main()