2015-07-09 1 views
2

Я использую GUI для вызова команды терминала. Используя dos(my_command, '-echo'), я могу получить вывод команды в командном окне Matlab. Есть ли способ воспроизвести этот -echo в статическом тексте в моем графическом интерфейсе?matlab - выводить вывод команды dos на статический текст

В настоящее время, с my_command, я пишу вывод в log файл и обновить строку статического текста путем этого log файла после завершения процесса, но то, что я хочу это live-view как в командном окне: выход отображается строка за строкой в настоящее время. Благодарю.

Update:

@Hoki: еще один вопрос не: когда команды для консоли выполняется, если я закрою GUI, то Matlab возвращает ошибки unstopable, как я могу заморозить весь GUI до тех пор пока команды закончили?

enter image description here

+0

Followup вопрос был здесь спросил: http://stackoverflow.com/questions/38478641/duplicate-matlab-command-window-to-gui –

ответ

2

Благодаря Яир Альтмана информации в этом article, я получил что-то работать, но она включает в себя взлом базовых объектов Matlab Java (а именно окно командной строки).

commandWindowGui

Она включает в себя прикрепление слушателя к окну команды Matlab. Теперь будьте осторожны, часто сохраняйте свою работу и будьте готовы убить процесс Matlab довольно много раз, пока не получите правильное решение ... потому что каждый раз, когда вы получаете ошибку в коде, вы застреваете в виде бесконечного цикла (ошибка/предупреждение отправляется в окно команд, которое запускает ваш слушатель, который повторно запускает ошибку и т. д.). Мне пришлось много раз перезапустить Matlab, чтобы привести пример ниже, чтобы работать стабильно.

Это также является причиной, по которой я временно присоединяю слушателя. перед отправкой команды dos, и я удаляю прослушиватель непосредственно после. Вы можете оставить слушателя навсегда или настроить его на свои нужды, но помните совет только что выше. Также учтите, что в командном окне может содержаться огромное количество символов, которые вам могут не нравиться все в вашем текстовом поле, поэтому вам нужно управлять текстом, который вы получаете от него (возьмите подмножество, как в примере), и подумайте, если вы хочу добавить или просто обновить текст в текстовом поле.

В приведенном ниже примере, как представляется, стабильным, как она есть, любое изменение в ваши собственные риски ;-)

После запроса в комментарии я добавил 3 функции:

  • onCleanup. Это функциональность Matlab, позволяющая использовать последнее действие курорта в случае, если что-то пойдет не так (своего рода механизм «поймать все»). Настоятельно рекомендуется для этой программы, используя недокументированные функции.

  • A myCloseRequestFcn, которые перехватывают закрывающее действие окна, чтобы удалить слушателя и избежать ошибок.

  • A scroll_to_bottom функция. Это позволяет перемещать курсор в конец текста (= для прокрутки в нижней части, если имеется больше текста, чем видимое пространство).

Предупреждение: Последние функциональные возможности могли бы заслуживают отдельного вопроса и снова призывают к незарегистрированной функциональности (поэтому совместимость никогда не гарантировано). Чтобы иметь возможность реализовать это, вы должны нуждаться в, чтобы иметь функцию findjobj, доступную в вашем пути Matlab. Если вы не хотите загружать внешний компонент, удалите/прокомментируйте часть используемого кода и подфункцию scroll_to_bottom (и забудьте про прокрутку текстового окна, в чистом Matlab нет способа сделать это). Или вы можете выбрать предыдущую версию кода, просмотрев историю изменений сообщения.


function h = gui_MirrorCmdWindow 

%% // just to remove the listener in case something goes wrong 
closeup = onCleanup(@() cleanup); 

%% // create figure and uicontrol 
h.f = figure; 
h.txtOut = uicontrol(h.f,'Style','edit','Max',30,'Min',0,... 
        'HorizontalAlignment','left',... 
        'FontName','FixedWidth',... 
        'Units','Normalized',... 
        'Enable','On',... 
        'Position',[.05 .2 .9 .75]); 

h.btnPing = uicontrol(h.f,'Style','Pushbutton',... 
        'String','Ping',... 
        'Units','Normalized',... 
        'Position',[.05 .05 .9 .1],... 
        'Callback',@btnPing_callback); 

guidata(h.f,h) 

%// intercept close request function to cleanup before close 
set(gcf,'CloseRequestFcn',@myCloseRequestFcn) 

%% // Get the handle of the Matlab control window 
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance; 
jCmdWin = jDesktop.getClient('Command Window'); 
jTextArea = jCmdWin.getComponent(0).getViewport.getView; 

%% // Get the handle of the jave edit box panel component 
jtxtBox = findjobj(h.txtOut) ; 
jTxtPane = jtxtBox.getComponent(0).getComponent(0) ; 

%// Save these handles 
setappdata(h.f , 'jTextArea', jTextArea) ; 
setappdata(h.f , 'jTxtPane', jTxtPane) ; 


function btnPing_callback(hobj,~) 
    h = guidata(hobj) ; 
    jTextArea = getappdata(h.f , 'jTextArea') ; 

    my_command = 'ping google.com -n 10' ; 
    startPos = jTextArea.getCaretPosition ; 
    set(jTextArea,'CaretUpdateCallback',{@commandWindowMirror,h.f,startPos}) ; 
    dos(my_command , '-echo') ; 
    pause(1) %// just to make sure we catch the last ECHO before we kill the callback 
    set(jTextArea,'CaretUpdateCallback',[]) ; 
    scroll_to_bottom(h.f) 


function commandWindowMirror(~,~,hf,startPos) 
    h = guidata(hf) ; 
    jTextArea = getappdata(h.f , 'jTextArea') ; 

    %// retrieve the text since the start position 
    txtLength = jTextArea.getCaretPosition-startPos ; 
    if txtLength > 0 %// in case a smart bugger pulled a 'clc' between calls 
     cwText = char(jTextArea.getText(startPos-1,txtLength)) ; 
    end 
    %// display it in the gui textbox 
    set(h.txtOut, 'String',cwText) ; 
    scroll_to_bottom(h.f) 


function scroll_to_bottom(hf) 
    %// place caret at the end of the texbox (=scroll to bottom) 
    jTxtPane = getappdata(hf , 'jTxtPane') ; 
    jTxtPane.setCaretPosition(jTxtPane.getDocument.getLength) 


function myCloseRequestFcn(hobj,~) 
    cleanup ;  %// make sure we remove the listener 
    delete(hobj) ; %// delete the figure 


function cleanup 
    jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance; 
    jCmdWin = jDesktop.getClient('Command Window'); 
    jTextArea = jCmdWin.getComponent(0).getViewport.getView; 
    set(jTextArea,'CaretUpdateCallback',[]) ; 
+0

Я попытаюсь сначала смешать это с моим графическим интерфейсом и вернуться – scmg

+0

Я попытался и все еще задал вопрос: если журнал слишком длинный, как я могу установить текстовую позицию в конце? – scmg

+0

@scmg. Я не понимаю ваш вопрос. Вы имеете в виду установить начальную позицию копии в конце командного окна? – Hoki

2

Matlab не предлагает нативный способ получить результаты непрерывно во время выполнения dos, unix и system. Тем не менее есть возможность добиться желаемого поведения.

Это предлагаемая работа вокруг:

  • Выполнить вашу команду и передать выходные данные в файл.
  • Используйте символ &, чтобы продолжить выполнение Matlab-кода.
  • Постоянно читайте содержимое этого файла и соответствующим образом обновляйте графический интерфейс.
  • Представьте второй временный файл, указывающий конец команды, чтобы остановить процесс обновления.

Вот код:

% create figure and uicontrol 
fh = figure; 
txtbox = uicontrol(fh,'Style','edit','Max',30,'Min',0,... 
        'HorizontalAlignment','left',... 
        'FontName','FixedWidth',... 
        'Position',[30 30 450 200]); 

% store current path 
path = cd; 

% delete token to make sure the loop continues as expected 
warnstate = warning('off','MATLAB:DELETE:FileNotFound'); 
delete(fullfile(path,'temp_cmdlog_done')); 
warning(warnstate); % restore original warning state 

% execute dos-command in background 
cmd = 'ping -c 5 192.168.200.1'; 
dos([cmd,' > temp_cmdlog && echo > temp_cmdlog_done &']); 

% refresh text in uicontrol until dos-command is done 
while 1 
    out = fileread('temp_cmdlog'); 
    set(txtbox,'String',out); 
    if exist(fullfile(path,'temp_cmdlog_done'),'file') 
     break; 
    end 
    pause(0.2); % adjust to suit your needs 
end 

% delete the temporary files 
delete(fullfile(path,'temp_cmdlog')); 
delete(fullfile(path,'temp_cmdlog_done')); 

% indicate that process finished 
set(txtbox,'ForegroundColor',[0,0.5,0]); 
+0

но с использованием '' & в конце будет сохранить cmd-Window открытым в фоновом режиме, есть все равно, чтобы избежать этого? – scmg

+0

Кстати, я думаю, что это должен быть единственный '&' in '> temp_cmdlog && echo> temp_cmdlog_done' – scmg

+0

@scmg Чтобы протестировать вышеупомянутый скрипт, я использовал OSX и' system'-command. Именно по этой причине я использовал '&&', потому что другие версии не работали для меня. Если вы подтвердите, что он работает с одним '&', я изменю его. Я не знаю прямого решения о том, как закрыть окно. – Matt

Смежные вопросы