同时运行多个相互通信的 Kivy 应用程序

2022-01-15 00:00:00 python python-2.7 kivy user-interface

问题描述

我希望我的 Kivy 应用程序能够在 Windows 机器上生成多个可以相互通信的应用程序(即新窗口).

I would like my Kivy application to be able to spawn multiple apps (i.e. new windows) on a Windows machine that can communicate with each other.

ScreenManager 和 Popup 选项不会削减它,因为它们位于同一个窗口中..我需要能够拖动新屏幕多个显示器,因此需要多个窗口.

ScreenManager and Popup options will not cut it because they live in the same window..I need to be able to drag new screens across multiple monitors and therefore need multiple windows.

Kivy 文档明确声明 "Kivy 仅支持一个窗口每个应用程序:请不要尝试创建多个."

Kivy docs explicitly state that "Kivy supports only one window per application: please don't try to create more than one."

谷歌搜索产生这种简单的方法来自另一个应用程序的新应用程序,如下所示:

A google search produces this simple approach of simple spawning a new app from within another app, like so:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label


class ChildApp(App):
    def build(self):
        return Label(text='Child')


class MainApp(App):

    def build(self):
        b = Button(text='Launch Child App')
        b.bind(on_press=self.launchChild)
        return b

    def launchChild(self, button):
        ChildApp().run()

if __name__ == '__main__':
    MainApp().run()

但是,当我这样做时,它会在同一窗口中启动应用程序并崩溃,我的终端会像疯了一样吐出:

However, when I do this, it launches the app within the same window and crashes, and my terminal spits out like crazy:

Original exception was:
Error in sys.exceptionhook:

如果我使用 multiprocessing.Process(target=ChildApp().run()).start() 而不是 ChildApp().run() 我会得到相同的结果代码>

I get the same result if instead of ChildApp().run() I do multiprocessing.Process(target=ChildApp().run()).start()

使用 subprocess 库让我更接近我想要的:

Using the subprocess library gets me closer to what I want:

# filename: test2.py

from kivy.app import App
from kivy.uix.label import Label


class ChildApp(App):
    def build(self):
        return Label(text='Child')

if __name__ == '__main__':
    ChildApp().run()

<小时>

# filename: test.py

from kivy.app import App
from kivy.uix.button import Button

import subprocess


class MainApp(App):

    def build(self):
        b = Button(text='Launch Child App')
        b.bind(on_press=self.launchChild)
        return b

    def launchChild(self, button):
        subprocess.call('ipython test2.py', shell=True)

if __name__ == '__main__':
    MainApp().run()

这会毫无错误地生成子窗口,但是现在主窗口被锁定(白色画布),如果我关闭子窗口,它就会重新打开.

This spawns the child window without error, however now the main window is locked (white canvas) and if I close the child window, it just gets reopened.

他们需要能够在彼此之间传递数据.关于如何在 Windows 中正确执行此操作的任何想法?这个 post 似乎表明这是可能的,但我不知道从哪里开始.

They need to be able pass data between one another. Any ideas on how to do this correctly in Windows? This post seems to suggest that this is possible but I'm not sure where to start.


解决方案

bj0 关于子进程的回答是正确的.

bj0's answer regarding subprocess was correct.

更好的是,我想出了如何通过多处理来做到这一点,这允许在应用程序之间更好地通信和传递信息.它以前不起作用,因为我在 multiprocessing.Process(target=ChildApp().run()).start() 应该是 multiprocessing.Process(target=ChildApp().run).start().以下作品

Even better, I figured out how to do this via multiprocessing, which allows better communication and passing of information between apps. It wasn't working before because I did multiprocessing.Process(target=ChildApp().run()).start() when it should be multiprocessing.Process(target=ChildApp().run).start(). The following works

# filename: test.py

from kivy.app import App
from kivy.uix.button import Button

from test2 import ChildApp

import multiprocessing


class MainApp(App):

    def build(self):
        b = Button(text='Launch Child App')
        b.bind(on_press=self.launchChild)
        return b

    def launchChild(self, button):
        app = ChildApp()
        p = multiprocessing.Process(target=app.run)
        p.start()

if __name__ == '__main__':
    MainApp().run()

<小时>

# filename: test2.py

from kivy.app import App
from kivy.uix.label import Label


class ChildApp(App):
    def build(self):
        return Label(text='Child')

if __name__ == '__main__':
    ChildApp().run()

相关文章