我希望我的Kivy应用程序能够在可以相互通信的Windows机器上生成多个应用程序(即新窗口)。
ScreenManager和Popup选项不会削减它,因为它们位于同一个窗口中。我需要能够在多个监视器上拖动新屏幕,因此需要多个窗口。
Kivy docs明确声明"Kivy supports only one window per application: please don't try to create more than one."
Google搜索会在另一个应用中生成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:
如果不是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中正确执行此操作的任何想法?这post似乎表明这是可能的,但我不知道从哪里开始。
答案 0 :(得分:3)
我尝试过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()
这是我正在使用的代码,包括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_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()
答案 1 :(得分:1)
我不确定为什么它不能用于多处理(我从未尝试过),但它至少应该与subprocess
一起使用。主窗口被锁定的原因是因为subprocess.call
在等待子进程完成并返回结果时阻塞调用它的线程。
您想要使用subprocess.Popen
,而不是阻止。
答案 2 :(得分:1)
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()
/token (creates capability for making calls - seems like this is where I pass in who is doing the call??)
/call (create twiml for Dial/Number)
/callstatus (handles status when call is over - intention is to perform some action on my backend to uupdate the specfic user account that started the call)