Running multiple Kivy apps at same time that communicate with each other

前端 未结 3 1193
梦谈多话
梦谈多话 2020-12-15 12:45

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 and Po

相关标签:
3条回答
  • 2020-12-15 13:22

    bj0's answer regarding subprocess was correct.

    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()
    
    0 讨论(0)
  • 2020-12-15 13:31

    I'm not sure why it doesn't work with multiprocessing (I've never tried it), but it should at least work with subprocess. The reason your main window is locked is because subprocess.call blocks the thread that calls it while it waits for the subprocess to finish and return a result.

    You want to use subprocess.Popen instead, which does not block.

    0 讨论(0)
  • 2020-12-15 13:32

    I tried baconwichsand's code and can confirm with Python 3.6 and Windows 10 it does not work. Apparently only top level object classes can be pickled, and since both apps inherit from the App class python throws an error. However a top level definition that simply executes the ChildApp().run() command can be pickled and works. Here is my working code.

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

    And here is the code I am using, including the Builder to use a shared .kv file for both windows.

    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()
    
    0 讨论(0)
提交回复
热议问题