2016-07-13 36 views
1

Ich baue eine GUI in Matlab, mit the programmatic approach (also ohne GUIDE und ohne AppDesigner). Meine GUI enthält ein Eingabefeld, das nur bestimmte Eingaben akzeptieren soll. Daher verwende ich einen Rückruf, der die Eingabe bereinigt und dann die String-Eigenschaft des Bearbeitungsfelds entsprechend aktualisiert. Wenn ich jedoch die String-Eigenschaft aktualisiere, bleibt der Cursor (der "Cursor") hängen: Er hört auf zu blinken, und obwohl du ihn immer noch nach links und rechts bewegen kannst, bleibt eine Geisterkopie am linken Rand der Eingabe gemalt.Caret hängt bei der Einstellung String-Eigenschaft von "bearbeiten" Feld

Mindestarbeits Beispiel unter Verwendung von Zufallszahlen:

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

Ergebnis (auf Win7, mit Matlab2016a oder Matlab2014b):

enter image description here

Wie kann ich die Zeichenfolge in dem Feld wihtout die Aktualisierung Caret werden g stecken?

+0

dass seltsam ich dieses Problem nicht auf R2013a begegne –

Antwort

0

ich eine Abhilfe gefunden: In der Callback, können Sie zunächst den Fokus auf ein Dummy-Element wechseln, aktualisieren Sie dann das Element-of-Interest, und Schalte schließlich den Fokus zurück auf das Element von Interesse. Nachteil dieser Lösung: Der Text ist in seiner Gesamtheit hervorgehoben. Außerdem ist die Lösung etwas fragil: Aus nicht naheliegenden Gründen muss die Sichtbarkeit des Dummy-Elements in einem separaten set-Aufruf auf "aus" gesetzt werden.

Da der neue Rückruf mehrere Zeilen umfasst, kann er nicht mehr als anonyme Funktion angegeben werden. Dies macht die minimale Beispiel etwas länger:

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 

Ergebnis:

enter image description here

Nachtrag

Sie können die Position des Cursors ändern, indem die zugrunde liegenden Java Swing-Objekt zu manipulieren. Mit Yair Altman's excellentfindjobj Funktion wird der Code:

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 

Sie könnten (und vielleicht sollten) in zusätzlichen Code zu überprüfen, ob der caret Index nicht illegal ist, wenn die Länge der Zeichenfolge ändert. Aber für dieses minimal Beispiel sieht das Ergebnis schon recht nett:

enter image description here

0

Versuchen Sie set zu verwenden, um den Wert zu aktualisieren, und dann drawnow, um das Aktualisieren der uicontrol zu erzwingen.

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

wo h ist der Griff zu Ihrem uicontrol

+0

Ist das nicht genau das, was mein Rückruf tut? Ich weiß, dass ich es außerhalb des Callbacks machen könnte, aber das wäre ziemlich sinnlos, da mein Ziel darin besteht, die Benutzereingaben zu bereinigen. –

+0

Versuchen Sie auch, 'drawnow' zu verwenden, um die Aktualisierung der uicontrol zu erzwingen –

+0

Leider hilft' drawnnow' nicht. –