Pygtk gtk.Builder.connect_signals to multiple objects?

I am updating some code from using libglade to GtkBuilder, which should be the way of the future.

With gtk.glade, you can call glade_xml.signal_autoconnect(...)several times to connect signals to objects of different classes corresponding to different program windows. However, Builder.connect_signalsit only works once and (therefore) to give warnings about any handlers that are not defined in the first class that passed.

I understand that I can connect them manually, but it seems a little time consuming. (Or, for that matter, I could use getattr hacking so that it can connect them through a proxy to all objects ...)

Is there an error that there is no function for connecting handlers to several objects? Or am I missing something?

Someone has a similar problem http://www.gtkforums.com/about1514.html , which I assume this cannot be done.

+3
source share
4 answers

Here is what I have now. Feel free to use it or suggest something better:

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))
+4
source

I have been looking for a solution to this for some time and found that this can be done by passing the dict of all handlers to connect_signals.

The validation module can retrieve methods using inspect.getmembers(instance, predicate=inspect.ismethod Then they can be combined into a dictionary using d.update(d3), observing repetitive functions such as on_delete.

Code example:

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.

+3

, , , , ;-)

" " -, - (, ) ( aboutDialog). (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"]))
+2
builder.connect_signals
({ 
   "on_window_destroy" : gtk.main_quit, 
   "on_buttonQuit_clicked" : gtk.main_quit 
})
-1

Source: https://habr.com/ru/post/1784337/


All Articles