Ruby/Tk (X,Y) Coordinate Question

ruby

Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Sun, 02 Apr 2006 01:21:27 GMT


How do I get the same (x,y) coordinate for a given relative location in
the Ruby/tk application regardless of which widget I'm clicking on?

Background:

This has to do with a sudoku program I'm writing wherein I use the (x,y) 
coordinates from mouse clicks to determine which sudoku cell I am in. 
The cells are TkcRectangles and the numbers in (actually 'on') them are 
TkLabels.  Note that both the TkcRectangles and the TkLabels have the 
same TkCanvas as  their parent widget.

When I click in a cell (TkcRectangle) with no number (TkLabel) displayed
within it, I get an (x,y) coordinate relative to the canvas (TkCanvas), 
but
when I click in the same rectangle after I display a number within it 
(placed
over the TkcRectangle as a TkLabel) - and I click on that number, then 
the (x,y) coordinate reported back to me is relative to the TkLabel's 
origin, not the TkCanvas'.

This breaks my cell lookup scheme!

Again, since both the rectangles and labels have the canvas a parent, I 
don't
see why the (x,y) coordinates shouldn't be relative to the canvas in 
both
cases.  That is what I want anyway.  Is there a way to make this this 
happen?

Does Ruby/Tk implement Tk's Virtual Desktop Coordinates (vrootx and
vrooty) that give coordinates relative to the virtual desktop?

Or does Ruby/Tk implement accessing the rootx and rooty coordinates
which would be the same regardless of which widget is under the mouse
click?

Or can I use a 'lower' method on the the TkLabel widget to put it below 
the
TkcRectangles (without, of course, covering it up)?

Alas, and alack, I've browsed around the docs quite a bit.  I also tried 
a bunch
of stuff, but I just keep breaking the code that I had running fine!

I'm stuck!!!




The relevant code is straightforward.

Ie got a root and a canvas:
  @root = TkRoot.new(:title=>"David's Sudoku Treasury", 
:geometry=>"650x650")
  @canvas = TkCanvas.new(@root, :width=> @canvasWidth, :height=> 
@canvasHeight)

A callback proc bind'ed to the mouse button:
  @root.bind('Button', proc{|b,x,y| mainCellClickedProc(b, x, y)}, \
    "%b %x %y")

A method that is called inside of the bind callback proc to report the
button clicked and the (x,y) coordinate of the clicked location:
  def tell_it(btn, x, y)
    puts "tell_it: Mouse button #{btn} clicked at coordinates 
(#{x},#{y})"
  end

A set of 81 rectangles:
  def createAndDrawCells()
    #  Sizing and Location Variables
    @cellSize = 40 if @cellSize == 0	#  Cell size
    @xr1c1 = 10 if @xr1c1 == 0		#  Cell R1C1 X Upper Left Position
    @yr1c1 = 10 if @yr1c1 == 0		#  Cell R1C1 Y Upper Left Position
    @color = @bgColor
    #  Cell Rows
    9.times do |i|
      xul = @xr1c1
      yul = @yr1c1 + (i * @cellSize)
      xlr =  xul + @cellSize
      ylr = yul + @cellSize
      #  Cell Columns
      9.times do |j|
        @boardRects [ (i * 9) + j ] = TkcRectangle.new(@canvas, xul, 
yul, xlr, ylr, \
	  :fill=>@color)
        xul = xul + @cellSize
        xlr = xlr + @cellSize
      end
    end
  end


A set of 81 labels:
  def crea{*filter*}tryNumberLabels()
    81.times do |i|
      @entryNumberLabels[i] = TkLabel.new(@canvas)
    end
  end



-- 
Posted via  http://www.**--****.com/ 



Re: Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Sun, 02 Apr 2006 22:41:56 GMT



Um, just to try out these %X and %Y objects real quick, I added X, Y, %X 
and %Y to my argument list in the callback proc in the same form as the 
x, y, %x and %y objects to see what would happen, but got the following 
"dynamic constant assignment" and "formal argument" errors:

C:\Documents and Settings\dbailey1\Desktop\Ruby My Dear>ruby 
sudoku_treasury.rb
sudoku_treasury.rb:15: dynamic constant assignment
    @root.bind('Button', proc{|b,x,y,X,Y| mainCellClickedProc(b, x, y, 
X, Y)}, "%b %x %y %X %Y")
                                       ^
sudoku_treasury.rb:15: dynamic constant assignment
    @root.bind('Button', proc{|b,x,y,X,Y| mainCellClickedProc(b, x, y, 
X, Y)}, "%b %x %y %X %Y")
                                         ^
sudoku_treasury.rb:68: formal argument cannot be a constant
  def mainCellClickedProc(btn,x,y,X,Y)
                                   ^
sudoku_treasury.rb:68: formal argument cannot be a constant
  def mainCellClickedProc(btn,x,y,X,Y)
                                     ^
sudoku_treasury.rb:116: formal argument cannot be a constant
  def tell_it(btn, x, y, X, Y)
                          ^
sudoku_treasury.rb:116: formal argument cannot be a constant
  def tell_it(btn, x, y, X, Y)
                             ^
C:\Documents and Settings\dbailey1\Desktop\Ruby My Dear>

What are these %X and %Y objects, and where can I find some 
documentation on them?  But, more to the point, what does the "%" 
leading character on these object names mean?  I am looking through the 
pickaxe book, but I'm not finding any reference to "%" outside of the 
modulo operator.  Please excuse my ignorance of Ruby syntax and 
semantics!

-- 
Posted via  http://www.**--****.com/ 



Re: Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Sun, 02 Apr 2006 23:12:00 GMT



Um, just to try out these %X and %Y objects real quick, I added X, Y, %X 
and %Y to my argument list in the callback proc in the same form as the 
x, y, %x and %y objects to see what would happen, but got the following 
"dynamic constant assignment" and "formal argument" errors:

C:\Documents and Settings\dbailey1\Desktop\Ruby My Dear>ruby 
sudoku_treasury.rb
sudoku_treasury.rb:15: dynamic constant assignment
    @root.bind('Button', proc{|b,x,y,X,Y| mainCellClickedProc(b, x, y, 
X, Y)}, "%b %x %y %X %Y")
                                       ^
sudoku_treasury.rb:15: dynamic constant assignment
    @root.bind('Button', proc{|b,x,y,X,Y| mainCellClickedProc(b, x, y, 
X, Y)}, "%b %x %y %X %Y")
                                         ^
sudoku_treasury.rb:68: formal argument cannot be a constant
  def mainCellClickedProc(btn,x,y,X,Y)
                                   ^
sudoku_treasury.rb:68: formal argument cannot be a constant
  def mainCellClickedProc(btn,x,y,X,Y)
                                     ^
sudoku_treasury.rb:116: formal argument cannot be a constant
  def tell_it(btn, x, y, X, Y)
                          ^
sudoku_treasury.rb:116: formal argument cannot be a constant
  def tell_it(btn, x, y, X, Y)
                             ^
C:\Documents and Settings\dbailey1\Desktop\Ruby My Dear>

What are these %X and %Y objects, and where can I find some 
documentation on them?  But, more to the point, what does the "%" 
leading character on these object names mean?  I am looking through the 
pickaxe book, but I'm not finding any reference to "%" outside of the 
modulo operator.  Please excuse my "less than ideal" knowledge of Ruby 
syntax and semantics!

-- 
Posted via  http://www.**--****.com/ 



Re: Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Sun, 02 Apr 2006 23:14:59 GMT




Chris,

I'm researching these canvasx and canvasy methods now.  I'll let you 
know how I make out.  Thank you for your help.

David

-- 
Posted via  http://www.**--****.com/ 



Re: Ruby/Tk (X,Y) Coordinate Question

Postby Hidetoshi NAGAI » Mon, 03 Apr 2006 00:05:54 GMT

From: David Bailey < XXXX@XXXXX.COM >
Subject: Re: Ruby/Tk (X,Y) Coordinate Question
Date: Sat, 1 Apr 2006 23:12:00 +0900
Message-ID: < XXXX@XXXXX.COM >

X and Y are constans. You must use local variables.
e.g.
  @root.bind('Button', 
             proc{|b,x,y,root_x,root_y| 
               mainCellClickedProc(b, x, y, root_x, root_y)
             }, "%b %x %y %X %Y")

-- 
Hidetoshi NAGAI ( XXXX@XXXXX.COM )



Re: Ruby/Tk (X,Y) Coordinate Question

Postby dperkins » Mon, 03 Apr 2006 00:10:10 GMT

> Um, just to try out these %X and %Y objects real quick, I added X, Y, %X

Anything that begins with a capital letter is a constant, e.g., |b, x, y,
X, Y|.  You could replaces X and Y with xx and yy.





An event can pass parameters to a callback.  The % tells Ruby/Tk which
event data you want passed to the callback.

%x %y    mouse's x and y coordinates in widget.
%X %Y    mouse's x and y coordinates in program window.
%W       widget mouse is in

There are more variables, but I don't have my notes with me.

A book on Tk or Perl/Tk should have the complete list.




Re: Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Tue, 04 Apr 2006 02:44:50 GMT




Hidetoshi,

At first I jumped with joy thinking that root_x and root_y would solve 
my problem.  Uh, it still may, but ...

When I bind via this:

@root.bind('Button', proc{|b,x,y,root_x,root_y| \
  mainCellClickedProc(b, x, y,root_x,root_y)}, "%b %x %y %X %Y")

And report the mouse-click coordinates with this method:

  def tell_it(btn, x, y,root_x, root_y)
    puts "tell_it: Mouse button #{btn} clicked at coordinates 
(#{x},#{y})" +\
      " and (#{root_x},#{root_y}))"
  end

The root_x and root_y coordinates are relative to the top left corner of 
the "screen".

For example, here is the output of a mouse-click on the top left corner 
of my application:

tell_it: Mouse button 1 clicked at coordinates (2,1) and (278,32))

Now, if I move the application window on the Windows XP screen and click 
in the same relative position of the application's window, here is the 
output of that mouse-click:

tell_it: Mouse button 1 clicked at coordinates (2,1) and (153,80))

See?  The (x,y) coordinates are the same, but the (root_x,root_y) 
coordinates have changed to reflect that the application's window has 
moved on the Windows XP Desktop.  I was hoping that "both" (x,y) and 
(root_x,root_y) would be the same, but they are not.

You know, when I use the "place" geometry manager, the :x and :y objects 
are relative to the "parent" widget's origin, but the "event" :x and :y 
objects seem to be relative to the "self" widget's origin.  Do you 
agree?

In any case, it appears that I'm back to "square one", so to speak.


-- 
Posted via  http://www.**--****.com/ 



Re: Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Tue, 04 Apr 2006 03:12:18 GMT





Hey Chris and/or Fellow Rubyists,

I bought and flipped through "Mastering Perl/Tk" by Nancy Walsh and 
Steve Lidie, which was purported to be "the" book on Perk/Tk.  There was 
scant info on canvasx, canvasy and find_overlapping.  I read through 
what was there, though.

Both canvasx and canvasy take a single argument, but when I supplied 
various x and y arguments, the methods just returned the same argument 
as a result!  So, I guess I just don't get it.  Do you have a sense of 
what the argument is supposed to be and what is supposed to happen to 
it?

Also, where can I get some inormation about find_overlapping, real 
quick.

I spent all day yesterday fighting with widget placement (see my earlier 
post "Placing Sets of Ruby/Tk Widgets"), and that pooped me out.  What 
week-end brain power I have left, I will apply toward continuing to 
explore this problem.

Thanks,

David


P.S. BTW, my use of root_x and root_y coordinates did not work because 
they appear to be relative to the desktop and not the application 
window.  (Unless I did something drastically wrong!)  So, if I calculate 
an offset but the user then moves the application window, the offset 
becomes no longer valid.  Rats!

-- 
Posted via  http://www.**--****.com/ 



Re: Ruby/Tk (X,Y) Coordinate Question

Postby Chris Alfeld » Tue, 04 Apr 2006 09:34:07 GMT

anvasx and canvasy translate from coordinates relative to the canvas
widget to the canvas's coordinate system. By default this will be the
same but if you have scrollbars or other transformations it can
differ.

I have never found a good use for root_x and root_y coordinates. Try
to avoid using coordinates at all when possible. Tk has a very rich
binding ability which means you can often do everything you want
without every worrying about actual coordinates of mouse clicks. The
exception is canvas work where you use %x %y fed through canvasx and
canvasy to get canvas coordinates.

Writing fully portable Tk code is difficult (though possibly easier
than with certain other GUI toolkits).

I use the packer (.pack) almost exclusively. Only when I'm trying to
do something really unusual do I use the placer (.place). The packer
does have a bit of a learning curve but is very powerful and easy once
learned properly. Don't try to pack too many widgets into the same
parent. Subdivide into frame's as needed.

While the perl/tk interface is closer to ruby/tk's than Tcl/Tk's the
Tcl/Tk documentation is the ultimate source for how the widgets
actually behave. This is especially true for an implementation like
Ruby/Tk which not only wraps compiled code but also wraps Tcl code.
You should find a copy either only or download (activestate.com has a
nice online copy). Use this documentation is "what does this do?" and
use the Perl/Tk documentation for "how do I use it?".

On 4/2/06, David Bailey < XXXX@XXXXX.COM > wrote:



Re: Ruby/Tk (X,Y) Coordinate Question

Postby Hidetoshi NAGAI » Tue, 04 Apr 2006 14:09:24 GMT

From: David Bailey < XXXX@XXXXX.COM >
Subject: Re: Ruby/Tk (X,Y) Coordinate Question
Date: Mon, 3 Apr 2006 02:44:50 +0900
Message-ID: < XXXX@XXXXX.COM >

Yes. You are right. 
I talked about error messages which you got.


Try this.
----------------------------------------------------------------------------
require 'tk'

TkLabel.new(:text=>'click me!', :padx=>10, :pady=>5, :relief=>:raised){
  place(:x=>30, :y=>50)

  bind('1', proc{|x, y|
         p info = self.place_info
         p [[x, y], [info['x'], info['y']], [info['x'] + x, info['y'] + y]]
       }, '%x %y')
}

Tk.mainloop
----------------------------------------------------------------------------
-- 
Hidetoshi NAGAI ( XXXX@XXXXX.COM )



Re: Ruby/Tk (X,Y) Coordinate Question

Postby David Bailey » Wed, 05 Apr 2006 00:58:26 GMT




 YES!!!   YES!!!   YES!!!   That worked!

When I click in the sudoku cell (TkcRectangle) just above the number 
(TkLabel), I get:

tell_it: Mouse button 1 clicked at coordinates (124,71)

When I click the number (TkLabel), I get:

{"relwidth"=>"", "relx"=>0, "x"=>115, "anchor"=>"nw", "y"=>75, 
"relheight"=>"", "rely"=>0, "height"=>20
, "width"=>20}
[[7, 4], [115, 75], [122, 79]]

So, the "[info['x'] + x, info['y'] + y]" is just what I needed.  The 
coordinates [122, 79] map to the proper cell!  Thank you, Hidetoshi. 
Thank you very much!

I now (or will soon, after I integrate this technique) have a playable 
sudoku game!  (:>)

My development plan was to proceed in three steps.  Step 1 was to draw 
the board, outline any clicked cell with the left-click, and highlight 
the cell's constraining row, columnn and sub-grid with the the 
right-click.  Step 2 was to enter numbers constrained by the rules of 
sudoku, generate a history of the moves, and to implement backing up 
through the history of the moves.

Completion of steps 1 and 2 would give me a "playable" sudoku game.  I 
am now at this point, thanks to you, my friend!

Step 3 will be to implement inputting a game's initial configuration 
from a file, generating games of varying difficulty, and solving the 
game via a set of hints that allow progressively advanced solution 
strategies, starting with basic ones such as 'intersections' and 'forced 
moves', and up through the use of advanced techniques such as 'x-wing' 
and 'unique rectangles'.

I realize that an argument can be made for completing the logic first 
and doing the GUI last, but I figured that this way I could acquire more 
Ruby syntax and semantics up front.  Learning Ruby, after all, was the 
reason why I started this this project to begin with.

So, I thank you again.  When the code is a bit more robust, I'll send 
you a copy.



-- 
Posted via  http://www.**--****.com/ 



Similar Threads:

1.Ruby Tk and X/Y coordinates

2.Tk - Ruby/Tk core library design questions

I forgot which old version is, on that old version, the widget.pack
method always returns nil.
So people have to write something like:

b = TkButton.new {
  pack
}

Now the pack returns self, what's great improvement, so we can write
something like:
b = TkButton.new.pack.command { puts "Hello" }

Now, my ruby version is : ruby 1.8.2 (2004-12-25) [i386-mswin32]
and my Tcl/Tk version is : 8.4
I have some Ruby/Tk design questions :

(1) Layout Manager:
there are:
widget.pack ;  TkPack.pack ; Tk.pack
widget.grid ; TkGrid.grid ; Tk.grid
widget.place ; TkPlace.place
methods, why there is no Tk.place method ?
This seems inconsistent for me.

(2) Since we try to wrap Tcl/Tk on OO, why some Tcl commands are not
treat like options ?
Most options have getter and setter method, there are many way to do
it, for example:
# setter
button.bg = :red
button.bg(:red)
button.configure(:bg, :red)
# getter
puts button.bg
puts button.cget(:bg)

Now, for example, root.title and root.iconbitmap ... etc are command
but not options on Tcl/Tk language.
But, I feel this will be nice if we "wrap" them like options, so we
can write something like:
TkRoot.new(:title=>'Hello')  or
TkButton.new(:text=>'set title').command { Tk.root.title = "some title" }
For me, it seems title is just like an option for TkRoot.
(But in current version, it is not, so I cannot use :title=>... or
root.title = ... syntax )

(3)
require 'tk'
c = TkCanvas.new.pack
TkcRectangle.new(c, 10, 10, 50, 50)
Tk.mainloop

The above code works fine, but if I rewrite it to become

require 'tk'
TkcRectangle.new(TkCanvas.new.pack, 10, 10, 50, 50)
Tk.mainloop

I got this error: uninitialized constant TkcRectangle (NameError)

Rewrite it again like:

require 'tk'
TkCanvas
TkcRectangle.new(TkCanvas.new.pack, 10, 10, 50, 50)
Tk.mainloop

It works fine again.

So, what's going wrong with:
require 'tk' ; TkcRectangle.new(TkCanvas.new.pack, 10, 10, 50, 50) ; Tk.mainloop
Why should I reference TkCanvas ( at least class ) first ?

Thank you.


3.ruby graph: coordinate plane?

4.Noob Q: ruby block scoping question (ruby TK)

I've just recently been getting to know ruby and the ruby Tk library and
have run into a block scoping problem [apparently] that I don't really
understand (I'm a long-time C programmer, mostly at the systems and
library levels, and have little experience with VHLLs such as ruby).

I've included below a cobbled up example that demonstrates the problem
that has been driving me completely batty.

Basically, why is the "mybutton" method reference not contained within
the binding of the block passed to the TkButton.new method though it is
clearly within the scope of the initialize_n methods?

I guess my question boils down to is how much of the block's context is
actually contained within its binding, i.e., how far out does it extend?
Obviously, it extends at least to that of the method within which it
appears.  Why not to all symbols visible within the class definition
(as, apparently, it doesn't)?

I do realize that the actual block passed to the "command" method in the
outer block passed to the TkButton.new method is actually executed in
the context of the button code itself somewhere in the Tk library and,
therefore, executes in -that- context.  However, it's binding should
carry over some of the context in which it was created.  How much (i.e.,
to what extent)?

Any references to books, online docs, code examples, ruby interpreter
sources, etc., in this regard would also be much appreciated.
Additionally, any insights as to what goes on "behind the scenes" in
ruby would be very helpful.

Thanks!

Phil


----- Begin ruby code -----
#!/usr/bin/ruby -w

require 'tk'

class MyButton

  def myexit
    exit
  end

  # Doesn't work: "myexit" out of scope in block.  Why?
  def initialize_1
    mybutton = TkButton.new do
      text "EXIT"
      command { myexit }
      pack
    end
  end

  # Works: refs "myexit" outside of block.
  # Note that "myexit" -is- visible within the initialize_2 method!?!
  def initialize_2
    mybutton = TkButton.new do
      text "EXIT"
      pack
    end
    mybutton.command { myexit }
  end

  # Works: creates local proc object to pass to block.
  # Note that "myexit" -is- visible within the initialize_3 method!?!
  def initialize_3
    proc_myexit = lambda { myexit }
    mybutton = TkButton.new do
      text "EXIT"
      command proc_myexit
      pack
    end
  end

  # Pick one of "initialize_[123]" to perform the test cases.
  def initialize
    initialize_1
    #initialize_2
    #initialize_3
    Tk.mainloop
  end
end

MyButton.new
----- End Ruby Code -----

-- 
Philip Amadeo Saeli
SUSE Linux 10.1
 XXXX@XXXXX.COM 

5.2 questions about TkVariable and ruby/tk

Hi all!

I have the following code snippet:

-----------------------------------
...
h=Hash.new
(0..4).each {|c|
  (0..9).each {|r|
    h["#{r},#{c}"]="#{r} ; #{c}";
  }
}
v=TkVariable.new(h)
#~ puts "before: #{v.value}"
puts "ok."
t2=TkTable.new() {
  rows 10
  cols 5
  variable v
}
t2.pack()
Tk.mainloop()
-------------------------------------
(TkTable is a wrapper for a tktable tcl widget written by me. It uses
'variable' to store the data of the table cells.)

This works perfectly, just as I expect. BUT, if I comment out the
debugging puts(), then it prints v's content, then 'ok.' just as before,
but after that the program hangs, the X window do not appear, and I
cannot even stop the program with CTRL-C! If I simply just read the
v.value (do not print it), the result is similar. :-O With v.inspect the
problem do not occur. What difference makes reading a TkVariable's
value???

My second question is related to the previous: I have the feeling that
this 'hang' really means a runtime error in the ruby code which is
executed from tcl (which is executed from ruby :). So, my question is
how to receive these error messages, and why do the process hang if it
encounters with an error like this?

6. Ruby-tk question

7. ruby/tk question

8. Ruby TK window size question



Return to ruby

 

Who is online

Users browsing this forum: No registered users and 37 guest