SpinButton: how to avoid calling signal handler when set_value()
I have a SpinButton with an associated Adjustment. I connected a handler for "value-changed" signal, because I have to make something when the user changes the value. I sometimes need to change the value in the code, using set_value() method of SpinButton or Adjustment. In this case, I don't want to execute the signal handler. I will try to describe the situation. I have many widgets on the window, mainly SpinButton (but I have Entry too). I retrieve the values from remote, so I use set_value() methods for each widget when the values are received. The user can change some values and I need to detect this, because I have to send the new values to remote. So I have to connect a custom signal handler. Of course, I have to avoid calling the signal handler when the values are changed by code. Is it possible? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Have you tried g_signal_handler_block (gpointer instance, gulong handler_id); and g_signal_handler_unblock (gpointer instance, gulong handler_id); Putting these before and after your set_value() should temporarily block the handler. You get the handler_id from g_signal_connect(...): handler_id = g_signal_connect(...); On 11/01/16 11:29, pozzugno wrote: I have a SpinButton with an associated Adjustment. I connected a handler for "value-changed" signal, because I have to make something when the user changes the value. I sometimes need to change the value in the code, using set_value() method of SpinButton or Adjustment. In this case, I don't want to execute the signal handler. I will try to describe the situation. I have many widgets on the window, mainly SpinButton (but I have Entry too). I retrieve the values from remote, so I use set_value() methods for each widget when the values are received. The user can change some values and I need to detect this, because I have to send the new values to remote. So I have to connect a custom signal handler. Of course, I have to avoid calling the signal handler when the values are changed by code. Is it possible? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
I already thought of blocking handlers during refresh, but it means adding two instructions (_block and _unblock) for each set_value(). A simple and clear sequence of instructions: _set_value() _set_value() .. will be transformed in a complex, long and cryptic sequence of instructions: _block() _set_value() _unblock() _block() _set_value() _unblock() I hoped there was another better solution. Actually I'm using a flag that is checked in the handler: refreshing = True _set_value() _set_value() ... refreshing = False # In the handler if not refreshing: # Process the handler This is simple enough, but I have to remember to check the flag in the handler and this is error prone. Il 01/11/2016 20:33, Chris Moller ha scritto: Have you tried g_signal_handler_block (gpointer instance, gulong handler_id); and g_signal_handler_unblock (gpointer instance, gulong handler_id); Putting these before and after your set_value() should temporarily block the handler. You get the handler_id from g_signal_connect(...): handler_id = g_signal_connect(...); On 11/01/16 11:29, pozzugno wrote: I have a SpinButton with an associated Adjustment. I connected a handler for "value-changed" signal, because I have to make something when the user changes the value. I sometimes need to change the value in the code, using set_value() method of SpinButton or Adjustment. In this case, I don't want to execute the signal handler. I will try to describe the situation. I have many widgets on the window, mainly SpinButton (but I have Entry too). I retrieve the values from remote, so I use set_value() methods for each widget when the values are received. The user can change some values and I need to detect this, because I have to send the new values to remote. So I have to connect a custom signal handler. Of course, I have to avoid calling the signal handler when the values are changed by code. Is it possible? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Il Wed, 2 Nov 2016 00:09:29 +0100 pozzugno scrisse: > ... > A simple and clear sequence of instructions: > >_set_value() >_set_value() >.. > > will be transformed in a complex, long and cryptic sequence of > instructions: > >_block() >_set_value() >_unblock() >_block() >_set_value() >_unblock() Hi, I hope you are missing some fundamental detail because this is a non-problem. _my_set_value() _block() _set_value() _unblock _my_set_value() _my_set_value() > I hoped there was another better solution. Actually I'm using a flag > that is checked in the handler: > >refreshing = True >_set_value() >_set_value() >... >refreshing = False This is not equivalent to what you wrote above. This is (roughly) equivalent to: _block() _set_value() _set_value() ... _unblock() A minimal test case exposing the problem would be much clearer. Ciao. -- Nicola ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Il Wed, 2 Nov 2016 10:23:44 +0100 Pozz Pozz scrisse: > ... > How do you implement the generic function _my_set_value()? It should have > two parameters: spinbutton and value. signal_handler_block() function needs > the handler_id associated that I don't have. > Maybe during initialization, when I connected the handlers, I could create > a data structure (a list) with spinbuttons and associated handler_id. In > this way, _my_set_value() could accept the item of the list and could > recover the handler_id to block. > > However there is another problem with this approach. I'm using Glade and I > connect *all* the handlers with a single instruction: > builder.connect_signals(). So I don't have the handler IDs. > ... Hi, you don't necessarily need the handler id. In C (I don't use python) you could write the following: void my_set_value(GtkSpinButton *spin_button, gdouble value) { g_signal_handlers_block_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); /* This will not trigger callback_to_skip */ gtk_spin_button_set_value(spin_button, value) g_signal_handlers_unblock_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); } Not tested, but should give you the idea. Ciao. -- Nicola ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Il Wed, 2 Nov 2016 14:40:58 +0100 Pozz Pozz scrisse: > 2016-11-02 11:24 GMT+01:00 Nicola Fontana : > > ... > > > > you don't necessarily need the handler id. In C (I don't use > > python) you could write the following: > > > > void my_set_value(GtkSpinButton *spin_button, gdouble value) > > { > > g_signal_handlers_block_matched(spin_button, > > G_SIGNAL_MATCH_FUNC, > > 0, 0, NULL, > > callback_to_skip, > > NULL); > > > > /* This will not trigger callback_to_skip */ > > gtk_spin_button_set_value(spin_button, value) > > > > g_signal_handlers_unblock_matched(spin_button, > > G_SIGNAL_MATCH_FUNC, > > 0, 0, NULL, > > callback_to_skip, > > NULL); > > } > > > > I got the idea. I don't know if g_signal_handlers_block_matched() or > similar functionality is available in Python. However, remaining in C, your > code make the assumption there is a single callback function for all the > spinbuttons. This is not true: I have a different handler for each > spinbutton, because I have to make different things. Sorry but I am a developer, not a mind reader. You can match by data or try to lookup the callback by detail with g_signal_handler_find or refactor your code to use a single callback. The fact that you are using different callbacks has a foul smell indeed. Come on, a little bit of initiative. Here, today only, the link to the official (C) documentation: https://developer.gnome.org/gobject/stable/gobject-Signals.html Ciao. -- Nicola ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Il 02/11/2016 18:55, Nicola Fontana ha scritto: Il Wed, 2 Nov 2016 14:40:58 +0100 Pozz Pozz scrisse: 2016-11-02 11:24 GMT+01:00 Nicola Fontana : ... you don't necessarily need the handler id. In C (I don't use python) you could write the following: void my_set_value(GtkSpinButton *spin_button, gdouble value) { g_signal_handlers_block_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); /* This will not trigger callback_to_skip */ gtk_spin_button_set_value(spin_button, value) g_signal_handlers_unblock_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); } I got the idea. I don't know if g_signal_handlers_block_matched() or similar functionality is available in Python. However, remaining in C, your code make the assumption there is a single callback function for all the spinbuttons. This is not true: I have a different handler for each spinbutton, because I have to make different things. Sorry but I am a developer, not a mind reader. Yes, of course :-) Thank you for spending some time for me. I thought using a different callback for each SpinButton was the more typical solution. You can match by data or try to lookup the callback by detail with g_signal_handler_find or refactor your code to use a single callback. It seems pyGObject implementation gives only two "handler block" functions: handler_block(), that needs the handler_id that I don't have; handler_block_by_func() that needs the callback to block (the same problem of your solution, because I have different callbacks). Is it possible to retrieve the list of connected callbacks of an object and a signal name ("value-changed")? The fact that you are using different callbacks has a foul smell indeed. Yes? I have to generate and send a different request to the device. Why do you think it's better to have a single callback? Of course, I could write one single callback as: def callback(self, spinbutton): if spinbutton is spinSetting1: self.callback_setting1(spinbutton) elif spinbutton is spinSetting2: self.callback_setting2(spinbutton) ... def callback_setting1(self,spinbutton): # This is the callback of the spinbutton associated to setting1 parameter set_setting1(spinbutton.get_value()) It seems to me a more complicated way to write different callbacks. IMHO the solution to use a refreshing flag is the simplest solution, even if a little dirty. Alternatively, I have to create a list of spinbuttons *and* callbacks and search for the callback to unblock in your suggested function my_set_value(). Come on, a little bit of initiative. Here, today only, the link to the official (C) documentation: https://developer.gnome.org/gobject/stable/gobject-Signals.html Please, don't think I don't use to read documentation. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
On 11/02/2016 05:19 PM, pozzugno wrote: > It seems pyGObject implementation gives only two "handler block" > functions: handler_block(), that needs the handler_id that I don't have; > handler_block_by_func() that needs the callback to block (the same > problem of your solution, because I have different callbacks). Usually when you connect a signal, the return value from the connect call is the handler_id. Can you save this value somewhere for future use? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Op 11/03/2016 om 12:19 AM schreef pozzugno: > Il 02/11/2016 18:55, Nicola Fontana ha scritto: >> Il Wed, 2 Nov 2016 14:40:58 +0100 Pozz Pozz >> scrisse: >> >>> 2016-11-02 11:24 GMT+01:00 Nicola Fontana : ... you don't necessarily need the handler id. In C (I don't use python) you could write the following: void my_set_value(GtkSpinButton *spin_button, gdouble value) { g_signal_handlers_block_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); /* This will not trigger callback_to_skip */ gtk_spin_button_set_value(spin_button, value) g_signal_handlers_unblock_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); } >>> I got the idea. I don't know if g_signal_handlers_block_matched() or >>> similar functionality is available in Python. However, remaining in >>> C, your >>> code make the assumption there is a single callback function for all >>> the >>> spinbuttons. This is not true: I have a different handler for each >>> spinbutton, because I have to make different things. >> Sorry but I am a developer, not a mind reader. > Yes, of course :-) Thank you for spending some time for me. > > I thought using a different callback for each SpinButton was the more > typical solution. > >> You can match by data or try to lookup the callback by detail with >> g_signal_handler_find or refactor your code to use a single >> callback. > It seems pyGObject implementation gives only two "handler block" > functions: handler_block(), that needs the handler_id that I don't > have; handler_block_by_func() that needs the callback to block (the > same problem of your solution, because I have different callbacks). > > Is it possible to retrieve the list of connected callbacks of an > object and a signal name ("value-changed")? > >> The fact that you are using different callbacks has a >> foul smell indeed. > Yes? I have to generate and send a different request to the device. > Why do you think it's better to have a single callback? > Of course, I could write one single callback as: > > def callback(self, spinbutton): > if spinbutton is spinSetting1: > self.callback_setting1(spinbutton) > elif spinbutton is spinSetting2: > self.callback_setting2(spinbutton) > ... > > def callback_setting1(self,spinbutton): > # This is the callback of the spinbutton associated to setting1 > parameter > set_setting1(spinbutton.get_value()) > > It seems to me a more complicated way to write different callbacks. > Do you know you can subclass Gtk.SpinButton and override the virtual methods [1] and emit your own custom signal at the time you want it based of some attribute? There are some example on the internets but not much. Ironically the most complete imo is the old pygtk one [2] and gtk3 read the docs is not horrible [3]. And I want to reiterate what Nicola said, create a small example with only 2 or 3 buttons that shows what you are truing to do. It works much easier that way and we do not have to read minds. ~infirit [1] https://lazka.github.io/pgi-docs/#Gtk-3.0/classes/SpinButton.html#virtual-methods [2] http://www.pygtk.org/articles/writing-a-custom-widget-using-pygtk/writing-a-custom-widget-using-pygtk.htm [3] http://python-gtk-3-tutorial.readthedocs.io/en/latest/objects.html ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Il 03/11/2016 00:48, Michael Torrie ha scritto: On 11/02/2016 05:19 PM, pozzugno wrote: It seems pyGObject implementation gives only two "handler block" functions: handler_block(), that needs the handler_id that I don't have; handler_block_by_func() that needs the callback to block (the same problem of your solution, because I have different callbacks). Usually when you connect a signal, the return value from the connect call is the handler_id. Can you save this value somewhere for future use? As I wrote in one of my previous post, I use GtkBuilder to create widgets and GtkBuilder.connect_signals() method to connect signal handlers all together. So I don't have handler ids. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: SpinButton: how to avoid calling signal handler when set_value()
Il 03/11/2016 01:20, infirit ha scritto: Op 11/03/2016 om 12:19 AM schreef pozzugno: Il 02/11/2016 18:55, Nicola Fontana ha scritto: Il Wed, 2 Nov 2016 14:40:58 +0100 Pozz Pozz scrisse: 2016-11-02 11:24 GMT+01:00 Nicola Fontana : ... you don't necessarily need the handler id. In C (I don't use python) you could write the following: void my_set_value(GtkSpinButton *spin_button, gdouble value) { g_signal_handlers_block_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); /* This will not trigger callback_to_skip */ gtk_spin_button_set_value(spin_button, value) g_signal_handlers_unblock_matched(spin_button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, callback_to_skip, NULL); } I got the idea. I don't know if g_signal_handlers_block_matched() or similar functionality is available in Python. However, remaining in C, your code make the assumption there is a single callback function for all the spinbuttons. This is not true: I have a different handler for each spinbutton, because I have to make different things. Sorry but I am a developer, not a mind reader. Yes, of course :-) Thank you for spending some time for me. I thought using a different callback for each SpinButton was the more typical solution. You can match by data or try to lookup the callback by detail with g_signal_handler_find or refactor your code to use a single callback. It seems pyGObject implementation gives only two "handler block" functions: handler_block(), that needs the handler_id that I don't have; handler_block_by_func() that needs the callback to block (the same problem of your solution, because I have different callbacks). Is it possible to retrieve the list of connected callbacks of an object and a signal name ("value-changed")? The fact that you are using different callbacks has a foul smell indeed. Yes? I have to generate and send a different request to the device. Why do you think it's better to have a single callback? Of course, I could write one single callback as: def callback(self, spinbutton): if spinbutton is spinSetting1: self.callback_setting1(spinbutton) elif spinbutton is spinSetting2: self.callback_setting2(spinbutton) ... def callback_setting1(self,spinbutton): # This is the callback of the spinbutton associated to setting1 parameter set_setting1(spinbutton.get_value()) It seems to me a more complicated way to write different callbacks. Do you know you can subclass Gtk.SpinButton and override the virtual methods [1] and emit your own custom signal at the time you want it based of some attribute? There are some example on the internets but not much. Ironically the most complete imo is the old pygtk one [2] and gtk3 read the docs is not horrible [3]. Ok, thank you for your suggestion, I'll study this solution. At first, it seems too complicated for a very simple thing... at least, I thought it was a very simple thing. And I want to reiterate what Nicola said, create a small example with only 2 or 3 buttons that shows what you are truing to do. It works much easier that way and we do not have to read minds. Another situation, similar to mine. You have a dialog window with a SpinButton showing the volume speaker. When the dialog is shown, the SpinButton value should be the current volume level. The user could change the volume speaker by changing the value of the SpinButton, so a callback for the "value-changed" signal is connected. The callback calls the OS API to change the volume speaker. In this scenario (I think it's very common in GUI applications), the value of the SpinButton can be changed by code (when the dialog is shown) and by the user (when he wants to change the volume speaker). As you can understand, when the value is changed by code, the callback shouldn't be called. The solution is trivial for a single SpinButton. When you have much more SpinButtons, you need a more generic solution. I think the best approach is the one suggested by Nicola, creating a set_value_by_code() function that blocks the callback, call the original SpinButton.set_value() and unblock the callback again. The only problem is how to retrieve the reference for the callback to block. In Python I could add an attribute to SpinButton that is the associated callback. builder.connect_signals(self) self.spinButton1 = builder.get_object("spinButton1") self.spinButton1.callback = self.my_callback1 # so it could be retrieved in set_value_by_code() self.spinButton2 = builder.get_object("spinButton2") self.spinButton2.callback = self.my_callback2 def set_value_by_code(button, value): button.handler_
Re: SpinButton: how to avoid calling signal handler when set_value()
Op 11/03/2016 om 10:47 AM schreef pozzugno: > Another situation, similar to mine. You have a dialog window with a > SpinButton showing the volume speaker. When the dialog is shown, the > SpinButton value should be the current volume level. The user could > change the volume speaker by changing the value of the SpinButton, so > a callback for the "value-changed" signal is connected. The callback > calls the OS API to change the volume speaker. > In this scenario (I think it's very common in GUI applications), the > value of the SpinButton can be changed by code (when the dialog is > shown) and by the user (when he wants to change the volume speaker). So you need to keep properties in sync with each other, right? Binding widgets properties is possible even with some conversion, see [1]. As you refuse to give proper example code I'll leave it at this, good luck. ~infirit [1] https://lazka.github.io/pgi-docs/#GObject-2.0/classes/Object.html#GObject.Object.bind_property ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list