Сбой сохранения графического интерфейса MATLAB 2013a в обратном вызове флажка

Я делаю графический интерфейс, который считывает данные с измерительной платы через последовательный интерфейс. Он состоит из 8 каналов, и я хочу иметь возможность включать и отключать каналы на графике рисунка, но состояние моей переменной handles.channelsEnable не сохраняется.

При открытии графического интерфейса: handles.channelEnable = [0;0;1;1;0;0;0;0]; Во время работы с графическим интерфейсом я хочу изменить handles.channelEnable. Внутри функции обратного вызова флажка он изменяется, но не вне функции. Я использую guidata(hObject,handles) для сохранения сделанных изменений. Почему не сохраняются изменения, внесенные в handles.channelEnable?

    % --- Executes on button press in checkbox2.
    function checkbox2_Callback(hObject, eventdata, handles)
    % hObject    handle to checkbox2 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)

    % Hint: get(hObject,'Value') returns toggle state of checkbox2
        handles.channelEnable(2) = get(hObject,'Value');
        guidata(hObject, handles);
    end

person cor55555    schedule 30.07.2014    source источник


Ответы (3)


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

person YisasL    schedule 30.07.2014
comment
Я не думаю, что полностью понимаю тебя. Вы имеете в виду, что мне нужно добавить guidata (hObject), чтобы получить дескрипторы? Итак, код выглядит так: % --- Выполняется при нажатии кнопки в checkbox2. функция checkbox2_Callback(hObject, eventdata, handles) обрабатывает guidata(hObject); обрабатывает handles.channelEnable(2) = get(hObject,'Value'); guidata(hObject,дескрипторы); конец Это не имеет никакого значения с или без. В обоих случаях известны все дескрипторы (также ChannelEnable)l - person cor55555; 31.07.2014
comment
Я имею в виду, что при вызове обратного вызова вы получите handles в качестве входной переменной, но она не будет содержать полный список хэндлов. Если вы хотите иметь их все (которые вы также включали ранее с помощью guihandles(hObject, handles)), вам нужно снова вызвать guihandles внутри обратного вызова, чтобы получить ВСЕ. Это теперь ясно? :) - person YisasL; 31.07.2014
comment
Я все еще не понимаю. Это не имеет значения, я думаю, что я все еще делаю что-то не так. Не могли бы вы написать код, который я должен поместить в обратный вызов флажка (буквально)? Когда я просматриваю документацию MATLAB, там говорится, что если вы используете GUIDE, вам не нужно вызывать guihandles для создания структуры, потому что GUIDE генерирует структуру дескрипторов, содержащую дескрипторы GUI. Вы можете добавить в него свои данные. См. ссылку. - person cor55555; 31.07.2014
comment
Но вы включили новый элемент управления в handles вручную. Чтобы получить полный список дескрипторов, просто введите 'handles = guihandles;' после 'function checkbox2_Callback(hObject, eventdata, handles)' (то есть первая строка после вызова обратного вызова флажка). Если у вас все еще есть проблемы, см. также ответ @excaza. - person YisasL; 31.07.2014
comment
Оно работает! Большое спасибо! Теперь я понимаю. В начале КАЖДОЙ функции или обратного вызова (не только обратного вызова флажка) вы должны загрузить структуру дескрипторов с помощью «handles = guidata (hObject);» и в конце КАЖДОЙ функции или обратного вызова вы должны сохранить структуру дескрипторов с помощью «guidata (hObject, handles);». Моя вина была в том, что я не загрузил снова структуру дескрипторов в функции, где я использовал channelEnable. - person cor55555; 31.07.2014

Ответ @YisasL правильный, но я хотел немного его уточнить.

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

function testcode
handles.mainwindow = figure();

handles.button1 = uicontrol( ...
    'Style','pushbutton', ...
    'Units','normalized', ...
    'Position',[0.05 0.05 .30 .90], ...
    'String','Button1', ...
    'Callback',{@button1,handles} ...
    );
handles.button2 = uicontrol( ...
    'Style','pushbutton', ...
    'Units','normalized', ...
    'Position',[0.35 0.05 .30 .90], ...
    'String','Button2', ...
    'Callback',{@button2,handles} ...
    );
handles.button3 = uicontrol( ...
    'Style','pushbutton', ...
    'Units','normalized', ...
    'Position',[0.65 0.05 .30 .90], ...
    'String','Button3', ...
    'Callback',{@button3,handles} ...
    );
end

function button1(~,~,handles)
fieldnames(handles)
end

function button2(~,~,handles)
fieldnames(handles)
end

function button3(~,~,handles)
fieldnames(handles)
end

Нажмите каждую кнопку и посмотрите на отображаемый результат fieldnames. Вы заметите, что у кнопки 1 есть только mainwindow, у кнопки 2 есть mainwindow и button1, а у кнопки 3 есть mainwindow, button1 и button2. Как вы уже заметили, независимо от того, какие изменения вы вносите где-то еще в своем коде, этот результат останется постоянным.

Это интересная особенность, которую я заметил, когда перешел на программные графические интерфейсы вместо использования GUIDE. Обычно вы этого не замечаете, используя GUIDE GUI, потому что вся инициализация выполняется в фоновом режиме, и пользователи не склонны изменять структуру дескрипторов. С программным графическим интерфейсом вам нужно помнить о порядке, в котором вы определяете свои обратные вызовы (определяйте их после того, как ваша структура дескрипторов построена).

Альтернативой является использование guidata, как сказал @YisasL. Тогда вам не нужно беспокоиться о передаче переменных в ваши обратные вызовы.

person excaza    schedule 30.07.2014

Я не думаю, что полностью понимаю тебя.

Вы имеете в виду, что мне нужно добавить guidata (hObject), чтобы получить дескрипторы? Итак, код выглядит так:

% --- Executes on button press in checkbox2.
function checkbox2_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox2
    handles
    guidata(hObject);
    handles
    handles.channelEnable(2) = get(hObject,'Value');
    guidata(hObject, handles);
end

Нет никакой разницы с ним или без него. В обоих случаях известны все дескрипторы (также channelEnable).

person cor55555    schedule 31.07.2014