应用程序用于存储和查看多个实例

1 投票
1 回答
41 浏览
提问于 2025-04-14 16:46

我的这个基于Toga的应用程序让用户在一系列框里输入信息。最后,这些信息会用来启动一些由调度器管理的进程。一旦这些进程启动,应用程序就会通过不断更新状态框来向用户显示进度。

用户可以同时运行多个应用程序实例。用户应该能够创建一个新的应用实例,并查看所有正在进行的实例的状态框。

目前的做法是使用了multiprocessing来提高操作的稳定性,基本上是这样的:

import toga
import multiprocessing
from toga.style import Pack


class Test(toga.App):
    
    instances = []
    
    def startup(self):

        self.main_box = toga.Box(style=Pack(direction='column'))        

        self.main_window = toga.MainWindow(title=self.formal_name)
        
        self.main_window.content = self.main_box
        
        self.main_window.show()
        
        self.work()
        
    
    def work(self):
        
        add_but = toga.Button('Add instance to list', on_press=self.add_but_hdl)
        
        ins_num = len(Test.instances) + 1
        
        ins_lbl = toga.Label('Current instance number is {}'.format(ins_num))
        
        if Test.instances:
            prv_ins_idx = len(Test.instances) - 1
            self.main_box.add(Test.instances[prv_ins_idx].main_window.show(),
                              ins_lbl, 
                              add_but)
        else:
            self.main_box.add(ins_lbl, add_but)
            
            
    def add_but_hdl(self, widget):
        
        Test.instances.append(self)
        
        self.init_proc()
        
        
    def init_proc(self):
        
        proc = multiprocessing.Process(target=self.mk_app_ins)
        
        proc.start()
        
        
    def mk_app_ins(self):
        
        new_ins = Test()
        
        new_ins.main_loop()


def main():
        
    return Test()

当通过briefcase dev运行上述代码,并点击将实例添加到列表时,会出现以下错误:

[tender] 正在以开发模式启动... =========================================================================== 注册失败:接口org.gtk.Application已经有一个对象被导出在...

这个设置能否正常工作,还是应该放弃,换一种完全不同的方法?可行的解决方案可能是什么样的呢?

1 个回答

1

根据multiprocessing的文档,在Linux系统上,默认的进程启动方式是fork。这意味着“子进程一开始就和父进程几乎一模一样”。所以,子进程会认为它已经有一个图形界面在运行了。

因此,你可能应该使用spawn方法,这样子进程就能从头开始。你可以通过调用multiprocessing.set_start_method来实现。

或者,与其处理多个进程的复杂性,不如只用一个进程来创建多个窗口,这样可能更简单。Toga在Linux、Windows和macOS上都支持这个功能。

在Android或iOS上,Toga目前只支持一个窗口,但你可以随意修改这个窗口的用户界面,让用户看到不同的内容。你可以通过添加或移除子组件,甚至重新设置窗口的content属性来做到这一点。

撰写回答