Подтвердить что ты не робот

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?

4b9b3361

Ответ 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).