GetGraphicsEvent для чтения клавиатуры для неинтерактивного сеанса
В старых версиях R, версии 2.9 в любом случае мне удалось запустить программу R из пакета с помощью rterm.exe и создать графическое окно, которое пользователь мог бы прокручивать назад и вперед и просматривать графики. Я смог сделать это, используя некоторый код R, например:
kbd <- function(key) {
if (key == "q") { "Quit" } else NULL }
getGraphicsEvent(" ", onKeybd = kbd)
Это удерживало графический просмотрщик открытым до тех пор, пока пользователь не нажмет клавишу "q". В более новых версиях R кажется, что, поскольку это начинается с пакетной (неинтерактивной с использованием Rterm.exe), значение ключа всегда равно NULL, а графическое окно просто мигает и закрывается. Мой вопрос в том, можно ли каким-то образом убедить систему R, что я выполняю квазиинтерактивный сеанс и получить поведение getGraphicsEvent, чтобы не сразу возвращать NULL?
Ответы
Ответ 1
Вы можете подделать интерактивный сеанс в одном, который будет обнаружен как неинтерактивный, запустив Rterm с помощью опции
--ess
в Windows или
--interactive
в Unix-alikes.
Это может вызвать другие проблемы, поскольку все функции будут видеть сеанс как интерактивный. Вы не можете изменить этот флаг в середине сеанса, так как он затрагивает множество вещей, связанных с I/O.
Ответ 2
Вот исходный код для getGraphicsEvent:
function (prompt = "Waiting for input", onMouseDown = NULL, onMouseMove = NULL,
onMouseUp = NULL, onKeybd = NULL, consolePrompt = prompt)
{
if (!interactive())
return(NULL)
if (!missing(prompt) || !missing(onMouseDown) || !missing(onMouseMove) ||
!missing(onMouseUp) || !missing(onKeybd)) {
setGraphicsEventHandlers(prompt = prompt, onMouseDown = onMouseDown,
onMouseMove = onMouseMove, onMouseUp = onMouseUp,
onKeybd = onKeybd)
}
.External2(C_getGraphicsEvent, consolePrompt)
}
Вы можете понять, почему он возвращает NULL, так как это явно выражается с помощью if (!interactive()) return(NULL)
. Попробуйте это вставить в исходный код:
getGraphicsEvent2 = function (prompt = "Waiting for input", onMouseDown = NULL, onMouseMove = NULL,
onMouseUp = NULL, onKeybd = NULL, consolePrompt = prompt)
{
# if (!interactive())
# return(NULL)
if (!missing(prompt) || !missing(onMouseDown) || !missing(onMouseMove) ||
!missing(onMouseUp) || !missing(onKeybd)) {
setGraphicsEventHandlers(prompt = prompt, onMouseDown = onMouseDown,
onMouseMove = onMouseMove, onMouseUp = onMouseUp,
onKeybd = onKeybd)
}
.External2(C_getGraphicsEvent, consolePrompt)
}
environment(getGraphicsEvent2) = environment(grDevices::getGraphicsEvent)
dragplot(rnorm(1000), rnorm(1000))
kbd = function(key) {
if (key == "q") { "Quit" } else NULL }
getGraphicsEvent2("Waiting for input", onKeybd = kbd)
Кажется, что теряют функциональность (т.е. я не мог манипулировать графиком на OSX с X11 в качестве графического устройства), но по крайней мере сюжет остается. Вызов внутреннего кода для этой функции недавно изменился (чтобы подтвердить, посмотрите исходный код для R в двух версиях - код для этой функции в R 2.6.2, например, находится в R-2.6.2/src/library/grDevices/R/gevents.R).