152 lines
5.1 KiB
R
152 lines
5.1 KiB
R
|
###
|
||
|
### This demonstration script creates a canvas widget showing a 2-D
|
||
|
### plot with data points that can be dragged with the mouse.
|
||
|
###
|
||
|
### It is a ripoff of the plot.tcl demo from the tk 8.0 distribution
|
||
|
### All I did was to add the code to plot the fitted regression line.
|
||
|
|
||
|
# Copyright (C) 2000-2008 The R Core Team
|
||
|
|
||
|
require(tcltk) || stop("tcl/tk library not available")
|
||
|
require(graphics); require(stats)
|
||
|
local({
|
||
|
have_ttk <- as.character(tcl("info", "tclversion")) >= "8.5"
|
||
|
if(have_ttk) {
|
||
|
tkbutton <- ttkbutton
|
||
|
tkframe <- ttkframe
|
||
|
tklabel <- ttklabel
|
||
|
}
|
||
|
tclServiceMode(FALSE) # don't display until complete
|
||
|
top <- tktoplevel()
|
||
|
tktitle(top) <- "Plot Demonstration"
|
||
|
|
||
|
msg <- tklabel(top,
|
||
|
font="helvetica",
|
||
|
wraplength="4i",
|
||
|
justify="left",
|
||
|
text="This window displays a canvas widget containing a simple 2-dimensional plot. You can doctor the data by dragging any of the points with mouse button 1.")
|
||
|
|
||
|
tkpack(msg, side="top")
|
||
|
|
||
|
buttons <- tkframe(top)
|
||
|
tkpack(buttons, side="bottom", fill="x", pady="2m")
|
||
|
dismiss <- tkbutton(buttons, text="Dismiss",
|
||
|
command=function()tkdestroy(top))
|
||
|
tkpack(dismiss, side="left", expand=TRUE)
|
||
|
|
||
|
canvas <- tkcanvas(top, relief="raised", width=450, height=300)
|
||
|
tkpack(canvas, side="top", fill="x")
|
||
|
|
||
|
plotFont <- "Helvetica 18"
|
||
|
|
||
|
tkcreate(canvas, "line", 100, 250, 400, 250, width=2)
|
||
|
tkcreate(canvas, "line", 100, 250, 100, 50, width=2)
|
||
|
tkcreate(canvas, "text", 225, 20, text="A Simple Plot",
|
||
|
font=plotFont, fill="brown")
|
||
|
|
||
|
# X tickmarks & labels
|
||
|
for (i in 0:10) {
|
||
|
x <- 100 + i * 30
|
||
|
tkcreate(canvas, "line", x, 250, x, 245, width=2)
|
||
|
tkcreate(canvas, "text", x, 254,
|
||
|
text=10*i, anchor="n", font=plotFont)
|
||
|
}
|
||
|
# Y tickmarks & labels
|
||
|
for (i in 0:5) {
|
||
|
y <- 250 - i * 40
|
||
|
tkcreate(canvas, "line", 100, y, 105, y, width=2)
|
||
|
tkcreate(canvas, "text", 96, y,
|
||
|
text=formatC(50*i,format="f",digits=1),
|
||
|
anchor="e", font=plotFont)
|
||
|
}
|
||
|
|
||
|
# The (original) data
|
||
|
points <- matrix(c(12, 56,
|
||
|
20, 94,
|
||
|
33, 98,
|
||
|
32, 120,
|
||
|
61, 180,
|
||
|
75, 160,
|
||
|
98, 223), ncol=2, byrow=TRUE)
|
||
|
|
||
|
## `self-drawing' point object
|
||
|
point.items <- apply(points, 1, function(row) {
|
||
|
x <- 100 + 3 * row[1]
|
||
|
y <- 250 - 4/5 * row[2]
|
||
|
item <- tkcreate(canvas, "oval", x - 6, y - 6, x + 6, y + 6,
|
||
|
width=1, outline="black",
|
||
|
fill="SkyBlue2")
|
||
|
tkaddtag(canvas, "point", "withtag", item)
|
||
|
item
|
||
|
})
|
||
|
|
||
|
plotDown <- function(x, y) {
|
||
|
## This procedure is invoked when the mouse is pressed over one
|
||
|
## of the data points. It sets up state to allow the point
|
||
|
## to be dragged.
|
||
|
##
|
||
|
## Arguments:
|
||
|
## x, y - The coordinates of the mouse press.
|
||
|
x <- as.numeric(x)
|
||
|
y <- as.numeric(y)
|
||
|
tkdtag(canvas, "selected")
|
||
|
tkaddtag(canvas, "selected", "withtag", "current")
|
||
|
tkitemraise(canvas,"current")
|
||
|
lastX <<- x
|
||
|
lastY <<- y
|
||
|
}
|
||
|
|
||
|
plotMove <- function(x, y) {
|
||
|
## This procedure is invoked during mouse motion events.
|
||
|
## It drags the current item.
|
||
|
##
|
||
|
## Arguments:
|
||
|
## x, y - The coordinates of the mouse.
|
||
|
x <- as.numeric(x)
|
||
|
y <- as.numeric(y)
|
||
|
tkmove(canvas, "selected", x - lastX, y - lastY)
|
||
|
lastX <<- x
|
||
|
lastY <<- y
|
||
|
}
|
||
|
### FIXME : Don't allow points to be moved outside the canvas !!
|
||
|
|
||
|
plotLine <- function(){
|
||
|
coords <- lapply(point.items,
|
||
|
function(item)
|
||
|
as.double(tkcoords(canvas,item)))
|
||
|
x <- sapply(coords, function(z) (z[1]+z[3])/2)
|
||
|
y <- sapply(coords, function(z) (z[2]+z[4])/2)
|
||
|
lm.out <- lm(y~x)
|
||
|
x0 <- range(x)
|
||
|
y0 <- predict(lm.out, data.frame(x=x0))
|
||
|
tkcreate(canvas, "line", x0[1], y0[1], x0[2], y0[2], width=3)
|
||
|
}
|
||
|
|
||
|
line <- plotLine()
|
||
|
|
||
|
lastX <- 0
|
||
|
lastY <- 0
|
||
|
|
||
|
tkitembind(canvas, "point", "<Any-Enter>",
|
||
|
function() tkitemconfigure(canvas, "current",
|
||
|
fill="red"))
|
||
|
tkitembind(canvas, "point", "<Any-Leave>",
|
||
|
function() tkitemconfigure(canvas, "current",
|
||
|
fill="SkyBlue2"))
|
||
|
tkitembind(canvas, "point", "<1>", plotDown)
|
||
|
tkitembind(canvas, "point", "<ButtonRelease-1>",
|
||
|
function(x){
|
||
|
tkdtag(canvas, "selected")
|
||
|
tkdelete(canvas, "withtag", line)
|
||
|
line <<- plotLine()
|
||
|
})
|
||
|
tkbind(canvas, "<B1-Motion>", plotMove)
|
||
|
tclServiceMode(TRUE)
|
||
|
|
||
|
cat("******************************************************\n",
|
||
|
"The source for this demo can be found in the file:\n",
|
||
|
file.path(system.file(package = "tcltk"), "demo", "tkcanvas.R"),
|
||
|
"\n******************************************************\n")
|
||
|
|
||
|
})
|