pyGTK一次运行2个“主循环”

时间:2013-04-05 21:09:30

标签: python loops gtk main

我正在编写一个pyGTK程序,其中包括(允许用户)从列表中选择和运行第二个程序。我想启动用户选择的程序作为一个完全独立的进程与它自己的主循环,但我不确定这是一个安全的事情。我运行了一个快速测试(见下文),它似乎是安全的,但我没有做很多GUI编程,所以我知道可能有一些我没想到的东西。我找不到任何解决这个问题的教程,所以我想在得到太深入之前我会问。

一旦第二个程序启动,这两个程序就不需要说话了。

这是我试过的测试。

import gtk
import numpy as np

class TopGUI(gtk.Window):
    def __init__(self):
        super(TopGUI,self).__init__()
        parentLabel = gtk.Label('I am the father')
        newWindowBtn = gtk.Button('meet my brother')
        vBox1 = gtk.VBox(False,4)
        vBox1.pack_start(parentLabel, True, True, 4)
        vBox1.pack_start(newWindowBtn, True, True, 4)

        newWindowBtn.connect("clicked", self.on_clicked) # 0p3n Br07h3r loop on butt0n pre55

        self.add(vBox1)
        self.show_all()
        self.startItUp

    def on_clicked(self, leButton):
        broWin = SecondGUI()
        broWin.startItUp

    def startItUp(self):
        gtk.main()

class SecondGUI(gtk.Window):
    bigthing = None
    def __init__(self):
        super(SecondGUI,self).__init__()
        brotherLabel = gtk.Label('I am the 3\/1L U|\|kl3. I D3v0ur M3M0ry!')
        spinner = gtk.Spinner()
        vBox1 = gtk.VBox(True,4)
        vBox1.pack_start(brotherLabel, True, True, 4)
        vBox1.pack_start(spinner, True, True, 4)
        spinner.start()

        self.add(vBox1)
        self.show_all()
        self.bigthing = np.zeros([10000,10000])

    def startItUp(self):
        gtk.main()


fatherLoop = TopGUI()

对于后代,这是实施 abarnert's 解决方案的测试代码的改进版本。

import gtk
import numpy as np
import multiprocessing

class TopGUI(gtk.Window):
    def __init__(self):
        super(TopGUI,self).__init__()
        parentLabel = gtk.Label('I am the father')
        newWindowBtn = gtk.Button('meet my brother')
        vBox1 = gtk.VBox(False,4)
        vBox1.pack_start(parentLabel, True, True, 4)
        vBox1.pack_start(newWindowBtn, True, True, 4)

        newWindowBtn.connect("clicked", self.on_clicked) # 0p3n Br07h3r loop on butt0n pre55
        self.connect("destroy", gtk.main_quit)

        self.add(vBox1)
        self.show_all()
        self.startItUp()

    def on_clicked(self, leButton):
        self.childProcess = multiprocessing.Process(target=child_main)
        self.childProcess.start()

    def startItUp(self):
        gtk.main()

class SecondGUI(gtk.Window):
    bigthing = None
    def __init__(self):
        super(SecondGUI,self).__init__()
        brotherLabel = gtk.Label('I am the 3\/1L U|\|kl3. I D3v0ur M3M0ry!')
        spinner = gtk.Spinner()
        vBox1 = gtk.VBox(True,4)
        vBox1.pack_start(brotherLabel, True, True, 4)
        vBox1.pack_start(spinner, True, True, 4)
        spinner.start()

        self.add(vBox1)
        self.show_all()
        self.bigthing = np.zeros([10000,10000])

        self.connect("destroy", gtk.main_quit)
        self.startItUp()

    def startItUp(self):
        gtk.main()

def parent_main():
    fatherLoop = TopGUI()

def child_main():
    broWin = SecondGUI()

if __name__ == '__main__':
    parent_main()

1 个答案:

答案 0 :(得分:2)

  

我想启动用户选择的程序作为一个完全独立的进程,使用它自己的主循环,但我不确定这是否安全。

是的,那是安全的,事实上它可能正是你想要的。除非你不愿意(通过fd继承,共享内存,管道等),否则单独的进程不会共享任何内容。

但是你的代码没有这样做,甚至没有尝试这样做。没有什么可以开始一个孩子的过程;您只需在同一个解释器中创建一个新对象。因此,一旦启动第二个GUI,它将最终运行自己的gtk.main(),使第一个GUI挂起,直到第二个退出。

但您只是在所有地方引用self.startItUp(和broWin.startItUp)而不是调用self.startItUp()。所以第二个GUI永远不会启动,一切都是“安全的”,从根本上说,什么都不做总是安全的。

您可能想要使用multiprocessing。首先,您不能只在顶层执行fatherLoop = TopGUI(),因为这样每个流程都可能最终运行它。 (它是否依赖于实现/平台。)然后,您需要显式创建Process并为子项启动它。所以,像这样:

class TopGUI(gtk.Window):
    # ...
    def on_clicked(self, leButton):
        self.child = multiprocessing.Process(target=child_main)
        self.child.start()
    # ...

def parent_main():
    fatherLoop = TopGUI()

def child_main():
    broWin = SecondGUI()

if __name__ == '__main__':
    parent_main()

我假设您要修改代码,以便构建TopGUI()SecondGUI()来电self.startItUp()