开发者

Updating listbox and variable changing to old value at the end of the function in MATLAB GUI

The below GUI simply lists some data in a listbox, plots it, and gives the user the option to delete entries from the listbox. I'm hitting my head against the wall trying to get to listbox updated correctly after the user deletes an entry (it should be obvious when you run it).

The 2 problems I have are:

  1. While the callback to the pushbutton does indeed delete the entry correctly from array x, once the callback finishes, the array x reverts back to the original x array (thus, t开发者_开发百科he value somehow restores itself).

  2. I try to use "drawnow" to refresh the listbox to reflect the current x array (which has been modified, at least where drawnow is issued below). Nothing changes though. How can I refresh the listbox with the new x array values?

----------------GUI code---------

function testgui
clear; close all;
% Create the data
x = (10:20)'; % example data

% Create a figure
f = figure('Name', 'GUI Test',...
  'NumberTitle', 'off',...
  'MenuBar', 'none',...
  'Units', 'pixels',...
  'Position', [100 100 700 800],...
  'Visible', 'off');

% Create a set of axes
a = axes('Parent', f,...
  'Units', 'pixels',...
  'Position', [230 50 450 700]);

% Create a pushbutton for modifying x array
pb_x = uicontrol('Style', 'pushbutton', ...
  'Parent', f,...
  'String', 'Delete Selection',...
  'Units', 'pixels',...
  'Position', [50 7 100 35],...
  'Callback', @pb_change_x);

plot(x,'bo'); % graph
xlabel('Index Number'); ylabel('Variable x');

% Create a listbox to hold the x values
y=strtrim(cellstr(num2str(x)));
lb = uicontrol('Style', 'listbox',...
  'Parent', f,...
  'String', y,...
  'Units', 'pixels',...
  'Position', [50 50 100 700],...
  'Callback', @list_change);

set(f,'Visible','on')


function list_change(varargin)
    % Runs when the selection in listbox is changed
    curIdx = get(lb,'Value');
    % Index the value
    curVal = str2double(cell2mat(y(curIdx)));

    % Get position of curVal in x
    posVal = find(ismember(x,curVal));

    % Clear all the children currently on the axes
    delete(get(a,'Children'))

    % Plot the one data point of interest
    plot(posVal,curVal,'bo','MarkerFaceColor','b','MarkerSize',10)
    xlabel('Index Number'); ylabel('Variable x');
    % Plot all the data
    hold on
    plot(x,'bo')
    hold off
end

function pb_change_x(varargin)
    % Runs when DUT <<< pushbutton is clicked
    % Obtain selected index
    curIdx = get(lb,'Value');
    % Index the value
    curVal = str2double(cell2mat(y(curIdx)));

    % Get position of curVal in x
    posVal = ismember(x,curVal);
x(posVal) = []; % HELP (why doesn't value stick when this function returns?)

    % Redraw figure (want listbox to update)
drawnow; % HELP (how to refresh listbox with current x array?)

    % Clear all the children currently on the axes
    delete(get(a,'Children'))

    % Plot all the data
    plot(x,'bo'); xlabel('Index Number'); ylabel('Variable x');
end

end 


You have correctly identified the fix. More generally, I would say that you need to separately update each of the items that encode your GUI's state (i.e. each of the items stored independently by the GUI).

Specifically, your implementation separately stores to the GUI both 'x', your array of data, in the plot and 'y', the cell array that has strings for the listbox names for each item in 'x'. When you created your listbox, 'lb', you provided 'y' as the 'String' attribute. At that point the listbox is separately storing its own copy of 'y' independent of your 'y' and 'x' variables.

When you update your plot, you are resetting the GUI's value of 'x', but as you discovered you also need to update the listbox's 'String' attribute (its copy of 'y'). In this case, the way you chose seems most straightforward, but a more general approach is to repeat the steps used to generate 'y' from 'x' (after updating 'x') and then use "set(lb, 'String', y);" to reset the GUI's version of 'y'.

Hope that is helpful! :-)


It seems that you already fixed the problem. Nonetheless, I rewrote your example and tried to simplify it a bit:

function testgui2()
    data = [1:11 ; 10:20]';          %'# data
    handles = [];

    %# create GUI
    handles.hFig = figure('Name','GUI Test', 'NumberTitle','off', ...
        'Units','pixels', 'Position',[100 100 700 800], ...
        'MenuBar','none', 'Visible','off');
    handles.hAx = axes('Parent',handles.hFig, ...
        'Units','pixels', 'Position',[230 50 450 700]);
    handles.hPB = uicontrol('Style','pushbutton', 'Parent',handles.hFig, ...
        'String','Delete Selection',...
        'Units','pixels', 'Position',[50 7 100 35],...
        'Callback',@button_callback);
    handles.hLB = uicontrol('Style','listbox', 'Parent',handles.hFig, ...
        'String',data(:,2), 'Value',1, ...
        'Units','pixels', 'Position',[50 50 100 700], ...
        'Callback',@listbox_callback);
    set(handles.hFig, 'Visible','on')

    %# plot data and highlighted point
    handles.hPlot = plot(data(:,1), data(:,2), 'bo');
    handles.hLine = line('XData',data(1,1), 'YData',data(1,2), ...
        'Marker','o', 'MarkerSize',10, 'Color','b', 'MarkerFaceColor','b');
    xlabel('Index Number'), ylabel('Variable x')
    set(handles.hAx, 'XLimMode','manual', 'YLimMode','manual')    %# fix limits

    %# callback function for button
    function button_callback(varargin)
        %# get current selection
        selected = get(handles.hLB, 'Value');
        if selected==0, return, end

        %# remove data point
        data(selected,:) = [];

        %# update the listbox
        set(handles.hLB, 'String',data(:,2))
        set(handles.hLB, 'Value',min(selected,size(data,1)))
        %# update plot
        set(handles.hPlot, 'XData',data(:,1), 'YData',data(:,2))
        listbox_callback()
    end

    %# callback function for listbox
    function listbox_callback(varargin)
        %# get current selection
        selected = get(handles.hLB, 'Value');
        if selected==0, selected = []; end

        %# update plot (highlighted point)
        set(handles.hLine, 'XData',data(selected,1), 'YData',data(selected,2))
    end

end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜