waiting on a callback with PyGTK

Mitch Chapman chapman at bioreason.com
Wed Aug 18 17:33:21 CEST 1999


Rob Hodges wrote:
> 
> I've been playing around with PyGTK and have a little program that
> pops up a dialog with a text entry in it.  When the user hits Enter in
> the text entry, a callback grabs the contents of the entry.
> 
> Now here's my problem: I want the program to sit there doing
> essentially nothing until the callback returns.

Rob,

Here's some sample code showing a solution to your problem.
The short answer is that you need a modal event loop.  (The loop
you showed would never give pygtk a chance to process any X11
events.)

BTW it might be better to route this sort of question to the
pygtk mailing list.  (But I like the fact that you're giving
exposure to pygtk here :)  See 
	http://theopenlab.uml.edu/pygtools/#pygtk-about
for subscription information.

-----------------------------------------------------------------------
#!/usr/bin/env python
"""Demonstrate the use of a modal dialog in pygtk."""

from gtk import *

class ModalDialog:
    """This is just a sample modal dialog."""
    def __init__(self, master=None):
        """Initialize a new instance.
        `master' (optional) is the GtkWindow by which this dialog is
        launched.  `master' is needed only so we can tell the window
        manager that the dialog is a transient window for some other
        window, so it should have transient window decorations."""

        self.master = master

        self.window = GtkDialog()
        if self.master:
            self.window.set_transient_for(self.master)

        # Dialogs come with containers built in: vbox for the custom
        # controls, and action_area for the dialog buttons.
        hbox = GtkHBox()
        self.window.vbox.pack_start(hbox)
        hbox.show()

        l = GtkLabel("Some Text:")
        hbox.pack_start(l, expand=FALSE, fill=FALSE)
        l.show()
            
        self.entry = GtkEntry()
        hbox.pack_start(self.entry)
        self.entry.show()

        self.okBtn = GtkButton("OK")
        self.okBtn.connect("clicked", self.OKCB)
        self.window.action_area.pack_start(self.okBtn, expand=FALSE)
        self.okBtn.show()

        # Tell Gtk+ this is a modal dialog.  Pop it up wherever
        # the mouse is at the time of popup.
        self.window.set_modal(TRUE)
        self.window.set_position(WIN_POS_MOUSE)

    def run(self):
        """Run the modal dialog.  Return whatever the user entered."""
        # This is a little weird.  Basically just run a nested
        # mainloop, and exit the mainloop by mainquit()-ing
        # out of the nested loop.  (See self.OKCB)
        self.window.show()
        mainloop()
        return self.entry.get_text()

    def OKCB(self, *args):
        """Callback invoked when the OK button is clicked."""
        # In theory, this would be a good place to validate user input
        # before committing changes.  In practice...
        self.window.hide()
        mainquit()
        

class AppWindow:
    """This is the controller for the application's main window."""
    def __init__(self):
        """Initialize a new instance -- build a UI and wire it up."""
        self.win = GtkWindow(title="Modal Dialog Example")
        # Exit when the window gets deleted/destroyed.
        self.win.connect("delete_event", mainquit)
        self.win.show()

        self.modalDialog = ModalDialog(self.win)

        # Stick a label into the window to show the results,
        # and a button which displays the modal dialog.
        self.vbox = GtkVBox()
        self.win.add(self.vbox)
        self.vbox.show()

        self.resultLabel = GtkLabel("Result:")
        self.vbox.pack_start(self.resultLabel, fill=FALSE, expand=FALSE)
        self.resultLabel.show()

        self.enterTextBtn = GtkButton("Enter Text...")
        self.enterTextBtn.connect("clicked", self.enterTextCB)
        self.vbox.pack_start(self.enterTextBtn, fill=FALSE,
expand=FALSE)
        self.enterTextBtn.show()

    def enterTextCB(self, *args):
        """Callback invoked when the 'Enter Text...' button is
clicked."""
        result = self.modalDialog.run()
        self.resultLabel.set_text("Result: %s" % result)

def main():
    """Module mainline (for standalone execution)"""
    appwin = AppWindow()
    mainloop()

if __name__ == "__main__":
    main()
-----------------------------------------------------------------------

-- 
Mitch Chapman
chapman at bioreason.com




More information about the Python-list mailing list