merrymonk has asked for the wisdom of the Perl Monks concerning the following question:

I want to add text to a canvas by:
1. opening a text widget;
2. type the text in the text widget;
3 having a button which automatically transfers the text to the cursor so that I can
place it where I want on the canvas.
Can someone explain how this can be done?
I appreciate that I could write the text at a certain point and then move it.
It would look so much better if the text ‘went’ straightaway to the cursor.

Replies are listed 'Best First'.
Re: Adding text to a Perl/Tk canvas
by zentara (Cardinal) on Jun 10, 2008 at 17:01 UTC
    I want ice cream with pistachios, chocolate crumbles, and cherries on top. :-)

    Seriously, what have you tried? It's not going to be easy to satisfy all those requirements, but it can be done with some work. Number 3 will be difficult, but not impossible. Here is a start for you, how to drag text to a position. All you need to do is open a Popup, with a text widget.... get your text, on pressing the Ok button, put it on the canvas, and drag it to where you want it.

    #!/usr/bin/perl use warnings; use strict; use Tk; # parts ripped from the testGraphics Zinc demo # and shown by themselves for clarity my $dx; my $dy; my $mw = MainWindow->new; $mw->geometry("700x600"); $mw->fontCreate('big', -family=>'courier', -weight=>'bold', -size=>int(-18*18/14)); my $canvas = $mw->Canvas(-width => 700, -height => 565, -bg => 'black', -borderwidth => 3, -relief => 'sunken', )->pack; my $closebutton = $mw->Button(-text => 'Exit', -command => sub{Tk::exi +t(0)}) ->pack; my $dragster = $canvas->createText( 50, 75, -fill => 'red', -tags => ['move'], -text => 'yahoo', -font => 'big', ); $canvas->bind('move', '<1>', sub {&mobileStart();}); $canvas->bind('move', '<B1-Motion>', sub {&mobileMove();}); $canvas->bind('move', '<ButtonRelease>', sub {&mobileStop();}); MainLoop; sub mobileStart { my $ev = $canvas->XEvent; ($dx, $dy) = (0 - $ev->x, 0 - $ev->y); $canvas->raise('current'); print "START MOVE-> $dx $dy\n"; } sub mobileMove { my $ev = $canvas->XEvent; $canvas->move('current', $ev->x + $dx, $ev->y +$dy); ($dx, $dy) = (0 - $ev->x, 0 - $ev->y); print "MOVING-> $dx $dy\n"; } sub mobileStop{&mobileMove;}

    I'm not really a human, but I play one on earth CandyGram for Mongo
      Many thanks for that.
      I do not want to sound ungrateful, however, with the previous good answers you have given I think I may have been able to do what you sent.
      It was Number 3 that I really wanted help with since I really
      do not know where to start.
      I suppose part of the problem is that I do not understand how
      your Perl actually get the selected text (and any other canvas items) from the canvas on to the cursor.
      It may be that $canvas->raise('current'); does this but I do not see how. :-(
      Any more clues or references will be more than welcome!
        Start by abandoning your problem for a few hours and reading an introductory Tk tutorial, like this one
      wow this is a really good code! nice piece! i tried changing the 'move' in this code $canvas->bind('move', '<1>', sub {&mobileStart();}); $canvas->bind('move', '<B1-Motion>', sub {&mobileMove();}); $canvas->bind('move', '<ButtonRelease>', sub {&mobileStop();}); into 'current' so that i can move different layers of objects inside the canvas. WOW thanks man! you guys are great! man im starting to love perl right now hehehe.
Re: Adding text to a Perl/Tk canvas
by zentara (Cardinal) on Jun 11, 2008 at 12:40 UTC
    Ok, here's a fish. This dosn't do it all, but it should show you everything you need to get started. After you move the text once, it is not movable again, so it won't move with the next text addition. The text will be placed at the position of the right mouse click. Since you need to press the Ok button in the dialogbox, the mouse can't have the text automatically placed on it. You can try if you want, but a right click is better. If you want something fancier, like being able to move a text a second time, figure out how to use bind and addtags. Like maybe a bind to 'Shift-ButtonPress-3' will add the 'mover' tag back onto some text.
    #!/usr/bin/perl use warnings; use strict; use Tk; require Tk::DialogBox; my $dx; my $dy; my $current; my $mw = MainWindow->new; $mw->geometry("700x600"); $mw->fontCreate('big', -family=>'arial', -weight=>'bold', -size=>int(-18*18/14)); my $canvas = $mw->Canvas(-width => 700, -height => 565, -bg => 'black', -borderwidth => 3, -relief => 'sunken', )->pack; my $closebutton = $mw->Button(-text => 'Exit', -command => sub{Tk::exi +t(0)}) ->pack; my $dialog = $mw->DialogBox( -buttons => [qw/Ok Cancel/], -title => "Enter Text" ); my $dialogT = $dialog->add("Text"); $dialogT->pack(qw/-padx 10 -pady 10/); $canvas->bind('move', '<1>', sub {&mobileStart();}); $canvas->bind('move', '<B1-Motion>', sub {&mobileMove();}); $canvas->bind('move', '<ButtonRelease>', sub {&mobileStop();}); #right click to post text $canvas->Tk::bind("<ButtonPress-3>", [\&getText, Ev('x'), Ev('y') ]); MainLoop; sub getText { # print "@_\n"; my ($canv, $x, $y) = @_; my $x1 = $canv->canvasx($x); my $y1 = $canv->canvasx($y); print "$x1 $y1\n"; $dialog->configure(-focus => $dialogT); $dialog->bind('<Return>' => undef); ## Determine whether or not the user hit "Ok" my $button = $dialog->Show(); if ( $button eq "Ok" ) { my $letters = $dialogT->get( '1.0', 'end' ); #print "$letters was submitted\n"; $dialogT->delete( '1.0', 'end' ); my $dragster = $canvas->createText( $x1, $y1, -fill => 'red', -tags => ['move'], -text => $letters, -font => 'big', -anchor => 'nw', ); $current = $dragster; } } sub mobileStart { my $ev = $canvas->XEvent; ($dx, $dy) = (0 - $ev->x, 0 - $ev->y); $canvas->raise('current'); print "START MOVE-> $dx $dy\n"; } sub mobileMove { my $ev = $canvas->XEvent; $canvas->move('current', $ev->x + $dx, $ev->y +$dy); ($dx, $dy) = (0 - $ev->x, 0 - $ev->y); print "MOVING-> $dx $dy\n"; } sub mobileStop{ $canvas->dtag($current,'move'); } __END__

    I'm not really a human, but I play one on earth CandyGram for Mongo
      Thanks for that. I will see if I can modify it to get the behaviour I want.

      PS - I have found your suggestions about using tags flexibly very effective.:-)