0

これは、GUIでやろうとしていることのモックアップ版です。コールバック メソッドの実行中にどこかで作成される MessageDialog があります。私の問題は、コールバック メソッドの実行が終了するまで MessageDialog が閉じないことです。

ダイアログを破棄すると予想される「dialog.destroy()」があります。「はい/いいえ」をクリックするとボタンが押されますが、「_go」が終了するまでダイアログは消えません。

「time.sleep(4)」は、MessageDialog インタラクションが終了した後に「_go」メソッドで発生する他のことをシミュレートするためにそこにあります。

from gi.repository import Gtk, GObject
import time

class Gui(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete_event", Gtk.main_quit)
        self.set_size_request(700, 600)
        notebook = Gtk.Notebook()
        notebook.set_tab_pos(Gtk.PositionType.TOP)
        notebook.append_page(MyTab(), Gtk.Label("A tab"))
        self.add(notebook)
        notebook.show_all()
        self.show()

class MyTab(Gtk.VBox):
    def __init__(self):
        super(MyTab, self).__init__()
        self.go_button = Gtk.Button()
        self.go_button.add(Gtk.Image().new_from_stock(Gtk.STOCK_APPLY,
                                                 Gtk.IconSize.BUTTON))
        top_box = Gtk.HBox()
        top_box.pack_start(self.go_button, False, True, 5)
        self.pack_start(top_box, False, True, 5)

        # setup callbacks
        self.go_button.connect("clicked", self._go)

    def _go(self, _):
        dialog = Gtk.MessageDialog(Gtk.Window(), 
                                   Gtk.DialogFlags.MODAL,
                                   Gtk.MessageType.QUESTION,
                                   Gtk.ButtonsType.YES_NO,
                                   "RESPONSE REQUIRED")
        dialog.format_secondary_text("are you having fun?")
        response = dialog.run()
        dialog.destroy()
        print "your response is: " + str(response)
        time.sleep(4)
        print "left _go"

def main():
    """
    Main entry point.
    """
    Gui()
    Gtk.main()

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

3 に答える 3

3

This problem is not specific to dialogs. Any GUI change is invisible until you return to the main loop and give the system a chance to process the events accumulated by modifying the widgets.

If you really want to update the GUI immediately in the callback, you can manually spin the accumulated events with a loop like this after the call to dialog.destroy():

while Gtk.events_pending():
    Gtk.main_iteration()

However, be aware that this will not only update the screen, but also run other accumulated events, including idle and timeout handlers and button click callbacks (if any are pending). That can have unexpected consequences.

于 2013-02-16T08:02:29.600 に答える
1

これは正しい動作です。ウィンドウが消えるのは、_goコールバックの最後にのみ発生するGtkのメインループに制御が戻された場合のみです。

于 2013-02-15T11:40:45.640 に答える
1

user4815162342 の回答に関するコメント に従って、ネストされたメイン ループを使用するソリューションを思いつきました。このクラスは、ダイアログを受け取り、run メソッドを提供します。

class NestedDialog(object):
    def __init__(self, dialog):
        self.dialog = dialog
        self.response_var = None

    def run(self):
        self._run()
        return self.response_var

    def _run(self):
        self.dialog.show()
        self.dialog.connect("response", self._response)
        Gtk.main()

    def _response(self, dialog, response):
        self.response_var = response
        self.dialog.destroy()
        Gtk.main_quit()

ダイアログは次のように実行されます。

def _go(self, _):
    dialog = Gtk.MessageDialog(Gtk.Window(), 
               Gtk.DialogFlags.MODAL,
               Gtk.MessageType.QUESTION,
               Gtk.ButtonsType.YES_NO,
               "RESPONSE REQUIRED")
    dialog.format_secondary_text("are you having fun?")
    nested_dialog = NestedDialog(dialog)
    response = nested_dialog.run()
    print "your response is: " + str(response)
    time.sleep(4)
    print "left _go"
于 2013-02-19T00:37:19.297 に答える