2016-08-05 1 views
1

У меня проблема с моим графическим интерфейсом MATLAB.MATLAB GUI: как обновлять дескрипторы при создании новых объектов в подфункции?

Я не использую GUIDE, поэтому я сам кодирую все для своего графического интерфейса. У меня есть Main, который генерирует первую панель GUIDE. Эта панель содержит кнопку, которая может создавать другие 2 панели через связанную функцию обратного вызова. В остальных 2 панелях можно выполнять другие операции, вызывающие другие функции обратного вызова. Одной из этих операций является создание 2 новых статических текстов и 2 новых редактируемых текстов. У меня проблемы с обновлением ручек, связанных с этими редактируемыми текстами. Точнее, я не могу получить значение своей строки после редактирования текста и снова вызвать функции обратного вызова последних двух панелей.

прилагается код, где все функции обратного вызова графического интерфейса являются:

%% server_selected callback function 
function server_selected(hObject, eventdata, handles) 
%UNTITLED8 Summary of this function goes here 
% Detailed explanation goes here 

% Get server version and run LaunchCDbQuery 
servers = get(handles.server_popup, 'String'); 
serverVersion = servers{get(handles.server_popup, 'Value')}; 
[Day] = LaunchCDbQuery(serverVersion); 
assignin('base', 'Day', Day) 

% Update current outing on GUI 
set(handles.outing_text, 'String', strcat(Day.date, Day.DocumentKey)) 

% Tool description 
% Create panel for the tool description 
handles.description_panel = uipanel('Title', 'Tool description',... 
    'units', 'normalized',... 
    'position', [0.675, 0.025, 0.3, 0.9]); 
% Create items inside the panel for the tool description 
% Function heading 
handles.funheading_text = uicontrol('Parent', handles.description_panel,... 
    'Style', 'text',... 
    'units', 'normalized',... 
    'position', [0, 0.7, 1, 0.2],... 
    'String', 'Please choose a tool and click description to obtain the tool''s heading and description.',... 
    'HorizontalAlignment', 'left'); 
% Function description 
handles.description_text = uicontrol('Parent', handles.description_panel,... 
    'Style', 'text',... 
    'units', 'normalized',... 
    'position', [0, 0.05, 1, 0.6],... 
    'HorizontalAlignment', 'left'); 

% Tool selection 
% Create panel for the tool selection 
handles.tool_panel = uipanel('Title', 'Tool selection',... 
    'units', 'normalized',... 
    'position', [0.35 0.025 0.3 0.9]); 
% Create items inside the panel for the tool selection 
% Text 
handles.tool_text = uicontrol('Parent', handles.tool_panel,... 
    'Style', 'text',... 
    'units', 'normalized',... 
    'position', [0 0.7 1 0.2],... 
    'String', 'Please choose a tool to perform a piece of analysis.',... 
    'HorizontalAlignment', 'left'); 
% Popup 
handles.tool_popup = uicontrol('Parent', handles.tool_panel,... 
    'Style', 'popup',... 
    'units', 'normalized',... 
    'position', [0.2 0.25 0.6 0.4],... 
    'String', {'plotmaptg'; 'TestReview'});  
% Input variables panel 
handles.varin_panel = uipanel('Parent', handles.tool_panel,... 
    'Title', 'Type input variables',... 
    'units', 'normalized',... 
    'position', [0, 0, 1, 0.3]); 
% Description push 
handles.tool_push_description = uicontrol('Parent', handles.tool_panel,... 
    'Style', 'pushbutton',... 
    'units', 'normalized',... 
    'position', [0.05 0.4 0.4 0.1],... 
    'String', 'Description',... 
    'callback', {@tool_description, handles}); 
% Ok push 
handles.tool_push_ok = uicontrol('Parent', handles.tool_panel,... 
    'Style', 'pushbutton',... 
    'units', 'normalized',... 
    'position', [0.51 0.4 0.4 0.1],... 
    'String', 'Ok',... 
    'callback', {@tool_selected, handles, Day}); 

% Update guidata 
guidata(hObject, handles) 
end 

%% tool_description callback function 
function tool_description(hObject, eventdata, handles) 
%UNTITLED2 Summary of this function goes here 
% Detailed explanation goes here 

% Call handles function 
handles = tool_description_handles(handles); 

% Update guidata 
guidata(hObject, handles) 
end 

function newHandles = tool_description_handles(handles) 
%UNTITLED Summary of this function goes here 
% Detailed explanation goes here 

% Get tool name 
tools = get(handles.tool_popup, 'String'); 
tool_selected = tools{get(handles.tool_popup, 'Value')}; 

% Open tool .m file 
fid = fopen(strcat(tool_selected, '.m'), 'r'); 

% Read .m file to find function description and save it 
line = fgets(fid); 
heading = line; 
while isempty(regexp(line, '%', 'ONCE')) 
    line = fgets(fid); 
end 
description = []; 
while ~isempty(regexp(line, '%', 'ONCE')) 
    description = strcat(description, line(regexp(line, '%', 'ONCE'):end)); 
    line = fgets(fid); 
end 
description(regexp(description, '%')) = []; 
fclose(fid); 

% Set descritption found to the description handle 
set(handles.funheading_text, 'String', heading); 
set(handles.description_text, 'String', description); 

% Find the input variables needed to run the tool 
global inputs varout 
[varin, varout] = get_arg_names(strcat(pwd, '\Tools\', tool_selected, '.m')); 
inputs = cell(1, length(varin{1,1})); 
for i = 1:length(varin{1,1}) 
    % Input variable text 
    handles.varin_text(i) = uicontrol('Parent', handles.varin_panel,... 
     'Style', 'text',... 
     'units', 'normalized',... 
     'position', [0, 1-i*(1/length(varin{1,1})), 0.45, 1/length(varin{1,1})],... 
     'String', varin{1,1}{i,1},... 
     'HorizontalAlignment', 'left'); 
    % Input variables editable text 
    handles.varin_edit(i) = uicontrol('Parent', handles.varin_panel,... 
     'Style', 'edit',... 
     'units', 'normalized',... 
     'position', [0.55, 1-i*(1/length(varin{1,1})), 1, 1/length(varin{1,1})],... 
     'HorizontalAlignment', 'left',... 
     'callback', {@varin_callback, handles}); 
end 

% Save handles 
newHandles = handles; 
end 

function varin_callback(hObject, eventdata, handles) 
% hObject handle to edit1 (see GCBO) 
% eventdata reserved - to be defined in a future version of MATLAB 
% handles structure with handles and user data (see GUIDATA) 

% Save in the main workspace the input variables 
global inputs 
for i = 1:length(inputs) 
    if isempty(inputs{1,i}) 
     inputs{1,i} = get(hObject,'String'); 
     break 
    end 
end 
end 


%% tool_selected callback function 
function tool_selected(hObject, eventdata, handles, Day) 
%UNTITLED Summary of this function goes here 
% Detailed explanation goes here 

% Get tool name 
tools = get(handles.tool_popup, 'String'); 
tool = tools{get(handles.tool_popup, 'Value')}; 
% fh = str2func(tool); 

% Get tool inputs and outputs 
global inputs varout 

% Run the tool 
if ~isempty(varout) 
    expression = strcat('out = ', tool, '('); 
else 
    expression = strcat(tool, '('); 
end 
for i = 1:length(inputs) 
    if ~isempty(inputs{1,i}) 
     expression = strcat(expression, inputs{1,i}, ','); 
    else 
     break 
    end 
end 
expression(end) = ')'; 
eval(expression) 

% Update guidata 
guidata(hObject, handles) 
end 

Я попытался с помощью guidata(hObject, handles) в конце каждой функции, но это не сработало. Поскольку теперь я использую глобальные переменные, чтобы избежать проблемы, но мне бы очень хотелось просто обновить дескрипторы по мере их изменения.

+2

Вы также должны использовать 'guidata' в начале обратного вызова, чтобы получить структуру' handles'. Передача 'handles' каждому обратному вызову будет проходить только' handles', как он существовал в момент, когда вы определили обратный вызов. – excaza

+0

, так как excaza сказал, что если вы используете 'guidata', вам нужно получить структуру' handles' 'handles = guidata (hobj)' в начале каждого обратного вызова, который в ней нуждается. Таким образом, вы всегда извлекаете «свежие» 'дескрипторы', и если вы это сделаете, вы можете полностью удалить« дескрипторы »из списка входных параметров обратных вызовов. – Hoki

+0

Теперь ясно, спасибо вам, ребята, за ваши комментарии. – Francesco

ответ

0

При предоставлении входной переменной функции обратного вызова переменная, которая передается при вызове обратного вызова, является той переменной, которая существует, когда она определена. MATLAB не знает, как обновлять эти входы при изменении guidata.

Вы можете увидеть это на следующем примере:

function testcode 
h.mf = figure('Menubar', 'none', 'NumberTitle', 'off', 'ToolBar', 'none'); 

h.lb = uicontrol('Parent', h.mf, 'Style', 'Listbox', ... 
       'Units', 'Normalized', 'Position', [0.1 0.5 0.4 0.4] ... 
       ); 

h.b1 = uicontrol('Parent', h.mf, 'Style', 'pushbutton', ... 
       'Units', 'Normalized', 'Position', [0.1 0.1 0.4 0.3], ... 
       'String', 'Pass handles','Callback', {@button1push, h}); 

h.b2 = uicontrol('Parent', h.mf, 'Style', 'pushbutton', ... 
       'Units', 'Normalized', 'Position', [0.5 0.1 0.4 0.3], ... 
       'String', 'Use GUIdata', 'Callback', @button2push); 

guidata(h.mf, h); 
makepanel(h.mf); 
end 

function makepanel(mf) 
h = guidata(mf); 
h.panel = uipanel('Parent', h.mf, 'Title', 'A Panel', ... 
        'Units', 'Normalized', 'Position', [0.5 0.5 0.4 0.4] ... 
       ); 
guidata(h.mf, h); 
end 

function button1push(~, ~, h) 
h.lb.String = fieldnames(h); 
end 

function button2push(hObj, ~) 
h = guidata(hObj); 
h.lb.String = fieldnames(h); 
end 

Вдавите каждую кнопку и посмотрите на результат в ListBox. Вы можете видеть, что изменение h сделанных в makepanel не отображаются, когда вы нажмете кнопку 1.

Вместо прохождения handles как вход обратного вызова (например, кнопка 1 выше), называют guidata с выходом в начале вашей функции для получения самой последней версии handles. Если ваш обратный вызов вносит изменения в структуру дескрипторов, снова вызовите guidata, чтобы сохранить эти изменения для других обратных вызовов.

+0

Теперь он работает, и я понял различия в использовании ручек в качестве ввода функции и с помощью guidata. Благодаря! – Francesco