0

我正在开发一个 kivy 应用程序,该应用程序旨在以参数方式在现场进行听力训练练习并进行播放。音乐使用 mingus 模块进行描述,并通过其流体合成器实现播放。我有一个练习播放功能,它在正常调用时按预期工作,但是由于使用该方法,其他所有东西都会在钻头运行时挂起(在无限循环等待手动停止),这不会导致可接受的行为。我使用Process(),并根据终端的输出,它按预期循环,但没有声音。还有一点值得注意的是,从终端活动的节奏来看,多次按下开始按钮会导致多个进程并行运行。这是接口的python端的代码:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.config import Config
from classes import *
from multiprocessing import Process
import yaml
Config.set('graphics', 'width', '400')
Config.set('graphics', 'height', '700')

class Welcome(Screen):
    pass

class Builtin(Screen):
    pass

class DrillScreen(Screen):
    def __init__(self, **kwargs):
        super(DrillScreen, self).__init__(**kwargs)
        self.options = kwargs['options']
        self.desc = self.options.des
        self.thedrill = drill(self.options)
        desc = Label(
                text=self.options.des,
                size_hint_x=0.9,
                size_hint_y=1)
        button = Button(
                text = 'Start',
                size_hint=[0.4,0.1])
        button.bind(on_release=self.startdrill())
        self.add_widget(desc)
        self.add_widget(button)

    def startdrill(self):
        def starter(*args):
            proc = Process(target=self.thedrill.run)
            proc.start()
        return starter



class BuiltinView(RecycleView):
    def __init__(self, **kwargs):
        super(BuiltinView, self).__init__(**kwargs)
        with open('builtin.yaml', 'r') as builtin:
            self.drills = yaml.load(builtin)
        self.data = [ {'text': self.drills[i]['name'],
            'on_release': self.startermaker(i,self.drills[i])}
            for i in sorted(self.drills.keys()) ]

    def startermaker(self,num,options):
        def startdrill():
            options = drilloptions(self.drills[num])
            drillscreen = DrillScreen(name='drill', options=options)
            app = App.get_running_app()
            app.root.add_widget(drillscreen)
            app.root.current = 'drill'
            #drillscreen.thedrill.run()
        return startdrill


class Manager(ScreenManager):
    pass

class TestingApp(App):
    def build(self):
        return Manager()

TestingApp().run()

该类drill在其属性中保存一些参数,并在.run()调用其方法时进入一个循环以在这些参数中无休止地生成练习。在类的button.bind()声明中DrillScreen,如果我直接输入 on_release=self.thedrill.run ,我的功能就没有问题了。我不知道我在这里错过了什么。如果需要,我可以发布项目其他组件的代码。谢谢你。

4

1 回答 1

0

好吧,在尝试制作一个小的损坏示例时,我偶然发现了一个修复方法。我不确定为什么它以一种方式而不是另一种方式工作。以前流体合成器在创建.__init__()时在类的方法中初始化drill,我将它移到.run()方法中。在几乎伪代码中非常粗略:

前:

class drill:
    def __init__(self, opt):
        #Some attribute setting
        self.ex = None #This will instantiate a class describing a single question
        fluidsynth.init(args)

    def run(self):
        while True:
            #Determining randomly the arguments to create Exercise instance

            self.ex = Exercise(args)
            self.ex.play()

后:

class drill:
    def __init__(self, opt):
        #Some attribute setting
        self.ex = None

    def run(self):
        fluidsynth.init(args)
        while True:

            #Determining randomly the arguments to create Exercise instance

            self.ex = Exercise(args)
            self.ex.play()

当我.run()直接使用调用时button.bind(),两个版本都可以使用。当我将它分配给它自己的进程并将该进程交给 时button.bind(),只有第二个版本会发出声音。所以似乎大致发生的事情是初始化的流体合成器无法从不同的进程中访问。

如果有人对此事发表非推测性的理解,我将延迟接受这个答案。

于 2017-06-05T21:50:48.180 回答