質問

Libgladeを使用してGtkbuilderに至るまでのコードを更新しています。

GTK.Gladeを使用すると、電話をかけることができます glade_xml.signal_autoconnect(...) プログラム内の異なるウィンドウに対応するさまざまなクラスのオブジェクトに信号を接続するために繰り返し。でも Builder.connect_signals 一度だけ動作しているようで、(したがって)渡されたファーストクラスで定義されていないハンドラーについて警告を出すようにします。

私はそれらを手動で接続できることに気づきましたが、これは少し面倒なようです。 (または、そのことについては、Getattrハッカーを使用して、すべてのオブジェクトにプロキシを介してそれらを接続できるようにすることができます...)

複数のオブジェクトにハンドラーを接続する機能がないバグですか?それとも私は何かが足りませんか?

他の誰かが同様の問題を抱えています http://www.gtkforums.com/about1514.html これは、これができないことを意味します。

役に立ちましたか?

解決

これが私が現在持っているものです。お気軽に使用するか、より良いものを提案してください:

class HandlerFinder(object):
    """Searches for handler implementations across multiple objects.
    """
    # See <http://stackoverflow.com/questions/4637792> for why this is
    # necessary.

    def __init__(self, backing_objects):
        self.backing_objects = backing_objects

    def __getattr__(self, name):
        for o in self.backing_objects:
            if hasattr(o, name):
                return getattr(o, name)
        else:
            raise AttributeError("%r not found on any of %r"
                % (name, self.backing_objects))

他のヒント

私はしばらくの間、これの解決策を探していましたが、すべてのハンドラーのdictを渡すことでできることがわかりました。 connect_signals.

検査モジュールは、使用を使用してメソッドを抽出できますinspect.getmembers(instance, predicate=inspect.ismethodこれらを使用して辞書に連結することができます d.update(d3), 、次のような重複関数に注意してください on_delete.

例コード:

import inspect
...    
handlers = {}
for c in [win2, win3, win4, self]:  # self is the main window
    methods = inspect.getmembers(c, predicate=inspect.ismethod)
    handlers.update(methods)
builder.connect_signals(handlers)

これは、@aliasを使用して宣言されたエイリアスメソッド名をピックアップしません。それを行う方法の例については、builder.pyのコードを参照してください。 def dict_from_callback_obj.

私は初心者だけですが、これは私がしていることです、多分それはインスピレーションを与えることができます;-)

「コントロール」から主要なコンポーネントをインスタンス化し、ビルダーオブジェクトを渡して、インスタンス化されたオブジェクトがビルダーオブジェクト(例のmainWindow)を使用したり、ビルダーに追加したりすることができるようにします。また、各コンポーネントが「信号」を追加する辞書(DIC)も渡します。
次に、「connect_signals(dic)」が実行されます。
もちろん、ユーザー引数をコールバックメソッドに渡す必要がある場合に、手動の信号接続を行う必要がありますが、それらはほとんどありません。

#modules.control.py
class Control:

    def __init__(self):

        # Load the builder obj
        guibuilder = gtk.Builder()
        guibuilder.add_from_file("gui/mainwindow.ui")
        # Create a dictionnary to store signal from loaded components
        dic = {}

        # Instanciate the components...
        aboutdialog = modules.aboutdialog.AboutDialog(guibuilder, dic)           
        mainwin = modules.mainwindow.MainWindow(guibuilder, dic, self)
        ...

        guibuilder.connect_signals(dic)
        del dic


#modules/aboutdialog.py
class AboutDialog:

    def __init__(self, builder, dic):
        dic["on_OpenAboutWindow_activate"] = self.on_OpenAboutWindow_activate
        self.builder = builder

    def on_OpenAboutWindow_activate(self, menu_item):
        self.builder.add_from_file("gui/aboutdialog.ui")
        self.aboutdialog = self.builder.get_object("aboutdialog")
        self.aboutdialog.run()

        self.aboutdialog.destroy()

#modules/mainwindow.py
class MainWindow:

    def __init__(self, builder, dic, controller):

        self.control = controller

        # get gui xml and/or signals
        dic["on_file_new_activate"] = self.control.newFile
        dic["on_file_open_activate"] = self.control.openFile
        dic["on_file_save_activate"] = self.control.saveFile
        dic["on_file_close_activate"] = self.control.closeFile
        ...

        # get needed gui objects
        self.mainWindow = builder.get_object("mainWindow")
        ...

編集:コールバックへの自動添付信号に代わるもの:
テストされていないコード

def start_element(name, attrs):
    if name == "signal":
        if attrs["handler"]:
            handler = attrs["handler"]
            #Insert code to verify if handler is part of the collection
            #we want.
            self.handlerList.append(handler)

def extractSignals(uiFile)
    import xml.parsers.expat
    p = xml.parsers.expat.ParserCreate()
    p.StartElementHandler = self.start_element
    p.ParseFile(uiFile)

self.handlerList = []
extractSignals(uiFile)

for handler in handlerList:
    dic[handler] = eval(''. join(["self.", handler, "_cb"]))
builder.connect_signals
({ 
   "on_window_destroy" : gtk.main_quit, 
   "on_buttonQuit_clicked" : gtk.main_quit 
})
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top