设置 "edit" 字段的字符串 属性 时插入符卡住

Caret stuck when setting String property of "edit" field

我正在使用 the programmatic approach 在 Matlab 中构建一个 GUI(所以没有 GUIDE 也没有 AppDesigner)。 我的 GUI 包括一个只接受特定输入的编辑字段。因此,我正在使用一个回调来清理输入,然后相应地更新编辑字段的字符串 属性。但是,当我更新字符串 属性 时,插入符号(“光标”)卡住了:它停止闪烁,虽然您​​仍然可以左右移动它,但它的幻影副本将留在左边缘输入的。

最小工作示例,使用随机数:

figure;
edit_cb = @(h, e) set(h, 'String', num2str(rand(1)));
uicontrol('Style', 'edit', 'String', '0', 'Callback', edit_cb);

结果(在 Win7 上,使用 Matlab2016a 或 Matlab2014b):

如何在插入符号卡住的情况下更新字段内的字符串?

尝试使用set更新值然后drawnow强制刷新uicontrol。

set(h, 'String', StrValue);
drawnow;

其中 h 是您的 uicontrol

的句柄

我找到了解决方法:在回调中,您可以先将焦点切换到虚拟元素,然后更新感兴趣的元素,最后将焦点切换回感兴趣的元素。此解决方案的缺点:文本整体突出显示。此外,该解决方案有些脆弱:出于不明显的原因,必须在单独的 set 调用中将虚拟元素的可见性设置为 'off'。

由于新回调跨越多行,因此不能再声明为匿名函数。这使得最小示例稍长:

function caret_stuck_hack()

figure
hedit = uicontrol('Style', 'edit', 'String', '0', 'Callback', @edit_cb);
hdummy = uicontrol('Style', 'edit', 'String', 'dummy', ...
    'Position', [0, 0, 1, 1]); % Position: HAS to be non-overlapping with other edit field
hdummy.Visible = 'off'; % Don't merge with upper line! HAS to be called seperately! 

function edit_cb(h, e)
    uicontrol(hdummy);
    h.String = num2str(rand(1));
    uicontrol(h);
    drawnow;
end

end

结果:

附录

您可以通过操纵底层 Java Swing 对象来更改插入符号的位置。使用Yair Altman's excellentfindjobj函数,代码变为:

function caret_stuck_hack()

figure
hedit = uicontrol('Style', 'edit', 'String', '0', 'Callback', @edit_cb);
hdummy = uicontrol('Style', 'edit', 'String', 'dummy', ...
    'Position', [0, 0, 1, 1]); % Position: HAS to be non-overlapping with other edit field
hdummy.Visible = 'off'; % Don't merge with upper line! HAS to be called seperately! 

jhedit = findjobj(hedit, 'nomenu');

function edit_cb(h, e)
    caret_pos = get(jhedit, 'CaretPosition');
    uicontrol(hdummy);
    h.String = num2str(rand(1));
    uicontrol(h);
    drawnow;
    set(jhedit, 'CaretPosition', caret_pos)
end

end

您可以(也许应该)添加额外的代码来检查字符串长度更改时插入符号索引是否非法。但是对于这个最小的例子,结果看起来已经很不错了: