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 немедленно?

2 ответа

Вы можете подделать интерактивный сеанс, который будет определен как неинтерактивный, запустив Rterm с параметром

--ess

в Windows или

--interactive

на Unix-подобных.

Это может вызвать другие проблемы, потому что все функции будут видеть сеанс как интерактивный. Вы не можете изменить этот флаг в середине сеанса, так как он влияет на многие вещи, связанные с вводом / выводом.

Вот исходный код для getGraphicsEvent:

function (prompt = "Ожидание ввода", onMouseDown = NULL, onMouseMove = NULL, 
    onMouseUp = NULL, onKeybd = NULL, consolePrompt = приглашение) 
{

    if (!interactive()) 
        вернуть (NULL)
    if (! отсутствует (приглашение) ||! отсутствует (onMouseDown) ||! отсутствует (onMouseMove) ||! отсутствует (onMouseUp) ||! отсутствует (onKeybd)) {
        setGraphicsEventHandlers(prompt = prompt, onMouseDown = onMouseDown, 
            onMouseMove = onMouseMove, onMouseUp = onMouseUp, 
            onKeybd = onKeybd)
    }
    .External2(C_getGraphicsEvent, consolePrompt)
}

Вы можете понять, почему он возвращает NULL, так как это делается с помощью if (!interactive()) return(NULL), Попробуйте это вставить в свой оригинальный код:

getGraphicsEvent2 = function (prompt = "Ожидание ввода", onMouseDown = NULL, onMouseMove = NULL, 
    onMouseUp = NULL, onKeybd = NULL, consolePrompt = приглашение) 
{

  #  if (!interactive()) 
  # возврат (NULL)
    if (! отсутствует (приглашение) ||! отсутствует (onMouseDown) ||! отсутствует (onMouseMove) ||! отсутствует (onMouseUp) ||! отсутствует (onKeybd)) {
        setGraphicsEventHandlers(prompt = prompt, onMouseDown = onMouseDown, 
            onMouseMove = onMouseMove, onMouseUp = onMouseUp, 
            onKeybd = onKeybd)
    }
    .External2(C_getGraphicsEvent, consolePrompt)
}
environment(getGraphicsEvent2) = среда (grDevices::getGraphicsEvent)

драгплот (рнорм (1000), ннорм (1000))


kbd = функция (ключ) { 
 if (key == "q") { "Quit" } else NULL } 
 getGraphicsEvent2("Ожидание ввода",  onKeybd = kbd) 

Кажется, он теряет функциональность (то есть, я не мог манипулировать сюжетом на OSX с X11 в качестве графического устройства), но, по крайней мере, сюжет остается неизменным. Вызов внутреннего кода для этой функции недавно изменился (для подтверждения посмотрите исходный код для R в двух версиях - код для этой функции в R 2.6.2, например, находится в R-2.6.2/src/library/grDevices/R/gevents.R).

Другие вопросы по тегам