in reply to Detect perl/Tk Button double-clicks vs. single-clicks

++ Works great, I could have used this on some past projects. It's surprising the doubleclick bug has never been fixed. Here's my rough cut at a module version of your code, called in more of a Perl Tk style.

package Tk::Doubleclick; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(bindClicks); sub bindClicks { my %arg = @_; my $btn = delete $arg{-widget}; my $delay = delete $arg{-delay} || 300; my $args1 = delete $arg{-single}; my $args2 = delete $arg{-double}; my $clicked = delete $arg{-button} || 'left'; my %btnTable = ( left => 1, center => 2, right => 3 ); my $mousenum = $btnTable{$clicked} || $clicked; $mousenum = 1 unless ($mousenum =~ /^[123]$/); my $single = $args1; if (ref $args1 eq 'ARRAY'){ $single = shift @$args1; }else{ $args1 = []; } my $double = $args2; if (ref $args2 eq 'ARRAY'){ $double = shift @$args2; }else{ $args2 = []; } my $nclicks = 0; my $c_cmd = sub { ++$nclicks; $btn->after($delay => sub { my $count = $nclicks; $nclicks = 0; if ($count > 1) { $double->(@$args2); } elsif ($count == 1) { $single->(@$args1); } }); }; my $button_name = "<Button-$mousenum>"; $btn->bind($button_name => $c_cmd); } 1; =head1 NAME Tk::Doubleclick - Correct handling of single vs double click callback +bindings =head1 SYNOPSIS use Tk::Doubleclick; bindClicks( -delay => 500, -widget => $button_widget, -button => 'left', -single => [ \&callback, @args ], # with arguments -double => \&callback, # without arguments ); =head1 OPTIONS =over 5 =item -delay Maximum delay time detween clicks in milliseconds. Default = 300. =item -widget Widget to bind to mousebuttons. =item -button Mouse button to bind. Options are left, center, right, 1, 2, 3. Defaul +t = left. =item -single Single click callback. To include arguments, use array reference. =item -double Double click callback. To include arguments, use array reference. =back =cut

Update: fixed typo

Replies are listed 'Best First'.
Re^2: Detect perl/Tk Button double-clicks vs. single-clicks
by wol (Hermit) on Jul 28, 2009 at 11:52 UTC
    This problem is a difficult one to address generally, independent of the language.
    • Should the user have to wait half a second before their single click is processed?
    • Ditto for double clicks.
    • Shouldn't there be some kind of immediate feedback when the user click the first time? Can the kind of feedback it gives be common?
    • Is there any way that treble clicks can be detected?
    Even working on an obsolete platform many years ago, they took the same basic approach as Tk:
    • Every time a double click event comes through, you can assume that there was a single click event that came through a moment ago.
    • Don't define single and double click events for a widget so that the handlers are "not compatible"
    This does mean that if you want to handle a double click on a particular item, then there are some limitations on what you can do in the single click handler (don't open a dialog for eg, especially a modal one!).

    That said, I can imagine that the solution here may be quite apropriate in some cases, so it's great that it can be handled on a widget by widget basis. ++ from me.

    --
    use JAPH;
    print JAPH::asString();

Re^2: Detect perl/Tk Button double-clicks vs. single-clicks
by Anonymous Monk on Jul 26, 2009 at 01:41 UTC
    It's surprising the doubleclick bug has never been fixed.

    It isn't considered a bug.

      It isn't considered a bug.

      A double click is a single distinct user action, and the expected behavior would be for it to trigger a single distinct event. The fact that it triggers a series of two events, one of them also associated with a different action, is not logical, useful or documented. Whether or not you think it's a bug, it most certainly is a problem. Again, ++ to liverpole for coming up with a solution.

        A double click is a single distinct user action

        That is debatable.

        and the expected behavior would be for it to trigger a single distinct event.

        You may expect that, but Tk developers didn't. Many other GUI toolkits (Microsoft MFC, Java AWT, wxWidgets) propagate events the same way.

        The fact that it triggers a series of two events, one of them also associated with a different action, is not logical, useful or documented.

        Its documented in Tk::bind, bind: Binding to a single mouse click. The docs also say that Tk doesn't build that functionality in, partly because it's not what people actually want in most cases. So if Tk developers don't consider it a bug, well, there you go :)