由Matlab GUI给出的致命错误

3

编辑的文章

这些是我使用你的模板创建的新函数,以帮助我解决问题。

代码本身没问题,但“检查光标”的框没有覆盖在坐标轴上。实际上它们离得很远。我使用了一次set(hAx, 'Units','pixels')和一次注释掉它的disp(axPos)。结果显示为:

1.

 169.0000   71.0000  126.0000   51.0000
 94.0000  122.0000  126.0000   51.0000
 19.0000   71.0000  126.0000   51.0000
 94.0000   20.0000  126.0000   51.0000

这是轴的GUIDE坐标,而不是正在显示的“Currentpoint”坐标。

2.

33.6000    5.3846   25.2000    3.9231
18.6000    9.3077   25.2000    3.9231
3.6000    5.3846   25.2000    3.9231
18.6000    1.4615   25.2000    3.9231

我不知道这些来自哪里,但它们更接近需要的位置,但是向左偏移了约60个像素。

以下是代码:

function HVACSM_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to HVACSM (see VARARGIN)

% Choose default command line output for HVACSM
handles.output = hObject;
NUM = 4;

imgOff1 = imread('cond.png');
imgOn1 = imread('condH.png');

imgOff2 = imread('comp.png');
imgOn2 = imread('compH.png');

imgOff3 = imread('evap.png');
imgOn3 = imread('evapH.png');

imgOff4 = imread('exp.png');
imgOn4 = imread('expH.png');

imgOff = cell(1,NUM);
imgOff{1} = imgOff1;
imgOff{2} = imgOff2;
imgOff{3} = imgOff3;
imgOff{4} = imgOff4;

imgOn = cell(1,NUM);
imgOn{1} = imgOn1;
imgOn{2} = imgOn2;
imgOn{3} = imgOn3;
imgOn{4} = imgOn4;

%# setup axes
hAx = zeros(1,NUM);
hImg = zeros(1,NUM);
hAx = [handles.axes1 handles.axes2 handles.axes3 handles.axes4];
hImg(1) = imagesc(imgOff{1}, 'Parent',hAx(1));
hImg(2) = imagesc(imgOff{2}, 'Parent',hAx(2));
hImg(3) = imagesc(imgOff{3}, 'Parent',hAx(3));
hImg(4) = imagesc(imgOff{4}, 'Parent',hAx(4));
set(hAx, 'XTick',[], 'YTick',[],'Box', 'on')

%# get corner-points of each axis
set(hAx, 'Units','pixels')
axPos = cell2mat( get(hAx,'Position') );
disp(axPos)
p = zeros(5,2,NUM);
for k=1:NUM
    p(:,:,k) = bsxfun(@plus, axPos(k,1:2), ...
        [0 0; axPos(k,3) 0; axPos(k,3:4); 0 axPos(k,4); 0 0]);
end
handles.p = p;
handles.hAx = hAx;
handles.hImg = hImg;
handles.imgOff = imgOff;
handles.imgOn = imgOn;
% Update handles structure
guidata(hObject, handles);



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

pos = get(hObject,'CurrentPoint');%CurrentPoint
posx = pos(1); posy = pos(2);

%Display to check to see if the position is working
posx = num2str(posx);
posy = num2str(posy);

set(handles.Xpos,'String',posx);
set(handles.Ypos,'String',posy);

p = handles.p;
hImg = handles.hImg;
hAx = handles.hAx;
imgOff = handles.imgOff;
imgOn = handles.imgOn;


%# for each axis, determine if we are inside it
    for i=1:numel(hImg)
        if inpolygon(pos(1),pos(2), p(:,1,i),p(:,2,i))
            set(hImg(i), 'CData',imgOn{i})
            set(hAx(i), 'LineWidth',3, 'XColor','r', 'YColor','r')
        else
            set(hImg(i), 'CData',imgOff{i})
            set(hAx(i), 'LineWidth',1, 'XColor','k', 'YColor','k')
        end
    end

enter image description here 这些是使用原始代码“set(hAx,'Units','pixels')”的击中框。

注意*其他击中框偏离屏幕顶部右侧,或将如此。

enter image description here 这些是使用修改后的代码“set(hAx,'Units','characters')”的击中框。

注意*当代码被注释掉时,会发生完全相同的事情。

测试时间为8月2日。

.

.

.

补充说明 原帖

运行我的GUI之后,我遇到了这个错误[Fatal Error]:-1:-1: 文件过早结束。

这是在以下代码块中发生的:

function figure1_WindowButtonMotionFcn(hObject, eventdata, handles)

% hObject handle to figure1 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

pos = get(hObject,'CurrentPoint');

%CurrentPoint

posx = pos(1); posy = pos(2);

%Display to check to see if the position is working

posx = num2str(posx); posy = num2str(posy);

 set(handles.Xpos,'String',posx); set(handles.Ypos,'String',posy);

%If mouse over then update the immage

if ((115 < pos(1)) && (pos(1) < 125) && (7 < pos(2)) && (pos(2) < 11))
axes(handles.axes1);
imshow('condH.png')  
else 
 axes(handles.axes1);
imshow('cond.png')

 end

 if ((90 < pos(1)) && (pos(1) < 100) && (7 < pos(2)) && (pos(2) < 11))
 axes(handles.axes2);
 imshow('compH.png')  
 else
axes(handles.axes2);
 imshow('comp.png')  
 end

if ((80 < pos(1)) && (pos(1) < 90) && (7 < pos(2)) && (pos(2) < 11))
axes(handles.axes3);
imshow('evapH.png')  
else
 axes(handles.axes3);
 imshow('evap.png')  
 end

if ((90 < pos(1)) && (pos(1) < 100) && (2 < pos(2)) && (pos(2) < 5))
axes(handles.axes4);
imshow('expH.png')  
else
 axes(handles.axes4);
 imshow('exp.png')  
end

通常情况下,GUI 运行良好,直到我将鼠标悬停在预定框上触发其中一个 if 语句。然后 GUI 停止响应,并且直到重新启动 Matlab,它才能再次打开。

1个回答

2
很难在不看到您的整个代码的情况下确定MATLAB崩溃的原因。出于这个原因,我编写了下面的简短示例。它演示了我如何编写一个GUI来模拟翻转效果,并使用WindowButtonMotionFcn回调函数:
function testRolloverGUI()
    %# prepare rollover image
    imgOff = imread('coins.png');
    imgOn = imcomplement(imgOff);

    %# setup figure
    hFig = figure('Resize','off', 'MenuBar','none', 'Color','w');
    set(hFig, 'WindowButtonMotionFcn',@figWindowButtonMotionFcn);
    hTxt = uicontrol('Style','text', 'String','(0,0)');

    %# setup axes
    NUM = 4;
    hAx = zeros(1,NUM);
    hImg = zeros(1,NUM);
    for k=1:NUM
        hAx(k) = subplot(2,2,k);
        hImg(k) = imagesc(imgOff, 'Parent',hAx(k));
    end
    colormap(gray)
    set(hAx, 'XTick',[], 'YTick',[], 'Box','on')

    %# get corner-points of each axis
    set(hAx, 'Units','pixels')
    axPos = cell2mat( get(hAx,'Position') );
    p = zeros(5,2,NUM);
    for k=1:NUM
        p(:,:,k) = bsxfun(@plus, axPos(k,1:2), ...
            [0 0; axPos(k,3) 0; axPos(k,3:4); 0 axPos(k,4); 0 0]);
    end

    %# callback function
    function figWindowButtonMotionFcn(hObj,ev)
        %# get mouse current position
        pos = get(hObj, 'CurrentPoint');
        set(hTxt, 'String',sprintf('(%g,%g)',pos))

        %# for each axis, determine if we are inside it
        for i=1:numel(hImg)
            if inpolygon(pos(1),pos(2), p(:,1,i),p(:,2,i))
                set(hImg(i), 'CData',imgOn)
                set(hAx(i), 'LineWidth',3, 'XColor','r', 'YColor','r')
            else
                set(hImg(i), 'CData',imgOff)
                set(hAx(i), 'LineWidth',1, 'XColor','k', 'YColor','k')
            end
        end
    end
end

screenshot


编辑#2

针对您的评论,我在GUIDE中重新创建了示例。以下是主要部分:

%# --- Executes just before rollover is made visible.
function rollover_OpeningFcn(hObject, eventdata, handles, varargin)

    %# Choose default command line output for rollover
    handles.output = hObject;

    %# allocate
    NUM = 4;
    imgOff = cell(1,NUM);
    imgOn = cell(1,NUM);
    hImg = zeros(1,NUM);

    %# read images
    imgOff{1} = imread('coins.png');
    imgOn{1} = imcomplement(imread('coins.png'));
    imgOff{2} = imread('coins.png');
    imgOn{2} = imcomplement(imread('coins.png'));
    imgOff{3} = imread('coins.png');
    imgOn{3} = imcomplement(imread('coins.png'));
    imgOff{4} = imread('coins.png');
    imgOn{4} = imcomplement(imread('coins.png'));

    %# setup axes
    hAx = [handles.axes1 handles.axes2 handles.axes3 handles.axes4];
    for i=1:NUM
        hImg(i) = imagesc(imgOff{i}, 'Parent',hAx(i));
    end
    colormap(hObject, 'gray')
    set(hAx, 'XTick',[], 'YTick',[], 'Box','on')

    %# make sure axes units match that of the figure
    set(hAx, 'Units',get(hObject, 'Units'))

    %# check axes parent container (figure or panel)
    hAxParents = cell2mat( get(hAx,'Parent') );
    idx = ismember(get(hAxParents,'Type'), 'uipanel');
    ppos = cell2mat( get(hAxParents(idx), 'Position') );

    %# adjust position relative to parent container
    axPos = cell2mat( get(hAx,'Position') );
    axPos(idx,1:2) = axPos(idx,1:2) + ppos(:,1:2);

    %# compute corner-points of each axis
    p = zeros(5,2,NUM);
    for k=1:NUM
        p(:,:,k) = bsxfun(@plus, axPos(k,1:2), ...
            [0 0; axPos(k,3) 0; axPos(k,3:4); 0 axPos(k,4); 0 0]);
    end

    %# store in handles structure
    handles.p = p;
    handles.hAx = hAx;
    handles.hImg = hImg;
    handles.imgOff = imgOff;
    handles.imgOn = imgOn;

    %# Update handles structure
    guidata(hObject, handles);


%# --- Executes on mouse motion over figure - except title and menu.
function figure1_WindowButtonMotionFcn(hObject, eventdata, handles)

    %# CurrentPoint
    pos = get(hObject,'CurrentPoint');
    set(handles.text1,'String',sprintf('(%g,%g)',pos));

    %# for each axis, determine if we are inside it
    for i=1:numel(handles.hImg)
        if inpolygon(pos(1),pos(2), handles.p(:,1,i),handles.p(:,2,i))
            set(handles.hImg(i), 'CData',handles.imgOn{i})
            set(handles.hAx(i), 'LineWidth',3, 'XColor','r', 'YColor','r')
        else
            set(handles.hImg(i), 'CData',handles.imgOff{i})
            set(handles.hAx(i), 'LineWidth',1, 'XColor','k', 'YColor','k')
        end
    end

GUI基本上与以前的组件相同,唯一不同之处在于轴被包含在一个中(类似于您GUI的屏幕截图):

GUIDE

一些需要注意的事项:
  • 由于我们的目标是将图形的CurrentPoint与坐标轴位置进行比较,因此重要的是它们具有与图形相同的Units。因此: set(hAx, 'Units',get(hObject, 'Units'))

  • 根据文档,轴的Position属性是相对于其父容器的,因为四个轴都在一个面板内,所以我们需要相应地调整它们的位置:axPos(idx,1:2) = axPos(idx,1:2) + ppos(:,1:2);

GUI_in_action


好的。我不知道您是否想看整个代码,但对于这个示例代码,我该如何修改才能与 GUIDE 预先制作的轴和图形一起使用? - CMacDady
@CMacDady:应该是类似的:第一部分是我通过编程设置图形和轴。这可以使用 GUIDE 和属性检查器完成。请注意,在图形的初始化函数中读取和存储图像最好。接下来,您将设置 WindowButtonMotionFcn 回调,如上所示。更新图像的 CData 比从头开始重新绘制它更快。最后,我使用了 INPOLYGON 函数,但如果您喜欢,可以保留您拥有的测试... - Amro
好的,关于回调函数。每次调用WindowButtonMotionFcn时,它通过for循环遍历每个区域。 然而,您将4个子图存储在一个矩阵中,然后将4个属于子图的图像存储起来...我有预先制作的坐标轴 我能做类似hAx(1) = axes1; hAx(2) = axes2;这样的事情吗? - CMacDady
@CMacDady:在上面的例子中,我使用嵌套函数来访问父级上下文中的数据。在GUIDE生成的图形中,使用传递给所有回调函数的“handles”结构。因此,您必须将稍后需要的任何数据存储在此结构内:“handles.p = []; guidata(hObject, handles);” - Amro
@CMacDady:恐怕这个问题越来越难以理解了...你能否编辑一下你的问题并发布一下你已经完成的部分? - Amro
显示剩余20条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接