Python 无法解释小部件打包和未打包时的行为差异
我正在做一个可视化声音的小应用程序,但控件的行为并不一致。 当我启用(打包)输入字段时,程序将按预期工作。然而,如果我把它们注释掉,情节就不再显示,我只听到声音。真的很困惑 (在Ubuntu 18.04上运行python 3.7.4) 以下工作:Python 无法解释小部件打包和未打包时的行为差异,python,tkinter,Python,Tkinter,我正在做一个可视化声音的小应用程序,但控件的行为并不一致。 当我启用(打包)输入字段时,程序将按预期工作。然而,如果我把它们注释掉,情节就不再显示,我只听到声音。真的很困惑 (在Ubuntu 18.04上运行python 3.7.4) 以下工作: import threading import numpy as np import tkinter as tk from tkinter import Label, Button, Entry, TOP, BOTH from matplotlib.b
import threading
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 = 420 # frequency in Hz
DEFAULT_DURATION = 3.0 # length of sound stream in seconds
VOLUME = 0.1 # must < 1
INTERVAL = 100 # plot interval in millisecond
PACKAGE_LENGTH = 1024 # number of samples in sound package
FS = 2**12 # sampling frequency sound, normal is 44100
class SoundVisualiser:
def __init__(self, root):
self.root = root
self.root.title("Sound Visualiser")
label = tk.Label(self.root, text="Sound Visualiser")
label.pack()
self.fig, self.ax = plt.subplots(figsize=(5, 5))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.ax.set_xlim(1000 * PACKAGE_LENGTH / FS, 0)
freq_label = tk.Label(self.root, text='Frequency')
self.frequency_entry = Entry(self.root)
self.frequency_entry.insert(0, DEFAULT_FREQUENCY)
durat_label = tk.Label(self.root, text='Duration')
self.duration_entry = Entry(self.root)
self.duration_entry.insert(0, DEFAULT_DURATION)
freq_label.pack(side='left')
self.frequency_entry.pack(side='left')
durat_label.pack(side='left')
self.duration_entry.pack(side='left')
self.quit_button = Button(
self.root, text='Quit', command=self.quit)
self.quit_button.pack(side='right')
self.control_button = Button(
self.root, text='Start')
self.control_button.bind('<Button-1>', self.start_visualisation)
self.control_button.pack(side='right')
self.duration = DEFAULT_DURATION
self.xdata = np.linspace(0, 1000 * PACKAGE_LENGTH / FS, PACKAGE_LENGTH)
self.audio = pyaudio.PyAudio()
def quit(self):
self.audio.terminate()
self.root.quit()
def generate_sound_stream(self):
self.sound_stream = (
(0.5 * np.sin(2 * np.pi * 325 / FS *
np.arange(FS * self.duration))) +
(0.1 * np.sin(2 * np.pi * 330 / FS *
np.arange(FS * self.duration))) +
(0.5 * np.sin(2 * np.pi * 340 / FS *
np.arange(FS * self.duration))) + 0
).astype(np.float32)
self.ax.set_ylim(1.1 * np.min(self.sound_stream), 1.1 * np.max(self.sound_stream))
def callback(self, in_data, frame_count, time_info, status):
out = self.sound_stream[:frame_count]
self.out_plot = out[:]
self.sound_stream = self.sound_stream[frame_count:]
return (out*VOLUME, pyaudio.paContinue)
def play_sound(self):
stream = self.audio.open(format=pyaudio.paFloat32,
channels=1,
rate=FS,
output=True,
stream_callback=self.callback)
stream.start_stream()
while stream.is_active():
pass
stream.stop_stream()
stream.close()
self.visualisation = None
self.control_button.config(text='Start')
def update_frame(self, frame):
samples = len(self.out_plot)
if samples == PACKAGE_LENGTH:
self.line.set_data(self.xdata, self.out_plot)
else:
xdata = np.linspace(0, 1000 * samples / FS, samples)
self.line.set_data(xdata, self.out_plot)
return self.line,
def start_visualisation(self, event):
self.duration = float(self.duration_entry.get())
self.generate_sound_stream()
self.line, = self.ax.plot([], [], lw=3)
self.control_button.config(text='run')
duration_range = np.arange(0, self.duration, INTERVAL / 1000)
self.visualisation = FuncAnimation(self.fig,
self.update_frame,
frames=duration_range,
interval=INTERVAL,
repeat=False)
# start audio in a seperate thread as otherwise audio and
# plot will not be at the same time
self.play_sound_thread = threading.Thread(target=self.play_sound)
self.play_sound_thread.start()
def main():
root = tk.Tk()
sound_visualiser = SoundVisualiser(root)
root.mainloop()
if __name__ == '__main__':
main()
导入线程
将numpy作为np导入
将tkinter作为tk导入
从tkinter导入标签、按钮、条目、顶部、两者
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
从matplotlib.figure导入图形
从matplotlib导入pyplot作为plt
从matplotlib.animation导入FuncAnimation
导入pyaudio
默认频率=420#频率,单位为Hz
默认_持续时间=3.0#音流长度(秒)
体积=0.1#必须小于1
间隔=100#以毫秒为单位的绘图间隔
包装长度=1024#声音包装中的样本数量
FS=2**12#采样频率声音,正常值为44100
类声音可视化器:
定义初始化(自,根):
self.root=根
self.root.title(“声音可视化器”)
label=tk.label(self.root,text=“声音可视化器”)
label.pack()
self.fig,self.ax=plt.子批次(figsize=(5,5))
self.canvas=FigureCanvasTkAgg(self.fig,master=self.root)
self.canvas.get_tk_widget().pack(side=TOP,fill=BOTH,expand=1)
self.ax.set\u xlim(1000*封装长度/FS,0)
freq_label=tk.label(self.root,text='Frequency')
self.frequency\u entry=entry(self.root)
self.frequency\u entry.insert(0,默认频率)
durat_label=tk.label(self.root,text='Duration')
self.duration\u entry=条目(self.root)
self.duration\u entry.insert(0,默认\u duration)
频率标签包(侧边为左)
自我频率_entry.pack(side='left')
durat_标签包装(侧边='left')
self.duration\u entry.pack(side='left')
self.quit_按钮=按钮(
self.root,text='Quit',command=self.Quit)
self.quit_按钮.pack(side='right')
self.control_按钮=按钮(
self.root,text='Start')
自我控制按钮绑定(“”,自我启动可视化)
自我控制按钮包(侧/右)
self.duration=默认持续时间
self.xdata=np.linspace(0,1000*包长度/FS,包长度)
self.audio=pyaudio.pyaudio()
def退出(自我):
self.audio.terminate()
self.root.quit()
def生成声音流(自身):
self.sound\u流=(
(0.5*np.sin(2*np.pi*325/FS*
np.arange(FS*自我持续时间)+
(0.1*np.sin(2*np.pi*330/FS*
np.arange(FS*自我持续时间)+
(0.5*np.sin(2*np.pi*340/FS*
np.arange(FS*自我持续时间))+0
).astype(np.32)
self.ax.set_ylim(1.1*np.min(self.sound_流),1.1*np.max(self.sound_流))
def回调(自身、输入数据、帧计数、时间信息、状态):
out=自身声音流[:帧计数]
self.out_plot=out[:]
self.sound\u stream=self.sound\u stream[帧计数:]
返回(out*VOLUME,pyaudio.paccontinue)
def播放声音(自):
stream=self.audio.open(格式=pyaudio.paFloat32,
通道=1,
速率=FS,
输出=真,
stream_callback=self.callback)
stream.start_stream()
当stream.u处于活动状态时()
通过
stream.stop_stream()
stream.close()
自我形象化=无
self.control\u button.config(text='Start')
def更新_帧(自身,帧):
样本=长度(自输出图)
如果样本==包装长度:
self.line.set_数据(self.xdata、self.out_绘图)
其他:
扩展数据=np.linspace(0,1000*个样本/FS,样本)
self.line.set_数据(扩展数据、self.out_绘图)
返回自助线路,
def启动可视化(自身、事件):
self.duration=float(self.duration\u entry.get())
self.generate_sound_stream()
self.line,=self.ax.plot([],[],lw=3)
self.control\u button.config(text='run')
持续时间范围=np.arange(0,自持续时间,间隔/1000)
self.visualization=FuncAnimation(self.fig,
self.update_框架,
帧=持续时间\u范围,
间隔=间隔,
重复(错误)
#在单独的线程中启动音频,否则音频和
#绘图将不会同时进行
self.play\u sound\u thread=threading.thread(target=self.play\u sound)
self.play\u sound\u thread.start()
def main():
root=tk.tk()
声音可视化程序=声音可视化程序(根)
root.mainloop()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
注释掉输入字段将停止显示绘图
def __init__(self, root):
self.root = root
self.root.title("Sound Visualiser")
label = tk.Label(self.root, text="Sound Visualiser")
label.pack()
self.fig, self.ax = plt.subplots(figsize=(5, 5))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.ax.set_xlim(1000 * PACKAGE_LENGTH / FS, 0)
freq_label = tk.Label(self.root, text='Frequency')
self.frequency_entry = Entry(self.root)
self.frequency_entry.insert(0, DEFAULT_FREQUENCY)
durat_label = tk.Label(self.root, text='Duration')
self.duration_entry = Entry(self.root)
self.duration_entry.insert(0, DEFAULT_DURATION)
# freq_label.pack(side='left')
# self.frequency_entry.pack(side='left')
# durat_label.pack(side='left')
# self.duration_entry.pack(side='left')
self.quit_button = Button(
self.root, text='Quit', command=self.quit)
self.quit_button.pack(side='right')
self.control_button = Button(
self.root, text='Start')
self.control_button.bind('<Button-1>', self.start_visualisation)
self.control_button.pack(side='right')
self.duration = DEFAULT_DURATION
self.xdata = np.linspace(0, 1000 * PACKAGE_LENGTH / FS, PACKAGE_LENGTH)
self.audio = pyaudio.PyAudio()
def\uuuu init\uuuu(self,root):
self.root=根
self.root.title(“声音可视化器”)
label=tk.label(self.root,text=“声音可视化器”)
label.pack()
self.fig,self.ax=plt.子批次(figsize=(5,5))
self.canvas=FigureCanvasTkAgg(self.fig,master=self.root)
self.canvas.get_tk_widget().pack(side=TOP,fill=BOTH,expand=1)
self.ax.set\u xlim(1000*封装长度/FS,0)
freq_label=tk.label(self.root,text='Frequency')
self.frequency\u entry=entry(self.root)
self.frequency\u entry.insert(0,默认频率)
durat_label=tk.label(self.root,text='Duration')
self.duration\u entry=条目(self.root)
self.duration\u entry.insert(0,默认\u duration)
#freq_label.pa