Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Block double-click on buttons

56 views
Skip to first unread message

Alexandru

unread,
Jan 22, 2018, 10:34:23 PM1/22/18
to
Hi,

What would be the best, simplest, most general way to block double-clicks on buttons? Per default, a double-click triggers two times the widget command, which is actually not wanted.

Many thanks.
Alexandru

Rich

unread,
Jan 22, 2018, 11:04:15 PM1/22/18
to
Alexandru <alexandr...@meshparts.de> wrote:
> Hi,
>
> What would be the best, simplest, most general way to block
> double-clicks on buttons? Per default, a double-click triggers two
> times the widget command, which is actually not wanted.

The "best, simplest, most general" way would be:

Do, as the very first command in the proc called by the -command
argument to the button: ".b configure -state disabled"

Then, the very last command performed before finishing the work
performed in the -command proc, should be ".b configure -state normal".

The above assumes the button is named .b, adjust accordingly for your
scripts.

Alexandru

unread,
Jan 22, 2018, 11:13:32 PM1/22/18
to
Thanks. I was aware if this possiblity, which I avoided until now because of possible errors in the callback script that would block setting the button state back to normal. I regard this method as "unsafe". Using catch arround the whole callback procedure would work but I think this is "ugly" and not general.

Gerald Lester

unread,
Jan 23, 2018, 1:06:59 AM1/23/18
to
Put a try {script} finally {.b configure -state normal} instead of just
a catch.


--
+----------------------------------------------------------------------+
| Gerald W. Lester, President, KNG Consulting LLC |
| Email: Gerald...@kng-consulting.net |
+----------------------------------------------------------------------+

Alexandru

unread,
Jan 23, 2018, 1:34:28 AM1/23/18
to
Oh, that sounds good. But is there a way to automate this? Instead of putting the same text into the widgets -command property, make sure all buttons have this behavior?

Rich

unread,
Jan 23, 2018, 6:54:46 AM1/23/18
to
Alexandru <alexandr...@meshparts.de> wrote:
> Am Dienstag, 23. Januar 2018 05:04:15 UTC+1 schrieb Rich:
>> Alexandru <alexandr...@meshparts.de> wrote:
>> > Hi,
>> >
>> > What would be the best, simplest, most general way to block
>> > double-clicks on buttons? Per default, a double-click triggers
>> > two times the widget command, which is actually not wanted.
>>
>> The "best, simplest, most general" way would be:
>>
>> Do, as the very first command in the proc called by the -command
>> argument to the button: ".b configure -state disabled"
>>
>> Then, the very last command performed before finishing the work
>> performed in the -command proc, should be ".b configure -state
>> normal".
>>
>> The above assumes the button is named .b, adjust accordingly for
>> your scripts.
>
> Thanks. I was aware if this possiblity, which I avoided until now
> because of possible errors in the callback script that would block
> setting the button state back to normal. I regard this method as
> "unsafe".

Any other way you utilize to 'block' the double button call is also
going to require that an "off" have a corresponding "on" function at
the end. And if the script errors out before reaching the "on" at the
end then you will have the identical issue. So any method you pick to
use to block the second button push from being handled when the first
returns will be equally 'unsafe' by this definition of unsafe.

> Using catch arround the whole callback procedure would work but I
> think this is "ugly" and not general.

Actually, using 'catch' is the 'general' way to detect and handle
properly errors from the script. But if you don't like catch, then if
you have 8.6 you could use a try block and turn "on" the button within
the 'finally' clause.

But in any case, if you are not using catch (or try ...) to detect
errors where they might occur and handle them appropriately, you are
not creating a very robust script in a general sense anyway.

Rich

unread,
Jan 23, 2018, 6:55:58 AM1/23/18
to
Alexandru <alexandr...@meshparts.de> wrote:
> Am Dienstag, 23. Januar 2018 07:06:59 UTC+1 schrieb Gerald Lester:
>> On 01/22/2018 10:13 PM, Alexandru wrote:
>> > Am Dienstag, 23. Januar 2018 05:04:15 UTC+1 schrieb Rich:
>> >> Alexandru <alexandr...@meshparts.de> wrote:
>> >>> Hi,
>> >>>
>> >>> What would be the best, simplest, most general way to block
>> >>> double-clicks on buttons? Per default, a double-click triggers
>> >>> two times the widget command, which is actually not wanted.
>> >>
>> >> The "best, simplest, most general" way would be:
>> >>
>> >> Do, as the very first command in the proc called by the -command
>> >> argument to the button: ".b configure -state disabled"
>> >>
>> >> Then, the very last command performed before finishing the work
>> >> performed in the -command proc, should be ".b configure -state
>> >> normal".
>> >>
>> >> The above assumes the button is named .b, adjust accordingly for
>> >> your scripts.
>> >
>> > Thanks. I was aware if this possiblity, which I avoided until now
>> > because of possible errors in the callback script that would block
>> > setting the button state back to normal. I regard this method as
>> > "unsafe". Using catch arround the whole callback procedure would
>> > work but I think this is "ugly" and not general.
>>
>> Put a try {script} finally {.b configure -state normal} instead of
>> just a catch.
>
> Oh, that sounds good. But is there a way to automate this? Instead of
> putting the same text into the widgets -command property, make sure
> all buttons have this behavior?

Build a proc that builds procs. I.e., what the java camp might refer
to as a "Factory".

Alexandru

unread,
Jan 23, 2018, 9:28:36 AM1/23/18
to
Could you explain what exactly do you mean? I have no idea about Java and Google didn't help.

Should I create a general procedure that gets the name of the actual procedure as first argument? This procedure than adds the additional commands around the procedure call?

sled...@gmail.com

unread,
Jan 23, 2018, 9:43:46 AM1/23/18
to
Implement two bindings: single click and double click. The binding on the regular press will match on the first press of the 'double'. Then the command bound to the double will match on the second (accidental) press. This script associated with the second command could then be a "no op"

bind . <1> {desired script}
bind . <Double-1> {do nothing}

Alexandru

unread,
Jan 23, 2018, 9:50:57 AM1/23/18
to
Thaks, I will check this.

Andreas Leitgeb

unread,
Jan 23, 2018, 11:40:43 AM1/23/18
to
Alexandru <alexandr...@meshparts.de> wrote:
> Am Dienstag, 23. Januar 2018 15:43:46 UTC+1 schrieb sled...@gmail.com:
>> On Monday, January 22, 2018 at 10:34:23 PM UTC-5, Alexandru wrote:
>> > What would be the best, simplest, most general way to block double-clicks on buttons? Per default, a double-click triggers two times the widget command, which is actually not wanted.
>> Implement two bindings: single click and double click. The binding on the regular press will match on the first press of the 'double'. Then the command bound to the double will match on the second (accidental) press. This script associated with the second command could then be a "no op"
>> bind . <1> {desired script}
>> bind . <Double-1> {do nothing}
> Thaks, I will check this.

That doesn't seem to work. It will call the "do nothing" and
still call the -command a second time (assuming that "do nothing"
is changed to a real noop).

Another approach against too fast re-execution of the command
would be setting it to disabled, then set up an "after ..."
timer to re-enable the button.

If the visual flicker of disabling/enabling the button is not
acceptable for the user, just check some global/namespaced
variable...
if {$::running} { return }
set ::running 1; after 1000 { set ::running 0 }
...

Alexandru

unread,
Jan 23, 2018, 11:48:51 AM1/23/18
to
Am Dienstag, 23. Januar 2018 15:43:46 UTC+1 schrieb sled...@gmail.com:
Thanks again, your solution works perfectly. I created this simple test code and use the binding to the ttk button class instead to a specific widget:

pack [ttk::button .b -text test -command Test]
bind TButton <Double-1> {Foo}
proc Foo {args} {
puts Double
}
proc Test {args} {
puts Click
}
console show

Alexandru

unread,
Jan 23, 2018, 11:50:08 AM1/23/18
to
It does work. See previous post.

Cheers
Alexandru

Alexandru

unread,
Jan 23, 2018, 11:53:10 AM1/23/18
to
Am Dienstag, 23. Januar 2018 15:43:46 UTC+1 schrieb sled...@gmail.com:
I have simplified the implementation, so that the Foo procedure is not needed:

pack [ttk::button .b -text test -command Test]
bind TButton <Double-1> {return 1}
proc Test {args} {
puts Click
}
console show

Note, that bind TButton <Double-1> {} would not work.

Harald Oehlmann

unread,
Jan 23, 2018, 11:54:05 AM1/23/18
to
I would always end bindings with a "break" to avoid the other bindings
in the binding chain to run.

So:
bind $w <Double-1> break

Harald

Alexandru

unread,
Jan 23, 2018, 11:57:33 AM1/23/18
to
Hi Harald,

what is the explanation for bind $w <Double-1> {return 1} still working. What is the difference between return and break in this context of bindings?

Rich

unread,
Jan 23, 2018, 12:13:21 PM1/23/18
to
A "Factory" in Java is an object that creates other objects.

> Should I create a general procedure that gets the name of the actual
> procedure as first argument? This procedure than adds the additional
> commands around the procedure call?

That is one way to do it. Remember, Tcl lets you define proc's at run
time. So inside a proc, you can build up a string, and then define
another proc with its body as that string (you do have to be careful
about character quoting).

Another way would be to have a proc that extracts the body from another
proc, inserts the wrapper, and then redefines the proc with that new
body.

Rich

unread,
Jan 23, 2018, 12:15:09 PM1/23/18
to
man n bind:

The continue and break commands may be used inside a binding script to
control the processing of matching scripts. If continue is invoked,
then the current binding script is terminated but Tk will continue
processing binding scripts associated with other tag's. If the break
command is invoked within a binding script, then that script terminates
and no other scripts will be invoked for the event.

Alexandru

unread,
Jan 23, 2018, 12:18:37 PM1/23/18
to
I was actually aware about the meaning of break and continue. My quastion was about return. Observed behavior: Returning any value has the same effect as break. But why?

Harald Oehlmann

unread,
Jan 23, 2018, 12:21:04 PM1/23/18
to
>> So:
>> bind $w <Double-1> break
>>
>> Harald
>
> Hi Harald,
>
> what is the explanation for bind $w <Double-1> {return 1} still working. What is the difference between return and break in this context of bindings?
>

Hi Alexandru,

Rich has pasted the manpage...

I just took the habbit to end my basta-style binding scripts with
"break". Otherwise, all the following scripts for parent widgets and for
the class will also fire.

I suppose, "return 1" is the same as "return -code ok 1" and thus is the
same as continue and thus should not work. I don't know...

Sorry,
Harald

Alexandru

unread,
Jan 23, 2018, 12:23:19 PM1/23/18
to
That's the point: return 1 *blocks* the execution of other bindings... This is was not expected by me...

Rich

unread,
Jan 23, 2018, 12:42:10 PM1/23/18
to
The "return" command is not documented for use inside binding scripts.
It, however, appears to function in the same manner as "break" is
documented to function.

I never tried doing a 'return' within a binding script before to
recognize the 'sameness' to break.

Robert Heller

unread,
Jan 23, 2018, 1:06:14 PM1/23/18
to
At Tue, 23 Jan 2018 09:18:33 -0800 (PST) Alexandru <alexandr...@meshparts.de> wrote:

>
> Am Dienstag, 23. Januar 2018 18:15:09 UTC+1 schrieb Rich:
> > Alexandru <alexandr...@meshparts.de> wrote:
> > > Am Dienstag, 23. Januar 2018 17:54:05 UTC+1 schrieb Harald Oehlmann:
> > >> Am 23.01.2018 um 17:50 schrieb Alexandru:
> > >> > Am Dienstag, 23. Januar 2018 17:40:43 UTC+1 schrieb Andreas Leitgeb:
> > >> >> Alexandru <alexandr...@meshparts.de> wrote:
> > >> >>> Am Dienstag, 23. Januar 2018 15:43:46 UTC+1 schrieb sled...@gmail.=
> com:
> > >> >>>> On Monday, January 22, 2018 at 10:34:23 PM UTC-5, Alexandru wrote=
> :
> > >> >>>>> What would be the best, simplest, most general way to block doub=
> le-clicks on buttons? Per default, a double-click triggers two times the wi=
> dget command, which is actually not wanted.
> > >> >>>> Implement two bindings: single click and double click. The bindin=
> g on the regular press will match on the first press of the 'double'. Then =
> the command bound to the double will match on the second (accidental) press=
> . This script associated with the second command could then be a "no op"
> > >> >>>> bind . <1> {desired script}
> > >> >>>> bind . <Double-1> {do nothing}
> > >> >>> Thaks, I will check this.
> > >> >>
> > >> >> That doesn't seem to work. It will call the "do nothing" and
> > >> >> still call the -command a second time (assuming that "do nothing"
> > >> >> is changed to a real noop).
> > >> >>
> > >> >> Another approach against too fast re-execution of the command=20
> > >> >> would be setting it to disabled, then set up an "after ..."
> > >> >> timer to re-enable the button.
> > >> >>
> > >> >> If the visual flicker of disabling/enabling the button is not
> > >> >> acceptable for the user, just check some global/namespaced=20
> > >> >> variable...
> > >> >> if {$::running} { return }
> > >> >> set ::running 1; after 1000 { set ::running 0 }
> > >> >> ...
> > >> >=20
> > >> > It does work. See previous post.=20
> > >> >=20
> > >> > Cheers
> > >> > Alexandru
> > >> >=20
> > >>=20
> > >> I would always end bindings with a "break" to avoid the other bindings
> > >> in the binding chain to run.
> > >>=20
> > >> So:
> > >> bind $w <Double-1> break
> > >>=20
> > >> Harald
> > >=20
> > > Hi Harald,
> > >=20
> > > what is the explanation for bind $w <Double-1> {return 1} still working=
> . What is the difference between return and break in this context of bindin=
> gs?
> >=20
> > man n bind:
> >=20
> > The continue and break commands may be used inside a binding script to
> > control the processing of matching scripts. If continue is invoked,
> > then the current binding script is terminated but Tk will continue
> > processing binding scripts associated with other tag's. If the break
> > command is invoked within a binding script, then that script terminates
> > and no other scripts will be invoked for the event.
>
> I was actually aware about the meaning of break and continue. My quastion w=
> as about return. Observed behavior: Returning any value has the same effect=
> as break. But why?
>

In some contexts, return is a kind of "break". Like break, return interupts
the flow of control.

--
Robert Heller -- 978-544-6933
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services
hel...@deepsoft.com -- Webhosting Services

Robert Heller

unread,
Jan 23, 2018, 1:06:14 PM1/23/18
to
In some cases, it isn't just the one button being "double clicked" on but some
case where once *A* button is clicked once, no other button's should be
clicked, until the original button has completed its task (this could be an
I/O overlap contention issue). In this case, the use of a shared "lock"
variable works best. Or the use of a busy-wait hack -- eg doing a forced
grap/focus to a non-realized widget (and displaying some sort of busy-wait
cursor to let the user know that things are busy and to wait until things are
not busy.

Schelte Bron

unread,
Jan 24, 2018, 10:48:43 AM1/24/18
to
Alexandru wrote:
> Note, that bind TButton <Double-1> {} would not work.

But bind TButton <Double-1> { } would.


Schelte.

Alexandru

unread,
Jan 24, 2018, 11:08:34 AM1/24/18
to
Hm, you write the same command as I did and say that is works. Perhaps I did something wrong but in my case it didn't work. I have Windows 10.

Rolf Ade

unread,
Jan 24, 2018, 1:24:53 PM1/24/18
to

Alexandru <alexandr...@meshparts.de> writes:
> Am Mittwoch, 24. Januar 2018 16:48:43 UTC+1 schrieb Schelte Bron:
>> Alexandru wrote:
>> > Note, that bind TButton <Double-1> {} would not work.
>>
>> But bind TButton <Double-1> { } would.
>
> Hm, you write the same command as I did and say that is works. Perhaps
> I did something wrong but in my case it didn't work. I have Windows
> 10.

No, he hadn't the same command. While you where using the empty string
(expressed with {}), he is using a non-empty, white-space only script
({ }).

The bind man page say in the first paragraph of the introduction:

"If script is an empty string then the current binding for sequence is
destroyed, leaving sequence unbound."

The binding called with an empty string, as you did, just removed that
binding. Using an non-empty white-space only string is one way to write
a non-op. What Schelte proposed should work.

Alexandru

unread,
Jan 24, 2018, 8:05:20 PM1/24/18
to
Hi Rolf, thanks for the explanation. Now I get it.

Cheers
Alexandru
0 new messages