http://www.perlmonks.org?node_id=951270


in reply to How to move up/down the row element in a ListBox/Mlistbox

If you are doing it in a GUI, why not do it with the GUI? Drag and drop, baby!

#!/usr/bin/perl use warnings; use strict; use Tk; use Tk::DragDrop; use Tk::DropSite; my %tk; my $font = '{Helvetica} 14'; $tk{mw} = MainWindow->new; $tk{lbframe} = $tk{mw}->Frame->pack( -expand => 1, -fill => 'both', -anchor => 'nw' ); $tk{listbox} = $tk{lbframe}->Scrolled( 'Listbox', -selectmode => 'single', -scrollbars => 'ose', -font => $font, )->pack( -expand => 1, -fill => 'both', -padx => 5, -pady => 5, ); $tk{listbox}->insert( 'end', $_) for qw/first second third fourth fift +h etc./; my $dnd_token = $tk{listbox}->DragDrop( -event => '<B1-Motion>', -sitetypes => [qw/Local/], -startcommand => \&DragStart, ); $tk{listbox}->DropSite( -droptypes => [qw/Local/], -dropcommand => [ \&Drop, $tk{listbox}, $dnd_token ], ); MainLoop; sub DragStart { my ($token) = @_; my $site = $token->parent; my $e = $site->XEvent; my $idx = $site->index( '@' . $e->x . ',' . $e->y ); if ( defined $idx ) { $token->configure( -text => $site->get($idx), -font => $font ) +; $site->delete($idx); my ( $X, $Y ) = ( $e->X, $e->Y ); $token->MoveToplevelWindow( $X, $Y ); $token->raise; $token->deiconify; $token->FindSite( $X, $Y, $e ); } } sub Drop { my ( $site, $token ) = @_; my $text = $token->cget('-text'); my $y = $site->pointery - $site->rooty; my $nearest = $site->nearest($y); if ( defined $nearest ) { my @xy = $site->bbox($nearest); if ( $xy[1] + $xy[3] > $y ) { $site->insert( $nearest, $text ); } else { $site->insert( 'end', $text ); } } }

Replies are listed 'Best First'.
Re^2: How to move up/down the row element in a ListBox/Mlistbox
by gllore (Acolyte) on Oct 13, 2017 at 18:46 UTC
    Dear Perl gurus, This is my first time asking a question with regard to the use of Drag and Drop in the previous example. (( #3333=superdoc: print w/replies, xml )) When I implement the above code for a ListBox and I drag the name of the item outside the Listbox and I accidently let go of the mouse, the following happens: (1) the text that I am dragging disappears and (2) the text corresponding to the dragged item does not return to the Listbox. Is there a way you could recommend to force the item to return in the listbox when this happens? REGARDS gllore
      Since my last question, I have actually taken advantage of the accidental disappearance of the dragged item. I use the disappearance to represent a deletion of the item --- a "swoosh" and delete of the pointer. I now keep track of whether the user has exited the ListBox and deleted the item (accidentally or by mistake) by keeping count of how many times the user enters and leaves the Listbox --- not too elegant but it works. Is there a simpler alternative? I already have an explicit "Delete" button for the first-time user who is yet unfamiliar with the behavior of the GUI. Best, Juan