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
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