Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Создание функции ggplot

#r #ggplot2


Допустим у меня есть данные

data=data.frame(s=c(10,13,17,8),
                pr=c("a","b","a","b"),
                m=c(rep(as.Date('01.01.2015','%d.%m.%Y'),2), rep(as.Date('01.02.2015','%d.%m.%Y'),2)),
                pr2=c("c","d","d","c"))


И я пытаюсь создать функцию которая рисует ggplot в зависимости от col1 - колонка
по которой нужно делать fill.

plot_function=function(col1){...}


Функция должна возвращать ggplot

ggplot(data = data, aes(x = as.factor(m), y = s/2,fill=col1 ,ymax = max(s/2)*1.1)) + 
  geom_bar(position = "dodge", stat="identity") + 
  geom_text(aes(y=s/4,label=paste(round(s/2,3),"%")),position = position_dodge(.9)) + 
  scale_x_discrete(labels = function(x) format(as.Date(x), "%m/%y")) + 
  xlab("m")


где fill переменная внутри функции.

Пробовал сделать нечто подобное используя aes_string() вместо aes() но не знаю как
совместить операции над переменными например s/2 и aes_string().

Так же смотрел lazyeval , который я использовал в подобных ситуациях когда делал
функции из dplyr, но не смог понять как его тут применить.

в dplyr я делал вот так

group=function(data,...){

    dat1=group_by_(data,.dots = lazyeval::lazy_dots(...))
    return(dat1)
  }


Заранее спасибо за помощь.
    


Ответы

Ответ 1



На основании комментария @ArtemKlevtsov и свои догадок на этот счет в итоге сделал вот так gr_plot=function(data_12,nm){ i=which(colnames(data_12)==nm) data_12$var=data_12$s/2 data_12$m=as.factor(data_12$m) j=which(colnames(data_12)=="m") k=which(colnames(data_12)=="var") return( ggplot(data = data_12, aes_string(x = names(data_12)[j], y = names(data_12)[k],fill=names(data_12)[i]))+ geom_bar(position = "dodge",stat="identity")+ geom_text(aes(y=s/4,label=paste(round(s/2,3),"%")),position = position_dodge(.9)) + scale_x_discrete(labels = function(x) format(as.Date(x), "%m/%y")) + xlab("m") ) } соответственно достаточно просто нарисовать в различных разрезах gr_plot(data,"pr") gr_plot(data,"pr2") Если у кого то есть идеи как сделать нечто подобное через lazyeval было бы интересно увидеть.

Несколько вопросов по паттерну MVVM

#c_sharp #wpf #xaml #mvvm


Навели меня на мысль, что весь мой код является "говнокодом", потому что мои WPF
приложения не соответствуют паттерну MVVM. Я начал про это читать, но в интернетах
информация изложена слишком сложно для моего понимания. Поэтому я задам несколько вопросов,
которые откроют мне глаза (я надеюсь)


Допустим, я создаю UserControl. При этом UserControl.xaml является View, а UserControl.xaml.cs
- ViewModel? Или ViewModel - это еще один дополнительный класс, например UserControlViewModel?
Я пока склоняюсь ко второму варианту, но не уверен.
Если в прошлом вопросе правильным является второй вариант, то где мне создавать DependenceProperties?
В UserControl.xaml.cs или в UserControlViewModel? Я пока склоняюсь к первому варианту.
Если UserControl содержит команды, которые надо добавить к главному меню окна, в
котором его расположили, то как это лучше осуществить, не отклоняясь от MVVM? Причем
сделать это надо с иерархией. Первое, что приходит на ум - создать в ресурсах UserControl
новое Menu. но при слиянии иерархию надо сохранить. То есть если в главном окне уже
есть меню "Файл", и оно используется в контроле, то элементы контрола должны добавиться
к элементам этого меню в окне без создания еще одного меню "Файл".


UPD:

И еще, что такое Model?

UPD2:

К примеру, мне надо вывести в ListBox коллекцию экземпляров класса MyClass

public class MyClass
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}


в виде Prop1(Prop2)

Как мне поступить, чтобы соответствовать MVVM?

Раньше я делал так 


    
        
            
    



Получается, что это неверный подход? Или что?

UPD3:

Еще вопрос. Вью и вью-модель связываются, например, через DataСontext вьюшки (других
способов я не знаю). В этом случае вью-модель не имеет параметров у конструктора. А
как тогда связать вью-модель и модель?

UPD4:

У меня еще вопрос. Вот есть у меня модель, вью-модель и вью. Вью-модель подписана
на изменение свойств модели (хоть через PropertyChanged, хоть через отдельные события).
Тогда получится следующее. Во вьюшке чего то меняется (пользователь изменил текст в
текстовом поле).
Через биндинг это передается в сеттер вью-модели, в которой написано следующее _model.Property
= value. Но я ведь подписан на изменение свойств модели. Получается, что модель после
изменения Property сообщит вью-модели, что ее свойство изменилось, вью-модель вызовет
PropertyChanged и во вьюшке применится это значение в текстовом поле. По сути ничего
страшного не произойдет, кроме того, что программа выполнит ЛИШНИЕ ДЕЙСТВИЯ
    


Ответы

Ответ 1



Модель представления - это еще один дополнительный класс. Представление не обязательно должно быть UserControl'ом. Это может быть, например, словарь ресурсов с шаблоном данных для модели представления. Тогда ни о каком code-behind речи быть не может. Свойства зависимости нужно создавать в code-behind контрола (т.е. UserControl.xaml.cs). Это часть представления и модели представления о них знать не нужно. UserControl не должен содержать команды. Он должен привязываться к командам модели представления. Если нужна иерархия, то делайте иерархию команд в модели представления плагина (предполагаю, что вы делаете что-то плагинообразное) и сливайте их с командами модели представления главного окна. Еще я бы посоветовал избавиться от иерархии команд и подумать над тем, как их можно представить плоским списком. UPD Я согласен с Discord, потому и посоветовал делать плоский список. Это может быть набор команд в модели представления: OpenFileCommand, SaveFileCommand и т.д. А в представлении это уже будет иерархией: меню файл содержит пункты "открыть" и "сохранить". Если у вас ситуация, когда пол проекта написана на WinForms, а половина на WPF, то, возможно, ваше решение вполне подходит. Просто после переноса проекта нужно не забыть переделать эту часть. Когда мы перетаскивали проект в WinForms на WPF, то сначала изменили главное окно приложения: оно научилось работать с плагинами и формировать меню из них. Все компоненты на WinForms мы обернули в WindowsFormsHost А потом уже переделывали плагины на WPF по одному. Модель - это то, для чего вы делали модель представления (например, какой-нибудь объект из БД). Примерно так: модель - то, что нужно показать пользователю; представление - то, что видит пользователь; модель представления - связующее звено с командами и доп. свойствами, необходимыми для корректной работы представления. UPD2 С ходу довольно сложно придумать нормально решение, а на практике с именно такой задачей я не сталкивался. Например, вы можете сделать пачку интерфейсов типа: // команды, расширяющие пункт меню "Файл". interface IFileCommandsProvider { List Commands { get; } } А потом: если вкладка реализует этот интерфейс, то добавить перечень команд в меню. Либо подумать над вариантом с чем-то вроде RegionManager'а из Prism. UPD4 В описанном вами случае эти действия выполнять не надо. Если по какой-то причине (например, чтобы повесить атрибуты валидации), вы хотите спрятать свойство модели за свойством модели представления, то в модели представления имеет смысл написать следующий код: public int Property { get { return _model.Property; } set { if (_model.Property != value) { _model.Property = value; OnPropertyChanged(); } } } Тогда всю работу со свойством Property внутри модели представления нужно будет осуществлять через свойство модели представления. Т.е. кода _model.Property = value больше нигде не должно встречаться. Тогда вам не нужно будет подписываться на Model.PropertyChanged("Property").

Callback загрузки карты yandex map

#javascript #yandex_maps_api


Имеется пустая страница с картой для печати. С помощью window.print() вызывается
на печать. Проблема заключается в том, что карта не успевает отрисоваться. Никак не
могу нагуглить и нарыть в их замечательной документации какой-то вариант события или
callback'a именно на готовность карты.  

Есть предложения, коллеги?

ymaps.ready(function() {
  ymaps.ready(init);
  var map,
    object;

  function init() {
    var center = settings.map.center,
      zoom = parseInt(settings.map.zoom),
      coords_point = settings.map.coords_point;

    center = center.split(',').map(parseFloat);
    coords_point = coords_point.split(',').map(parseFloat);

    map = new ymaps.Map('yamap', {
      center: center,
      zoom: zoom,
      controls: [],
    });

    object = new ymaps.GeoObject({
      geometry: {
        type: "Point",
        coordinates: coords_point
      },
    }, {
      preset: 'custom#point_green',
    });

    map.geoObjects.add(object);
  }

  ymaps.option.presetStorage.add('custom#point_green', {
    iconLayout: 'default#image',
    iconImageHref: settings.themePath + '/img/yamap_point_g.png',
    iconImageSize: [48, 41],
    iconImageOffset: [-15, -41],
    hideIconOnBalloonOpen: false,
  });
});


Обновление

Пример вызова window.print():

Пример на JsFiddle



ymaps.ready(function() {
  ymaps.ready(init);
  var map,
    object;

  function init() {
    var center = "56.83676954481658,60.61677207117298",
      zoom = 15,
      coords_point = "56.836098132297586,60.61771118192043";

    center = center.split(',').map(parseFloat);
    coords_point = coords_point.split(',').map(parseFloat);

    map = new ymaps.Map('yamap', {
      center: center,
      zoom: zoom,
      controls: [],
    });

    object = new ymaps.GeoObject({
      geometry: {
        type: "Point",
        coordinates: coords_point
      },
    });

    map.geoObjects.add(object);
  }
});

window.print();
#yamap {
  width: 300px;
  height: 200px;
}


Ответы

Ответ 1



Поместите хотя бы window.print() внутрь ymaps.ready() и вместо ymaps.ready(init) вызывайте просто init(). Дополнено Событий, однозначно показывающих полное окончание всех процедур составления карты пока нет. Однако, как показывает практика, загрузка карты заканчивается загрузкой всех тайлов. И в документации есть описание как можно добавлять новые слои с тайлами. Это делается при помощи классов layer.tileContainer.CanvasContainer и layer.tileContainer.DomContainer. У этих-то классов есть событие ready, которое вызывается когда все тайлы слоя загружены. И они даже используются при отображении карт, но до их экземпляра не так просто добраться. Если вы ничего не делаете со слоями, то на карте есть один единственный слой (если слоев все-таки несколько, придется обрабатывать все слои в циклах), к которому можно достучаться вот так var layer = map.layers.get(0).get(0); /* Сначала мы получаем первый экземпляр коллекции слоев, потом первый слой коллекции */ Так мы получаем экземпляр Layer, но в его описании нету ничего про tileContainer, однако это поле там есть, только оно как бы приватное и при минимизации становится неудобоваримым (в debug версии это поле _tileContainer). Чтобы его найти можно воспользоваться вот такой функцией: function getTileContainer(layer) { for (var k in layer) { if (layer.hasOwnProperty(k)) { if ( layer[k] instanceof ymaps.layer.tileContainer.CanvasContainer || layer[k] instanceof ymaps.layer.tileContainer.DomContainer ) { return layer[k]; } } } return null; } Теперь можно сделать так: var tc = getTileContainer(layer); tc.events.once("ready", function() { // Вызываем, например, печать документа window.print(); }); Одно плохо. Мы не узнаем о загрузке всех тайлов если выяснится, что мы не успели начать слушать событие до окончания загрузки тайлов. Неплохо было бы знать вообще чего-то ждем или нет. Для этого перед "подслушиванием" события нужно узнать есть-ли "неготовые" тайлы. Это можно проверить если перебрать все тайлы в контейнере и вызвать методы isReady() для layer.tile.CanvasTile или layer.tile.DomTile, после этого, если неготовые тайлы есть подключать событие. Будет удобно сделать такую функцию, которая будет возвращать промис. function waitForTilesLoad(layer) { return new ymaps.vow.Promise(function (resolve, reject) { var tc = getTileContainer(layer), readyAll = true; tc.tiles.each(function (tile, number) { if (!tile.isReady()) { readyAll = false; } }); if (readyAll) { resolve(); } else { tc.events.once("ready", function() { resolve(); }); } }); } В вашем случае этой функцией можно воспользоваться так: waitForTilesLoad(layer).then(function() { window.print(); });

Ответ 2



Привожу код, написанный @tutankhamun. // Здесь ваша загрузка карты. Ниже допишем строки. /* Поймаем событие завершения загрузки карты. */ // Сначала мы получаем первый экземпляр коллекции слоев, потом первый слой коллекции. var layer = myMap.layers.get(0).get(0); // Отслеживаем событие окончания отрисовки тайлов. waitForTilesLoad(layer).then(function() { // Вызываем, например, печать документа window.print(); alert('Карта загружена'); }); } // Получить слой, содержащий тайлы. function getTileContainer(layer) { for (var k in layer) { if (layer.hasOwnProperty(k)) { if ( layer[k] instanceof ymaps.layer.tileContainer.CanvasContainer || layer[k] instanceof ymaps.layer.tileContainer.DomContainer ) { return layer[k]; } } } return null; } // Определить, все ли тайлы загружены. Возвращает Promise. function waitForTilesLoad(layer) { return new ymaps.vow.Promise(function (resolve, reject) { var tc = getTileContainer(layer), readyAll = true; tc.tiles.each(function (tile, number) { if (!tile.isReady()) { readyAll = false; } }); if (readyAll) { resolve(); } else { tc.events.once("ready", function() { resolve(); }); } }); }

При добавлении класса анимация с keyframes работает, а при удалении нет, хотя transition задано

#css #анимация #css_animation #keyframes


В этом примере все достаточно очевидно и отрабатывает правильно



$('div').click(function() {
  $('div').toggleClass('wide');
});
div {
  width: 80px;
  height: 30px;
  background-color: green;
  transition: all 0.4s ease-in-out;
}
.wide {
  width: 140px;
  background-color: blue;
}


Но мне необходимо усложнить анимацию, как это сделать правильно? При добавлении keyframes анимация отрабатывает только при добавлении класса, а при удалении все происходит без анимации. $('div').click(function() { $('div').toggleClass('wide'); }); div { width: 80px; height: 30px; background-color: green; transition: all 0.4s ease-in-out; } @keyframes blue { 50% { background-color: blue; } 100% { width: 200px; background-color: blue; } } .wide { animation-name: blue; animation-duration: 0.4s; animation-fill-mode: both; }
Как мне необходимо организовать код, чтобы анимация по клику отрабатывала "в обе стороны"?


Ответы

Ответ 1



Анимации (animation), в отличие от переходов (transition), работают только в одну сторону. Переключение направления нормально не поддерживается. Вообще-то существует свойство animation-direction, но оно не поможет, потому что, если имя анимации не меняется, то элемент продолжает "проигрывать" одну и ту же последовательность. Если изменить направление, то анимация будет всё ещё в завершённом состоянии, и просто изменится конечное значение, которое браузер и применит моментально. И удаление имени анимации animation-name не поможет, потому что в этом случае сбросится и конечное значение, что вас не устроит (animation-fill-mode у вас both). Что касается переходов, то они существуют отдельно от анимаций, анимировать одни и те же свойства двумя способами бессмысленно, а свойства переходов на анимации не влияют. Если хотите анимировать в обе стороны, то нужно использовать или анимации с двумя отдельными @keyframes для каждого направления, или переходы, которые поддерживают изменение направления. См. также: Reverse Keyframe animation with Javascript Possible to reverse a css animation on class removal?

Ответ 2



Можно указывать несколько transition'ов через запятую, а также сдвигать их начало: $('div').click(function() { $('div').toggleClass('wide'); }); div { width: 80px; height: 30px; background-color: green; transition: width 4s ease-in-out, background-color 2s ease-in-out; transition-delay: 0s, 2s; } .wide { width: 380px; background-color: blue; transition-delay: 0s; } section { height: 10px; border-left: 80px silver solid; border-right: 150px silver solid; background-color: red; width: 150px; }


Как подключить шейдеры в WebGL-приложениях?

#javascript #html5 #графика #webgl #glsl


В книге К. Мацуда, Р. Ли - WebGL. Программирование трехмерной графики везде используется
встроенные шейдеры. Как подключить шейдеры из файлов. Решение описанное в этой же книге
не заработало:


  XMLHttpRequest cannot load file:///D:/Development/WebGL/DrawPoint/DrawPointVertesShader.gls.
Cross origin requests are only supported for protocol schemes: http, data, chrome,
chrome-extension, https, chrome-extension-resource.loadShaderFile @ ShaderUtilities.js:12
  
  XMLHttpRequest cannot load file:///D:/Development/WebGL/DrawPoint/DrawPointFragmentShader.gls.
Cross origin requests are only supported for protocol schemes: http, data, chrome,
chrome-extension, https, chrome-extension-resource.


Некоторые предлагали поднимать сервак и оттуда брать. Но это не годится так как пишется
игра и конечно игра должна работать без сучка и задоринок у пользователя. Есть ли какой-нибудь
простой механизм?
    


Ответы

Ответ 1



Истоки Вашей проблемы в том, что с веб страниц, которые были открыты по протоколу file:// не удается получить по этому-же протоколу ресурсы, которые лежат рядом на диске. Эта возможность в браузерах отключена из соображений безопасности. Однако, Вы совершенно не обязаны подключать шейдеры как отдельные файлы. Вам необходимо лишь передать компилятору шейдеров их исходный код, в виде строк, а как вы будете хранить и получать эти строки в том месте где она нужны - дело десятое. Таким образом Вы можете создать одну html страницу с webgl приложением, которое будет открываться локально и без веб-сервера. Можно держать glsl код прямо в javascript секциях в виде строк: Если используется любой любой из всевозможных современных бандлеров(вроде webpack), которые упаковывают веб приложения в одну или несколько портянок js, вы можете держать текст шейдера в отдельном файле. И импортировать его по месту использования, так появляется какая никакая модульность в glsl. Следующим шагом является модульность непосредственно внутри glsl кода, (чтобы не копи-пастить по 300 раз в разных шейдерах один и тот же код) тут 2 пути: собственный велосипед или более серьезное решение, например вот glslify это уже готовое решение и огромная экосистема всевозможных кусочков для шейдеров, построенная поверх npm let glsl = require('glslify') let shaderCode = glsl(` #pragma glslify: noise = require('glsl-noise/simplex/3d') precision mediump float; varying vec3 vpos; void main () { gl_FragColor = vec4(noise(vpos*25.0),1); } `); На просторах интернета и во многих туториалах используют теги PS: фрактал, который тут рисуется нашел и рассказал о нем миру некто Kali в этом топике с fractalforums

Как временно “приглушить” monit на период развертывания сервиса через ansible?

#linux #развертывание #ansible #monit


Есть сервер на linux, на нем работает некий сервис myservice, за сервисом наблюдает
monit. Сообщает на почту обо всех изменениях и при необходимости перезагружает сервис.

Есть ansible playbook, который переустанавливает сервис, конфигурирует и перезапускает.
И monit тоже конфигурирует и перезапускает при необходимости. Работает это отлично,
но плохо то, что при этом monit шлет пачку писем:


service instance пропал
service instance появился
service instance сменил PID
monit перезагрузился


Можно в роли давать monit задачу приостанавливать мониторинг, но об этой задаче он
тоже сообщает. Дважды.

- name: monit не наблюдает за myservice
  shell: monit unmonitor myservice

- name: monit наблюдает за myservice
  shell: monit monitor myservice


Можно перезапускать сервис из самого monit'a. Тогда письма приходят с менее угрожающими
заголовками, вроде Action done myservice. Но всё равно одно или два письма + одно про
релоад монита.

- name: Перезапуск myservice через monit
  shell: monit restart myservice


Я беспокоюсь о том, что это всё сработает как у мальчика, который кричал «Волки!».
Все привыкнут, что с почты постоянно валится куча писем и что это нормальный процесс,
волноваться не о чем. Поэтому хочу, чтобы штатные работы не приводили ни к каким тревогам
вообще.

Можно ли это как-то реализовать на этом стеке технологий? Или я категорически неправ
в своих опасениях?
    


Ответы

Ответ 1



Решение monit config: /etc/monit/monitrc set alert {{mail_recipient}} but not on { action, instance } ansible: Во всех командах параметр -I нужен, почему — смотри ниже. В начале установки через monit останавливаем сервис, это считается action - name: Остановка myservice через monit shell: monit -I stop myservice Потом производим всю необходимую установку и настройку. Убеждаемся, что сам monit запущен. Перезагружаем конфиги через сам monit, это событие типа instance - name: Убедиться, что monit запущен service: name=monit state=started - name: Перезагрузка конфигов monit shell: monit -I reload Потом перезагружаем сервис, это считается action - name: Перезапуск myservice через monit shell: monit -I restart myservice Конфигурация monit Получать только определенные события set alert foo@bar only on { timeout, nonexist } Получать все события кроме некоторых: set alert foo@bar but not on { instance } Подробнее про фильтрацию событий в monit: https://mmonit.com/monit/documentation/monit.html#Setting-an-event-filter Оставшиеся проблемы monit "забывает" команды, отданные после перезагрузки — решено. Разобрано в отдельном вопросе, здесь я просто добавляю -I к командам. C такой конфигурацией monit перестает сообщать об изменениях собственного instance не только на период развертывания, а вообще. То есть, если он был перезагружен вручную, либо если упал а потом был поднят при развертывании — то сообщения не будет. Можно оставить только такой конфиг: set alert {{mail_recipient}} but not on { action } Но тогда при развертывании все равно будет одно сообщение на почту про sudo monit reload. Безуспешно пробовал такую схему, она не работает. name: monit - приостановить мониторинг shell: monit unmonitor all name: monit - перезагрузка конфигов shell: monit reload name: monit - возобновить мониторинг shell: monit monitor all

Java Линукс/Win консольное прослушивание нажатия клавиатуры

#java #консоль #ввод #клавиатура #listener


Пишу Java консольное приложение для Линукс и Виндовс, которое одновременно прослушивает
нажатие клавиатуры и выводит информацию (без нажатия клавиши Enter для принятия ввода
текста).

Как это можно сделать?

Знаю про JNI, Jline, JavaCurces но нет навыков их использования, хотелось бы сделать
все средствами Java.
    


Ответы

Ответ 1



Одной из ключевых особенностей Java является написание кроссплатформенных программ. Для получения одинакового результата в разных операционных системах Java выполняет разный код в разных ОС. Упомянутые Вами программы это именно именно такие обёртки над системными функциями. Если кроссплатформенность хоть сколько-нибудь важна, лучше использовать их. Из JLine FAQ: How does JLine work? On Windows, JLine uses a native .dll (which it automatically extracts from the jline jar and loads at runtime) to access native console features. On UNIX systems, JLine will perform the necessary terminal setup by launching the "stty" command.

Ответ 2



На данный момент, я нашел решение с использованием jNativeHook. На Windows еще не тестировал, на Alt Linux работает хорошо. Осталось только сделоть прослушку клавиш не глобальгно, а только для окна консоли. package test; import java.io.IOException; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; import org.jnativehook.GlobalScreen; import org.jnativehook.NativeHookException; import org.jnativehook.keyboard.NativeKeyEvent; import org.jnativehook.keyboard.NativeKeyListener; public class Test0 implements NativeKeyListener { public static void main(String[] args) throws IOException { for (Handler handler : Logger.getLogger("").getHandlers()) handler.setLevel(Level.OFF); try { GlobalScreen.registerNativeHook(); } catch (NativeHookException ex) { System.exit(1); } GlobalScreen.addNativeKeyListener(new Test0()); } public void nativeKeyPressed(NativeKeyEvent e) { System.out.println(NativeKeyEvent.getKeyText(e.getKeyCode()).toLowerCase()); } public void nativeKeyReleased(NativeKeyEvent e) { } public void nativeKeyTyped(NativeKeyEvent e) { } } Все еще надеюсь найти лучшее решение, или сделать прослушку не глобальной.

Ответ 3



Такой вопрос уже был на stackoverflow: Equivalent function to C's “_getch()” in Java? Вот исходный код на ваш вопрос. Опубликованный в посте: public static void getCh() { final JFrame frame = new JFrame(); synchronized (frame) { frame.setUndecorated(true); frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME); frame.addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { synchronized (frame) { frame.setVisible(false); frame.dispose(); frame.notify(); } } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } }); frame.setVisible(true); try { frame.wait(); } catch (InterruptedException e1) { } } }

Ответ 4



Эт уже руткит получается. В линухе так получится отслеживать только того, из под которого запущена прога. Да и то вряд-ли.