matlab: muestra el resultado del comando dos en texto estático
batch-file cmd (2)
Gracias a la información de Yair Altman en este artículo , tengo algo que trabajar, pero implica piratear los objetos base de Matlab Java (es decir, la ventana de comandos).
Implica conectar un oyente a la ventana de comandos de Matlab. Ahora ten cuidado, guarda tu trabajo a menudo y prepárate para matar el proceso de Matlab bastantes veces hasta que lo hagas bien ... porque cada vez que tienes un error en el código estás atrapado en una especie de ciclo infinito (el error / se envía una advertencia a la ventana de comandos, que activa su oyente, que vuelve a activar el error, etc. ...). Tuve que reiniciar Matlab una buena docena de veces solo para que el siguiente ejemplo funcione de manera estable.
Esa es también la razón por la que solo adjunto al oyente temporalmente. justo antes de enviar el comando dos
y elimino el oyente directamente después. Puede dejar al oyente de forma permanente o ajustarlo a sus necesidades, pero recuerde los consejos que acabamos de mencionar. Tenga en cuenta también que la ventana de comandos puede contener una gran cantidad de caracteres, lo que puede no desear en su cuadro de texto, por lo que debe gestionar el texto que obtiene de él (tome un subconjunto como en el ejemplo) y considere si desea agregar o simplemente actualizar el texto en el cuadro de texto.
El siguiente ejemplo parece ser estable, cualquier modificación bajo su propio riesgo ;-)
Después de la solicitud en el comentario agregué 3 funciones:
Un
onCleanup
. Esta es una funcionalidad de Matlab que permite la acción de último recurso en caso de que algo salga mal (una especie de mecanismo de "atrapar todo"). Muy recomendable para este tipo de programa que utiliza funciones no documentadas .Un
myCloseRequestFcn
que intercepta la acción de cierre de la ventana para eliminar el oyente y evitar los bucles de error.Una función
scroll_to_bottom
. Este permite mover el cuadro de texto de cursor al final del texto (= para desplazarse hacia la parte inferior en caso de que haya más texto que espacio visible).
Advertencia: la última funcionalidad podría merecer una pregunta por separado y volver a solicitar la funcionalidad no documentada (por lo que nunca se garantiza la compatibilidad). Para poder implementarlo, necesita tener la función findjobj
disponible en su ruta de Matlab. Si no desea descargar el componente externo, elimine / comente la parte del código que lo usa y la subfunción scroll_to_bottom
(y olvídese de desplazar el cuadro de texto, no hay forma de hacerlo en Matlab puro). O puede elegir la versión anterior del código mirando el historial de edición de la publicación .
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'',[]) ;
Estoy usando GUI para llamar a un comando de terminal. Al usar dos(my_command, ''-echo'')
puedo obtener el resultado del comando en la ventana de comandos de Matlab. ¿Hay -echo
replicar ese -echo
en un texto estático en mi GUI?
Actualmente, con my_command
, escribo el resultado en un archivo de log
y actualizo el String del texto estático después de que el proceso finaliza, pero lo que quiero es una live-view
en live-view
como en la ventana de comandos: el resultado se muestra línea por línea en real -hora. Gracias.
Actualizar:
@Hoki: otra pregunta es: cuando los comandos de la consola se están ejecutando, si cierro la GUI, entonces Matlab devuelve los errores inservibles, ¿cómo puedo congelar toda la GUI hasta que los comandos hayan finalizado?
Matlab no ofrece una forma nativa de obtener resultados continuamente durante la ejecución de dos
, unix
y system
. Sin embargo, existe la posibilidad de lograr el comportamiento deseado.
Esta es la solución alternativa propuesta:
- Ejecute su comando y canalice la salida a un archivo.
- Use el carácter
&
para continuar la ejecución del código de Matlab. - Lea los contenidos de este archivo continuamente y actualice la GUI en consecuencia.
- Introduzca un segundo archivo temporal que indique el final del comando para detener el proceso de actualización.
Aquí está el código:
% 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]);