2

我正在开发一个大型 GUI,其基本结构非常基本,可以简单地简化为两个相互关联的控件(每个控件都更新另一个控件的值):一个滑块和一个编辑框。他们分享的价值被用来制作一个情节。如果您运行以下代码,您会发现您只能更改一次值(通过移动幻灯片或编辑框)。第二次,它会抛出一个错误。主要问题是:为什么?应该如何使用 GUIHANDLES 代替?

function GuiHandleShare1

handles.figure=figure;

handles.edit=uicontrol('Style','Edit',...
                       'Position',[5  5 50 20],...
                       'Callback',@edit_callback,...
                       'Tag','edit');
handles.slider=uicontrol('Style','Slider',...
                         'Position',[55 5 500 20],...
                         'Callback',@slider_callback,...
                         'Tag','slider');
handles.axes=axes('OuterPosition',[0.1 0.1 0.8 0.8],...
                  'Tag','axes');

function plotter
handles=guihandles;
plot(handles.axes,[0 1],[0 str2num(get(handles.edit,'String'))])

function edit_callback(h,eventdata)
handles=guihandles;
set(handles.slider,'Value',str2num(get(handles.edit,'String')));
plotter

function slider_callback(h,eventdata)
handles=guihandles;
set(handles.edit,'string',num2str(get(handles.slider,'Value')));
plotter

我试图通过挖掘guihandles的代码来找到答案,但就像guidata一样,它是getappdata、setappdata等的包装器,其来源不可用(Matlab R2008b)。

我已经知道此类 GUI 的其他解决方案: 1- 我不使用 guihandles、guidata 或其他此类,而是使用全局变量。2-使用嵌套函数。

在我正在处理的情况下,嵌套函数不是一个选项,因为这会使主函数工作区成为静态工作区。这不是我想要的,因为我必须在应用程序中管理变量。我最终使用了全局变量:我在每个需要它们的函数中将句柄声明为全局变量,并且它工作正常。这有什么缺点吗?我的意思是,如果我们可以使用全局变量,为什么 Matlab 会提出 guihandles、guidata 等命令?

4

2 回答 2

3

您必须使用此属性/值对:

'NextPlot' ,'ReplaceChildren'

在一开始就定义轴,否则 GUI 在第一个绘图之后创建一个新图形,并且与开头的轴关联的标签不再有效。实际上,如果您键入

get(handles.axes)

创建它后,您会看到此属性设置为“替换”,即替换整个轴而不是其子轴。因此,代码将如下所示:

handles.axes=axes('OuterPosition',[0.1 0.1 0.8 0.8],...
                  'Tag','axes','NextPlot' ,'ReplaceChildren');

作为全局变量的解决方法,您还可以使用 findobj 来检测轴,然后在其中绘图:

function plotter

hAx = findobj('Type','axes')
handles=guihandles;
plot([0 1],[0 str2num(get(handles.edit,'String'))],'parent',hAx);

但是如果您有多个轴,则不是很方便。

据我所知,GUI 中的全局变量使代码更易于实现,但是我知道的一个警告是,如果您计划从 GUI 部署独立应用程序,它将在编译期间抛出大量错误,您将不得不摆脱他们。

无论如何,使用上面的代码对我来说很好。希望有帮助!

于 2014-09-29T19:51:58.423 回答
3

我想你误解了函数 guihandles(),它给你一个图中真实句柄的列表,和 guidata() 不一样。事实上,尝试将您的handles.axes 重命名为handles.axes1,您会看到它在第一次回调时失败。

此代码使用 guidata() 来保存和检索数据(行末注释)。

function GuiHandleShare1

handles.figure=figure;

handles.edit=uicontrol('Style','Edit',...
                       'Position',[5  5 50 20],...
                       'Callback',@edit_callback,...
                       'Tag','edit');
handles.slider=uicontrol('Style','Slider',...
                         'Position',[55 5 500 20],...
                         'Callback',@slider_callback,...
                         'Tag','slider');
handles.axes1=axes('OuterPosition',[0.1 0.1 0.8 0.8],...
                  'Tag','axes');
guidata(handles.figure, handles); % save handles to GUIDATA

function plotter
handles=guidata(gcf); % retrieve handles from GUIDATA
plot(handles.axes1,[0 1],[0 str2num(get(handles.edit,'String'))])

function edit_callback(h,eventdata)
handles=guidata(gcf);
set(handles.slider,'Value',str2num(get(handles.edit,'String')));
plotter

function slider_callback(h,eventdata)
handles=guidata(gcf);
set(handles.edit,'string',num2str(get(handles.slider,'Value')));
plotter
于 2014-09-29T20:24:25.840 回答