我正在处理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
答案 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()