ruby/tk - getting started

M

Martin DeMello

I wrote my first small tk app (mostly by pasting in code from various
examples and reading through the tcl/tk docs), but now I've run into a
wall. The following code displays a canvas and lets the user draw lines
on it; the bit I'm stuck at is getting the x,y coordinates of the
mouseclick to be the coordinates on the canvas, rather than on the
canvas display viewport. (i.e., right now when I scroll, the (x,y) I get
from @canvas.bind("1",...) is not the same (x,y) that line.coords needs,
since they're using two different coordinate systems)

martin

require 'tk'

class PatternDraw
def initialize(parent)

TkLabel.new(parent, 'wraplength'=>'4i', 'justify'=>'left',
'text'=>"Cadlab Pattern Generator."){
pack('side'=>'top')
}

@grid = TkFrame.new(parent) {
pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
}
TkGrid.rowconfigure(@grid, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(@grid, 0, 'weight'=>1, 'minsize'=>0)

_grid = @grid

# canvas
@canvas = TkCanvas.new(parent, {
'background' => 'white',
'borderwidth' => 2,
'relief' => 'ridge',
'scrollregion'=> ['-10c', '-10c', '10c', '10c']
}) {|c|
grid('in'=>_grid, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')

TkScrollbar.new(parent, 'command'=>proc{|*args| c.yview(*args) }) {|vs|
c.yscrollcommand(proc{|first,last| vs.set first,last})
grid('in'=>_grid, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
}

TkScrollbar.new(parent, 'orient'=>'horiz',
'command'=>proc{|*args| c.xview(*args)}) {|hs|
c.xscrollcommand(proc{|first,last| hs.set first,last})
grid('in'=>_grid, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
}
}

@start_x = @start_y = 0
@canvas.bind("Motion", proc {|x, y| do_motion(x, y)}, "%x %y")
@canvas.itembind('all', 'Any-Enter', proc{objEnter @canvas})
@canvas.itembind('all', 'Any-Leave', proc{objLeave @canvas})
@canvas.bind("1", proc {|e| do_press(e.x, e.y)})
@canvas.bind("2", proc{|x,y| @canvas.scan_mark(x,y)}, '%x %y')
@canvas.bind("3", proc {|e| release_line})
@canvas.bind('B2-Motion', proc{|x,y| @canvas.scan_dragto(x,y)}, '%x %y')
end

def objEnter(c)
id = c.find_withtag('current')[0].id
$oldFill = c.itemconfiginfo(id, 'fill')[4]
c.itemconfigure(id, 'fill'=>'SeaGreen1')
end

def objLeave(c)
id = c.find_withtag('current')[0].id
c.itemconfigure(id, 'fill'=>$oldFill)
end

def do_press(x, y)
if @current_line
@current_line.coords @start_x, @start_y, x, y
@current_line.fill 'black'
@current_line = nil
do_press(x,y)
else
@start_x = x
@start_y = y
@current_line = TkcLine.new(@canvas, x, y, x, y)
end
end

def do_motion(x, y)
if @current_line
@current_line.coords @start_x, @start_y, x, y
end
end

def release_line
@canvas.delete(@current_line)
@current_line = nil
end
end

root = TkRoot.new{ title 'Canvas' }
PatternDraw.new(root)
Tk.mainloop
 
H

Hidetoshi NAGAI

Hi,

From: Martin DeMello <[email protected]>
Subject: ruby/tk - getting started
Date: Wed, 15 Sep 2004 21:19:56 +0900
Message-ID: said:
on it; the bit I'm stuck at is getting the x,y coordinates of the
mouseclick to be the coordinates on the canvas, rather than on the
canvas display viewport.

Probably, TkCanvas#canvasx (or canvasy) method satisfies you.

From Tcl/Tk's 'canvas' manual,
-----------------------------------------------------------
pathName canvasx screenx ?gridspacing?
Given a window x-coordinate in the canvas screenx,
this command returns the canvas x-coordinate that
is displayed at that location. If gridspacing is
specified, then the canvas coordinate is rounded to
the nearest multiple of gridspacing units.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top