使用 tkinter 中的按钮停止阅读使用 fluidsynth 创建的笔记
Stop the reading of notes created with fluidsynth with a button in tkinter
我在 python2-7 我想在 tkinter 中获得一个按钮,停止读取使用 fluidsynth 创建的笔记。
我发现常见的解决方案是像这里一样使用 time.after:How do you create a Tkinter GUI stop button to break an infinite loop?
但在我的情况下我不能使用它,因为我需要在 noteon 和 noteoff 之间有一定的时间来为我的笔记提供持续时间。
此外,我只想在单击开始时播放音符(而不是像 link 中的解决方案那样在开头播放)。
所以我创建了这段代码,但它不起作用,因为 var_start 总是初始化为 int:
from tkinter import*
import fluidsynth
import time
fs=fluidsynth.Synth()
fs.start(driver='alsa', midi_driver='alsa_seq')
org_charge = fs.sfload("organ.sf2")
fs.program_select(0,org_charge, 0, 0)
time.sleep(1)
var_start=int
def start():
global var_start
var_start=1
def stop():
global var_start
var_start=0
root=Tk()
if var_start==1:
fs.noteon(0,67,127)
time.sleep(1)
fs.noteoff(0,67)
fs.noteon(0,71,127)
time.sleep(1)
fs.noteoff(0,71)
fs.noteon(0,74,127)
time.sleep(1)
fs.noteoff(0,74)
Button(root, text='start', command= start).pack(padx=10, pady=10)
Button(root, text='stop', command= stop).pack(padx=10, pady=10)
root.mainloop()
我没有其他想法来重塑我的代码...
有人可以帮助我吗?
谢谢
您在语句 var_start=int
中启动了 var_start
到 int
,因此永远不会执行 if var_start==1:
中的代码块。而您的 start()
函数只是将 var_start
更改为 1 并且永远不会开始演奏音符,因此什么也不会发生。
切勿在主线程中调用 time.sleep()
,因为它会阻塞 tkinter
主循环。您可以使用 .after(...)
来模拟播放循环,下面是示例代码块:
playing = False
def play_notes(notes, index, noteoff):
global playing
if noteoff:
fs.noteoff(0, notes[index])
index += 1 # next note
if playing and index < len(notes):
fs.noteon(0, notes[index], 127)
# call noteoff one second later
root.after(1000, play_notes, notes, index, True)
else:
# either stopped or no more note to play
playing = False
print('done playing')
def start_playing():
global playing
if not playing:
print('start playing')
playing = True
notes = [67, 71, 74, 88, 80, 91]
play_notes(notes, 0, False)
else:
print('already playing')
def stop_playing():
global playing
if playing:
playing = False
print('stop playing')
else:
print('nothing playing')
Button(root, text='Start', command=start_playing).pack(padx=10, pady=10)
Button(root, text='Stop', command=stop_playing).pack(padx=10, pady=10)
这只是一个示例,您可以根据需要进行修改。
我在 python2-7 我想在 tkinter 中获得一个按钮,停止读取使用 fluidsynth 创建的笔记。
我发现常见的解决方案是像这里一样使用 time.after:How do you create a Tkinter GUI stop button to break an infinite loop?
但在我的情况下我不能使用它,因为我需要在 noteon 和 noteoff 之间有一定的时间来为我的笔记提供持续时间。 此外,我只想在单击开始时播放音符(而不是像 link 中的解决方案那样在开头播放)。
所以我创建了这段代码,但它不起作用,因为 var_start 总是初始化为 int:
from tkinter import*
import fluidsynth
import time
fs=fluidsynth.Synth()
fs.start(driver='alsa', midi_driver='alsa_seq')
org_charge = fs.sfload("organ.sf2")
fs.program_select(0,org_charge, 0, 0)
time.sleep(1)
var_start=int
def start():
global var_start
var_start=1
def stop():
global var_start
var_start=0
root=Tk()
if var_start==1:
fs.noteon(0,67,127)
time.sleep(1)
fs.noteoff(0,67)
fs.noteon(0,71,127)
time.sleep(1)
fs.noteoff(0,71)
fs.noteon(0,74,127)
time.sleep(1)
fs.noteoff(0,74)
Button(root, text='start', command= start).pack(padx=10, pady=10)
Button(root, text='stop', command= stop).pack(padx=10, pady=10)
root.mainloop()
我没有其他想法来重塑我的代码... 有人可以帮助我吗?
谢谢
您在语句 var_start=int
中启动了 var_start
到 int
,因此永远不会执行 if var_start==1:
中的代码块。而您的 start()
函数只是将 var_start
更改为 1 并且永远不会开始演奏音符,因此什么也不会发生。
切勿在主线程中调用 time.sleep()
,因为它会阻塞 tkinter
主循环。您可以使用 .after(...)
来模拟播放循环,下面是示例代码块:
playing = False
def play_notes(notes, index, noteoff):
global playing
if noteoff:
fs.noteoff(0, notes[index])
index += 1 # next note
if playing and index < len(notes):
fs.noteon(0, notes[index], 127)
# call noteoff one second later
root.after(1000, play_notes, notes, index, True)
else:
# either stopped or no more note to play
playing = False
print('done playing')
def start_playing():
global playing
if not playing:
print('start playing')
playing = True
notes = [67, 71, 74, 88, 80, 91]
play_notes(notes, 0, False)
else:
print('already playing')
def stop_playing():
global playing
if playing:
playing = False
print('stop playing')
else:
print('nothing playing')
Button(root, text='Start', command=start_playing).pack(padx=10, pady=10)
Button(root, text='Stop', command=stop_playing).pack(padx=10, pady=10)
这只是一个示例,您可以根据需要进行修改。