I don't know what are Differences between connect() and connect_after() in pygtk. can someone explain this with an example code.
Thanks.
First, here is the definition for g_signal_connect_after:
Connects a GCallback function to a signal for a particular object.The
handler will be called after the default handler of the signal.
But what is the default handler you may ask, well, the GSignal description it's very descritive:
The basic concept of the signal system is that of the emission of a
signal. Signals are introduced per-type and are identified through
strings. Signals introduced for a parent type are available in derived
types as well, so basically they are a per-type facility that is
inherited.
A signal emission mainly involves invocation of a certain set of
callbacks in precisely defined manner. There are two main categories
of such callbacks, per-object ones and user provided ones. (Although
signals can deal with any kind of instantiatable type, I'm referring
to those types as "object types" in the following, simply because that
is the context most users will encounter signals in.) The per-object
callbacks are most often referred to as "object method handler" or
"default (signal) handler", while user provided callbacks are usually
just called "signal handler".
The object method handler is provided at signal creation time (this
most frequently happens at the end of an object class' creation),
while user provided handlers are frequently connected and disconnected
to/from a certain signal on certain object instances.
A signal emission consists of five stages, unless prematurely stopped:
Invocation of the object method handler for G_SIGNAL_RUN_FIRST signals
Invocation of normal user-provided signal handlers (where the after flag is not set)
Invocation of the object method handler for G_SIGNAL_RUN_LAST signals
Invocation of user provided signal handlers (where the after flag is set)
Invocation of the object method handler for G_SIGNAL_RUN_CLEANUP signals
The user-provided signal handlers are called in the order they were connected in.
Now that you know the signal sequence, what follows is the answer to a similar question but on the Gtk mailing list:
g_signal_connect_after will let you run your user handler after the
class's default handler; why is this usefull ?
Say I have an object that emits an "initialize" signal in which its
class handler does the work, you probably want your handler to run
after the class handler so that you can use the already initialized
object in your function.
I think normally you dont have to use this method because signals of
that nature are usually installed with G_SIGNAL_RUN_FIRST which; if
I'm not mistaken means that it's default handler will be called before
user handlers anyway.
Using it on higher level languages may not have an obvious need but, eg., lets say that you want to guarantee that a callback will be the last user callback to run, then you can use this method. (Note pygtk is deprecated, use pygobject).
A simple example where we connect two methods, on_click2 and on_click1 (by this order), by using connect_after for on_click2 we make sure that it will run last (user callbacks):
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class Button(Gtk.Box):
def __init__(self, message):
Gtk.Box.__init__(self, spacing=6)
self.set_border_width(10)
button = Gtk.Button.new_with_label(message)
self.pack_start(button, True, True, 0)
button.connect_after("clicked", self.on_click2)
button.connect("clicked", self.on_click1)
def on_click1(self, widget):
print ("Click1 signal. connect normal");
def on_click2(self, widget):
print ("Click2 signal. connect after");
win = Gtk.Window()
button = Button("Test")
win.add (button)
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
And the result is that on_click2 is the last to be called despite the fact it was the first connected:
$ python <filename.py>
... (Click test button)...
Click1 signal. connect normal
Click2 signal. connect after
Related
I have the following code fragments:
win = new Gtk::Window;
m_canvas = new Goocanvas::Canvas;
sigc::connection conn_t1 = m_canvas->signal_event().connect( sigc::ptr_fun( &AnyEvent));
sigc::connection conn_t2 = win->signal_event().connect( sigc::ptr_fun( &WinHandler));
Now I also register an IdleHandler which generates signals:
Glib::signal_idle().connect( sigc::mem_fun( *this, &IdleSendEvent::Do));
What I want to achieve:
The handler of the canvas should receive an event and should generate a new one and this one should send to the object, so that it will call again the handler of the m_canvas->signal_event().
In other words: Indirectly via the Idle Handler the signal should be send to the sending object itself.
But if I fire to
g_signal_emit_by_name (m_canvas->gobj(), "button-press-event", event, &return_val);
the signal is not received in the canvas itself, but in some child objects there.
Q: How to emmit again to the canvas? Is there something like "get_the_parent_signal_object_handler_father_receiver" or something strange?
I did a lot of gtk_widget_get_parent_window() but all results in runtime errors like:
(go:15430): GLib-GObject-WARNING **: gsignal.c:3484: signal name 'button-press-event' is invalid for instance '0x9afbc48' of type 'GdkX11Window'
I simply have no idea where to find the correct instance which I have to emmit a signal which is then received for the canvas. It looks that the instance for g_signal_emit_by_name fires not to the object itself but all child instances. I can not find a documentation how the signals are processed and how the hierarchy can be walked through. One of the problems is that gtk+ and gtkmm are related but the documentation totally unclear and scattered.
You can't emit a signal to a particular object. You can only emit a signal from an object, that will be received by any signal handlers that are connected to that signal of the emitting object. Objects don't receive signals, only signal handlers do. (Although the signal handler may be, for example, a method of an object.)
The first argument of g_signal_emit_by_name() must be the emitting object.
To make a signal handler receive a signal, use g_signal_connect(emitter, signal_name, handler, user_data) or its C++ equivalent, sigc::signal::connect() as you have done in the example code above.
Is there any way to monitor all signals emitted from a widget with GTK3? I know that the event signal is emitted before an event, but I'm not sure of the distinction between "event" and "signal" in GTK terminology - as this does not seem to capture all signals.
I know GDK has a function gdk_set_show_events but this mostly shows events which are sent to the window from the operating system. Is there a GTK3 equivalent?
There is not built in function AFAIK, but I'm sure you can hack something together yourself:
Use g_signal_lookup to get all signal ids for a gtype. Then use g_signal_add_emission_hook on each signal of your instance to register a hook to be called whenever that particular signal is emitted. Inside the hook function, you're provided with the signal id via *ihint, from which g_signal_query should provide you with all the information you need to print debug messages. (I didn't test it, but it should work)
Note that this will unfortunately not work for signals defined with G_SIGNAL_NO_HOOKS.
Use g_signal_lookup to get all signal ids
It's a little more complicated than described. In order to use g_signal_lookup, you first need a signal-name. If you want to monitor every signal independent of the object-type, you first need to list all signals of the specific instance-type. This can be arranged by g_signal_list_ids for exactly one single GType. To get really ALL signals emitted on the instance, you need to iterate over all parent-types of this instance. You can do this by using g_type_parent.
I have build some utility-functions by myself, that provide this functionality for the same debugging purpose the question was intended. You can connect an Emission-Hook for all signals of a GObject-instance with gemu_glib_util_connect_to_all_signals or connect an emission-Hook to a GtkWidget-instance and all its children with gemu_gtk_util_signal_connect_to_widget_children.
By reading some text, especially the iOS document about delegate, all the protocol method are called hook that the custom delegate object need to implement. But some other books, name these hook as callback, what is the difference between them? Are they just different name but the same mechanism? In addition to Obj-C, some other programming languages, such as C, also got the hook, same situation with Obj-C?
The terminology here is a bit fuzzy. In general the two attempt to achieve similar results.
In general, a callback is a function (or delegate) that you register with the API to be called at the appropriate time in the flow of processing (e.g to notify you that the processing is at a certain stage)
A hook traditionally means something a bit more general that serves the purpose of modifying calls to the API (e.g. modify the passed parameters, monitor the called functions). In this meaning it is usually much lower level than what can be achieved by higher-level languages like Java.
In the context of iOS, the word hook means the exact same thing as callback above
Let me chime in with a Javascript answer. In Javascript, callbacks, hooks and events are all used. In this order, they are each higher level concepts than the other.
Unfortunately, they are often used improperly which leads to confusion.
Callbacks
From a control flow perspective, a callback is a function, usually given as an argument, that you execute before returning from your function.
This is usually used in asynchoronous situations when you need to wait for I/O (e.g. HTTP request, a file read, a database query etc.). You don't want to wait with a synchronous while loop, so other functions can be executed in the meantime.
When you get your data, you (permanently) relinquish control and call the callback with the result.
function myFunc(someArg, callback) {
// ...
callback(error, result);
}
Because the callback function may be some code that hasn't been executed yet, and you don't know what's above your function in the call stack, generally instead of throwing errors you pass on the error to the callback as an argument. There are error-first and result-first callback conventions.
Mostly callbacks have been replaced by Promises in the Javascript world and since ES2017+, you can natively use async/await to get rid of callback-rich spaghetti code and make asynchronous control flow look like it was synchronous.
Sometimes, in special cascading control flows you run callbacks in the middle of the function. E.g. in Koa (web server) middleware or Redux middleware you run next() which returns after all the other middlewares in the stack have been run.
Hooks
Hooks are not really a well-defined term, but in Javascript practice, you provide hooks when you want a client (API/library user, child classes etc.) to take optional actions at well-defined points in your control flow.
So a hook may be some function (given as e.g. an argument or a class method) that you call at a certain point e.g. during a database update:
data = beforeUpdate(data);
// ...update
afterUpdate(result);
Usually the point is that:
Hooks can be optional
Hooks usually are waited for i.e. they are there to modify some data
There is at most one function called per hook (contrary to events)
React makes use of hooks in its Hooks API, and they - quoting their definition - "are functions that let you “hook into” React state and lifecycle features", i.e. they let you change React state and also run custom functions each time when certain parts of the state change.
Events
In Javascript, events are emitted at certain points in time, and clients can subscribe to them. The functions that are called when an event happens are called listeners - or for added confusion, callbacks. I prefer to shun the term "callback" for this, and use the term "listener" instead.
This is also a generic OOP pattern.
In front-end there's a DOM interface for events, in node.js you have the EventEmitter interface. A sophisticated asynchronous version is implemented in ReactiveX.
Properties of events:
There may be multiple listeners/callbacks subscribed (to be executed) for the same event.
They usually don't receive a callback, only some event information and are run synchronously
Generally, and unlike hooks, they are not for modifying data inside the event emitter's control flow. The emitter doesn't care 'if there is anybody listening'. It just calls the listeners with the event data and then continues right away.
Examples: events happen when a data stream starts or ends, a user clicks on a button or modifies an input field.
The two term are very similar and are sometimes used interchangably. A hook is an option in a library were the user code can link a function to change the behavior of the library. The library function need not run concurrent with the user code; as in a destructor.
A callback is a specific type of hook where the user code is going to initiate the library call, usually an I/O call or GUI call, which gives contol over to the kernel or GUI subsystem. The controlling process then 'calls back' the user code on an interupt or signal so the user code can supply the handler.
Historically, I've seen hook used for interupt handlers and callback used for GUI event handlers. I also see hook used when the routine is to be static linked and callback used in dynamic code.
Two great answers already, but I wanted to throw in one more piece of evidence the terms "hook" and "callback" are the same, and can be used interchangeably: FreeRTOS favors the term "hook" but recognizes "callback" as an equivalent term, when they say:
The idle task can optionally call an application defined hook (or callback) function - the idle hook.
The tick interrupt can optionally call an application defined hook (or callback) function - the tick hook.
The memory allocation schemes implemented by heap_1.c, heap_2.c, heap_3.c, heap_4.c and heap_5.c can optionally include a malloc() failure hook (or callback) function that can be configured to get called if pvPortMalloc() ever returns NULL.
Source: https://www.freertos.org/a00016.html
In the past, I have used libraries that would allow me to register a callback so that the library can call my method when some event happens (e.g. it is common to see in code that use GUI libraries to look like button.onClick(clickHandler)).
Naively, I suppose the library's handling mechanism could be implemented like:
while(1){
if (event1) { event1Handler(); }
if (event2) { event2Handler(); }
...
}
but that would be really wasteful right? Or is that really how it is done (for instance do well known GUI libraries like java swing, or GTK+ do it this way)?
background:
This question hadn't really occured to me until I encountered curses. I thought about implementing my own callback system, until I realized I didn't know how.
The while loop will typically wait for an interrupt from the user (GetMessage in Windows). When an interrupt arrives GetMessage returns and then it ends up in the callback function. The if statements are typically implemented as a switch-case. See Windows Message Loop on Wikipedia.
In more detail, what happens is the following:
The user application calls GetMessage, which forces the process to sleep until an input message for that application arrives from the systems queue. When a message arrives, the user app calls DispatchMessage, which calls the callback function associated with the window that the message was aimed at.
Windows API uses one callback which handles all events in a switch case. Other libraries use one callback per event class instead.
The function pointers themselves are stored together with other window data in a struct.
Callback system implementation probably has different implementation in different technologies, however, I suppose they should be working this way:
A data structure stores the callback IDs and pointers to the handlers.
A callback handler has a validator
Event handlers have callback callers, which know what are the possible callbacks and check their validity this way:
for each callback in event.callbacks
if (callback.isValid())
call callback()
end if
end for
When you add a handler to a function the system will automatically know where the callback is valid and will add the callback to the datastructure described in 1.
Correct me if I'm wrong, this description is just a guess.
Is it a function?
Is it a function being called from the source?
Or, is it a function being returned from the destination?
Or, is it just executing a function at the destination?
Or, is it a value returned from a function passed to the destination?
A callback is the building block of asynchronous processing.
Think of it this way: when you call someone and they don't answer, you leave a message and your phone number. Later on, the person calls you back based on the phone number you left.
A callback works in a similar manner.
You ask an API for a long running operation and you provide a method from within your code to be called with the result of the operation. The API does its work and when the result is ready, it calls your callback method.
From the great Wikipedia:
In computer programming, a callback is
executable code that is passed as an
argument to other code. It allows a
lower-level software layer to call a
subroutine (or function) defined in a
higher-level layer.
Said another way, when you pass a callback to your method, it's as if you are providing additional instructions (e.g., what you should do next). An attempt at making a simple human example follows:
Paint this wall this shade of green (where "paint" is analagous to the method called, while "wall" and "green" are similar to arguments).
When you have finished painting, call me at this number to let me know that you're done and I'll tell you what to do next.
In terms of practical applications, one place where you will sometimes see callbacks is in situations with asynchronous message passing. You might want to register a particular message as an item of interest for class B.
However, without something like a callback, there's no obvious way for class A to know that class B has received the message. With a callback, you can tell class B, here's the message that I want you to listen for and this is the method in class A that I want you to call when you receive it.
Here is a Java example of a callback from a related question.