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



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

屏幕管理器和弹出选项不会削减它,因为他们住在同一个窗口..我需要能够拖动新屏幕跨多个显示器,因此需要多个窗口。

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

谷歌搜索产生了这样一种简单的方法,即从另一个应用程序中生成一个新应用程序,如下所示:

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:

我得到相同的结果如果我不做ChildApp().run(),而是做multiprocessing.Process(target=ChildApp().run()).start()

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

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

这产生子窗口没有错误,但现在主窗口被锁定(白色画布),如果我关闭子窗口,它只是重新打开。

它们需要能够相互传递数据。关于如何在Windows中正确地做到这一点,有什么想法吗?这篇文章似乎暗示这是可能的,但我不确定从哪里开始。

我尝试了baconwicsand的代码,可以在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()

这里是我正在使用的代码,包括Builder,为两个窗口使用共享的。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_CodesTesting Groundsshared.kv')
        main = MainRoot()
        return main
class OtherApp(App):
    def build(self):
        Builder.load_file('B:Python_CodesTesting Groundsshared.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()

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

你想用subprocess.Popen代替,它不会阻塞。

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

正在使用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()

相关内容

  • 没有找到相关文章

最新更新