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

qncylg1j  于 2023-02-15  发布在  Python
关注(0)|答案(4)|浏览(170)

我希望我的Kivy应用程序能够在Windows机器上产生多个可以相互通信的应用程序(iIndiee. new windows)。
ScreenManagerPopup选项不会削减它,因为他们住在同一个窗口。。我需要能够拖动新屏幕跨越多个显示器,因此需要多个窗口。
Kivy文档明确指出"Kivy supports only one window per application: please don't try to create more than one."
一个谷歌搜索产生this simple approach的简单产卵一个新的应用程序从另一个应用程序,像这样:

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()

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

Original exception was:
Error in sys.exceptionhook:

如果我用multiprocessing.Process(target=ChildApp().run()).start()代替ChildApp().run(),我会得到同样的结果
使用subprocess库使我更接近我想要的:
一个二个一个一个
这会毫无错误地生成子窗口,但是现在主窗口被锁定(白色画布),如果我关闭子窗口,它就会重新打开。
它们需要能够在彼此之间传递数据。关于如何在Windows中正确地做到这一点有什么想法吗?这个post似乎表明这是可能的,但我不知道从哪里开始。

mwkjh3gx

mwkjh3gx1#

我尝试了baconwichsand的代码,可以确认在Python 3.6和Windows 10中它不起作用。显然只有顶级对象类可以pickle,而且由于这两个应用都继承自App类,python抛出了一个错误。然而,一个只执行ChildApp().run()命令的顶级定义可以pickle并起作用。下面是我的工作代码。

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

class MainApp(App):
    def build(self):
        return Label(text='Main App Window')

class OtherApp(App):
    def build(self):
        return Label(text='Other App Window')

def open_parent():
    MainApp().run()

def open_child():
    OtherApp().run()

if __name__ == '__main__':
    a = multiprocessing.Process(target=open_parent)
    b = multiprocessing.Process(target=open_child)
    a.start()
    b.start()

这是我正在使用的代码,包括为两个窗口使用共享的.kv文件的构建器。

import multiprocessing
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.widget import Widget

class MainRoot(Widget):
    pass

class OtherRoot(Widget):
    pass

class MainApp(App):
    def build(self):
        Builder.load_file('B:\Python_Codes\Testing Grounds\shared.kv')
        main = MainRoot()
        return main

class OtherApp(App):
    def build(self):
        Builder.load_file('B:\Python_Codes\Testing Grounds\shared.kv')
        other = OtherRoot()
        return other

def open_parent():
    MainApp().run()

def open_child():
    OtherApp().run()

if __name__ == '__main__':
    a = multiprocessing.Process(target=open_parent)
    b = multiprocessing.Process(target=open_child)
    a.start()
    b.start()
798qvoo8

798qvoo82#

我不知道为什么它不能和多处理一起工作(我从来没有尝试过),但是它至少应该和subprocess一起工作,主窗口被锁定的原因是subprocess.call在等待子进程完成并返回结果时阻塞了调用它的线程。
您希望改用subprocess.Popen,它不会阻塞。

hjzp0vay

hjzp0vay3#

bj0关于子进程的回答正确。
更棒的是,我找到了如何通过多处理来实现这一点,这样可以更好地在应用程序之间进行通信和传递信息。以前它不起作用,因为我在应该是multiprocessing.Process(target=ChildApp().run).start()的时候使用了multiprocessing.Process(target=ChildApp().run()).start()

# 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()
sg2wtvxw

sg2wtvxw4#

使用Ubuntu Python 3.10
在多进程中调用子进程。
main.py

import multiprocessing
import subprocess
import shlex  
  
#my kivy code..

def sub_window():
    subprocess.call(shlex.split('python3 test.py'))
if __name__ == '__main__':
    b = multiprocessing.Process(target=sub_window)
    b.start()
    MyApp().run()

test.py

#another kivy app script..
OtherApp().run()

相关问题