【问题标题】:How to get handle to active object MATLAB GUI如何处理活动对象 MATLAB GUI
【发布时间】:2016-11-01 15:29:14
【问题描述】:

我正在尝试使用 MATLAB GUI 创建日历。 我有两个 Edit Text 对象 - edittext1edittext2

我想做这个: 我将光标放在edittext1,然后在日历上选择日期,它进入edittext1 的文本字段。 edittext2 也是如此:如果我将光标放入 edittext2 并选择它放入 edittext2 的日期编辑文本。

我知道我可以通过这种方式为日历使用回调。

问题:

如何将回调函数处理程序放入 ACTIVE 编辑文本对象? 如何获取当前光标所在对象的句柄?

【问题讨论】:

  • Something like this 通过调试器运行时功能正常,但由于某种原因,我无法让它自己正常工作。我讨厌 Java...
  • @excaza 非常感谢!我尝试简化代码以找出错误。请再看一次我编辑的问题。
  • @excaza 我决定将问题分成两部分stackoverflow.com/questions/40374942/…
  • @excaza,我modified your example,它现在即使在正常模式下也可以工作(在获取java对象属性之前只需要一个pause(0.1)。(其他修改是因为我在R2013a上所以我无法使用点符号,我不得不恢复到旧的set/get)。
  • 这太棒了! @Hoki 你能详细解释一下吗?我无法想象你是如何找到这个解决方案的......你或 excaza 必须在这里写下答案!

标签: matlab user-interface matlab-guide


【解决方案1】:

关于focus问题,java日历上点击日期时没有active文本框,因为active组件在这次java日历。

要知道哪个文本框是活动的最后,您只需要跟踪它。一种方法是向编辑框添加回调,它将使用最新活动文本框的句柄更新一个变量(存储在appdata)。

有了这个,日历的回调将只检索日期,然后将其放在 last active 文本框中。

注意:如果文本框'enable' 属性为'off''inactive',则文本框的ButtonDownFcn 事件只会在左 右键单击​​时触发。 (如果是'on',则只检测到右键)。这就是为什么我将文本框声明为inactive。这并不妨碍您以编程方式更新文本,所以我认为这不是问题。


testcalendar.m 的代码:

function testcalendar
handles.f = figure;

commonEditProperties = {'Style', 'edit', 'String', '', ...
    'Units', 'Normalized', ...
    'Enable','inactive' , ...
    'callback',@EditBoxFcn , ...
    'ButtonDownFcn',@EditBoxFcn } ;

handles.ledit = uicontrol( commonEditProperties{:}, 'Position', [0.1 0.1 0.3 0.1], 'Tag','ledit'  );
handles.redit = uicontrol( commonEditProperties{:}, 'Position', [0.5 0.1 0.3 0.1], 'Tag','redit' );

% preallocate a variable to hold the active text box handle
setappdata(handles.f,'activeTextBox',[]) ;

com.mathworks.mwswing.MJUtilities.initJIDE;
% Put calendar to my figure
handles.jPanel = com.jidesoft.combobox.DateChooserPanel;
[handles.hPanel,handles.hContainer] = javacomponent(handles.jPanel,[100,100,200,200], handles.f);

juiFunHandle = handle(handles.jPanel, 'CallbackProperties');
set(juiFunHandle, 'MousePressedCallback', ...
   @(src, evnt)CellSelectionCallback(src, evnt, handles));
set(juiFunHandle, 'KeyPressedCallback', ...
   @(src, evnt)CellSelectionCallback(src, evnt, handles));

% store gui handles in application data
guidata(handles.f , handles)
end

function EditBoxFcn(hobj,~)
    handles = guidata(hobj) ;
    ActiveTextBox = get(hobj,'Tag') ;
    setappdata( handles.f , 'activeTextBox', handles.(ActiveTextBox) ) ;
end

function CellSelectionCallback(~, ~, handles)

    % retrieve the handle of the active text box
    ActiveTextBox = getappdata(handles.f,'activeTextBox') ;

    % assign a default active text box if none was selected before
    if isempty(ActiveTextBox) ; ActiveTextBox = handles.ledit ; end

    numRetry = 10 ;
    for k=1:numRetry
        pause(0.1)
        dateString = char( javaMethodEDT('getSelectedDate', handles.jPanel) ) ;
        if ~isempty(dateString) ; break ; end
    end

    set(ActiveTextBox , 'String' , dateString ) ;
end

查看实际操作:


编辑

没有纯 Matlab 方法可以让您的 Matlab 编辑框完全可编辑一个响应(触发事件)对任何鼠标按钮的单击。
您可以通过使用 java 对象底层的文本框来获得此功能。这个 java 对象暴露了很多事件,你可以选择你需要的。

问题:
要获取底层 java 对象的句柄,您需要使用 Yair Altman 提供的全能 findjobj 实用程序。您可以从此处的文件交换处下载最新版本:findjobj

一旦你将它保存在你的 Matlab 路径中,只需将上面示例中定义编辑框的几行代码替换为:

commonEditProperties = {'Style', 'edit', 'String', '', 'Units', 'Normalized', 'Enable','on' } ;

handles.ledit = uicontrol( commonEditProperties{:}, 'Position', [0.1 0.1 0.3 0.1] );
handles.redit = uicontrol( commonEditProperties{:}, 'Position', [0.5 0.1 0.3 0.1] );
% preallocate a variable to hold the active text box handle
setappdata(handles.f,'activeTextBox',[]) ;

% Find the java underlying object for the text boxes
ledit = findjobj(handles.ledit) ;
redit = findjobj(handles.redit) ;
% assign a callback to the java object (which CAN detect single click)
set(ledit,'MouseClickedCallback',@(h,e) setappdata( handles.f , 'activeTextBox', handles.ledit ) ) ;
set(redit,'MouseClickedCallback',@(h,e) setappdata( handles.f , 'activeTextBox', handles.redit ) ) ;

并且您可以完全注释或删除子函数EditBoxFcn,因为回调动作是直接完成的。

【讨论】:

  • 霍基,非常感谢。我决定使用“非活动”模式,因为让用户手动更改一些数据 - 是一种不好的方式。但它仍然很有趣 - 是否可以为“开”模式做?它有效,但有 1 个问题 - 它需要编辑框中的数据必须更改!如果我在不更改数据的情况下放置光标,则程序会继续将数据放入最后一个 CHANGED 编辑框!
  • @Mikhail_Sam。我知道,inactive 模式是唯一可以在文本框中单击一次即可触发纯 Matlab 回调的模式(无需对内容进行任何修改)。如果您希望文本框可编辑并且对单击作出反应,则必须使用由底层 java 对象的文本框触发的事件(因此它会更 undocumented 代码)。我将编辑答案以添加它。
  • 谢谢!顺便说一句:你为​​什么使用setappdata/loadappdata?我可以使用handles.ActiveTextBox 吗?
  • 是的,您可以使用handles 结构来存储您的“最后一个活动”文本框句柄。只是选择问题。通常,我使用handles 结构仅存储我的GUI 组件的句柄,我使用appdata 存储我需要保存的任何其他内容。底线,两种方式都可以工作(甚至存在一些其他方式)。阅读文档文章以了解每种方法的优缺点:Passing Data Around your User Interface
猜你喜欢
  • 2012-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-24
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多