Using a GTK window and waiting for the response

2019-08-28 16:36发布

I am using PyGTK inside another application to take user input. I am building an window which has lots of Check Buttons and according to response I need to go ahead.

The problem is that in python when I call the function of window and its operation, the program doesn't wait for the response from window? How do I make it able to wait for the response from the window??

I also don't know if I can use a dialog instead of window because I tried adding check buttons to dialog and it did not work out well. If using window is not appropriate than can anybody help me with dialog?

Thanks for your help.

2条回答
女痞
2楼-- · 2019-08-28 16:54

In this answer you have an example using callback functions: How can I pass variables between two classes/windows in PyGtk?

After you confirm the called window, you execute the callback function of the caller window/object.

查看更多
放荡不羁爱自由
3楼-- · 2019-08-28 17:06

(Oldish question, but it deserves an answer)

While pmoleri gave an acceptable answer (which is how I initially handled this case) I find that it is kind of frustrating to add a callback because it obfuscates the program flow. It's neat to have a window that acts like gtk.Dialog, where you can call window.run() and it will block there until you get a response, but the GUI will still run. You can do this functionality yourself with gtk.main():

import gtk
class BlockingWindow(gtk.Window):
    def __init__(self,checkmark_values):
        gtk.Window.__init__(self)
        self.checkmarks = {}
        # Create check marks here, put them in a dictionary
        # relating their name to their widget
        # Also create ok button
        ok_button.connect("clicked",self.on_ok_button_clicked)

    def on_ok_button_clicked(self,button):
        gtk.main_quit()

    def run(self):
        self.show_all()
        gtk.main()
        self.destroy()
        return dict((x,self.checkmarks[x].get_active()) for x in self.checkmarks)

blocking_window = BlockingWindow(["option1","option2"])
values = blocking_window.run()
print "option1 is {}".format(values["option1"])
print "option2 is {}".format(values["option2"])

gtk.main can be nested, so this pattern will work even inside of another GUI window, e.g. doing the same thing from your main window (obviously the name "run" is not special, you may want to rename it something more pertinent, like "get_values" or something).

As for using dialog, you can do that as well, to add widgets to a dialog window, you can reference the dialog's "vbox" attribute, i.e. self.vbox.pack_start(my_checkbox). Usually I'll use a dialog in conjunction with this technique so I don't have to create the buttons myself. In that case, instead of connecting to clicked on ok_button, you can connect to response on the dialog (self) and read the response code to know what you want to return, generally setting an object variable to the response value and handling it back in run, e.g. return None if you find that the user clicked cancel.

Edit: I should also mention that this works not just for other windows, but for any action you want to block your code on but not freeze up the GUI. For instance, I used this pattern in conjunction with gobject.timeout_add to animate a progress bar representing git cloning. Using this, I was able to create a single function that would clone n repositories using a single for loop, instead of stringing them along with callbacks. It's a very powerful pattern, really.

查看更多
登录 后发表回答