感谢 article 中的 Yair Altman 信息,我得到了一些工作,但它涉及侵入 Matlab Java 基础对象(即命令窗口)。
它涉及将监听器附加到 Matlab 命令窗口。现在要小心,经常保存你的工作,并准备好多次杀死 Matlab 进程,直到你把它弄对......因为每次你在代码中出现错误时,你都会陷入一种无限循环(错误/警告被发送到命令窗口,这会触发您的侦听器,从而重新触发错误等...)。为了让下面的示例以稳定的方式工作,我不得不重新启动 Matlab 很多次。
这也是我暂时只附上监听器的原因。就在发送dos 命令之前,我直接删除了监听器。您可以永久离开听众或根据您的需要进行调整,但请记住上面的建议。还要考虑命令窗口可以包含大量字符,您可能不希望所有字符都在文本框中,因此您必须管理从中获取的文本(如示例中的子集),并考虑您是否想要追加或只是刷新文本框中的文本。
下面的例子看起来很稳定,任何修改都需要您自担风险;-)
在评论请求后,我添加了 3 个功能:
onCleanup。这是一个 Matlab 功能,允许在出现问题时采取最后的措施(一种“包罗万象”的机制)。强烈推荐使用 undocumented 函数的此类程序。
一个myCloseRequestFcn 拦截窗口的关闭动作以移除监听器并避免错误循环。
scroll_to_bottom 函数。这允许将文本框插入符号移动到文本的末尾(=滚动到底部以防文本多于可见空间)。
警告:最后一个功能可能值得单独提问并再次调用未记录功能(因此永远无法保证兼容性)。为了能够实现它,您需要在您的 Matlab 路径中提供 findjobj 函数。如果您不想下载外部组件,请删除/注释使用它的代码部分和子函数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',[]) ;