欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MATLAB App Designer入门实战(二)

程序员文章站 2024-01-24 15:33:04
...

为了方便汇总,这里的目录是接着第一篇来的。
第一弹链接:MATLAB App Designer入门实战(一)
注: 本文中多次提到的主动创建的控件及自动创建的控件是指:
主动创建的控件: 通过编程的方式创建的控件
自动创建的控件: 通过编拖拽创建并在检查器定义初始属性的控件

入门实战第二弹——2048小游戏App

7.如何批量创建控件——控件矩阵创建

我们虽然可以通过拖拽创建多个控件,但依次为其增添属性过于麻烦。
app自动创建的各个控件其实相当于app的几个公有属性,我们很自然的想到在添加属性的位置添加一个控件矩阵,并在startupFcn为其位置、颜色等属性赋值。
2048小游戏App中我们需要批量创建的便是一个一个数字卡片(有些目前没有数字):

MATLAB App Designer入门实战(二)

一共要创建4x4=16个,同时还需要适宜的编号对各个卡片进行区分,这时候我们便可以创造一个控件矩阵,并通过( i , j )这样的数对来确定修改或调用哪个控件。
我们首先在添加属性的区域添加要创建的控件矩阵名:
MATLAB App Designer入门实战(二)
之后通过for循环批量创建控件:
MATLAB App Designer入门实战(二)
需要注意的是,使用控件矩阵创建只能使用set对其更改属性,不能保证未来App Designer是会只允许使用点赋值,对此我想到了接下来介绍的结构体方法。

8.如何批量创建控件——通过字符串对结构体控件批量创建

依旧需要在属性创建区域添加要创建结构体控件名
startupFcn函数中,我们需要先构建含有i,j信息的字符串,例如Num12代表第一行第二列的控件。
字符串的创建方式如下:

for i=1:4
	for j=1:4
	tempStr=['Num',num2str(i),num2str(j)];
	end
end

之后便可以通过各个字符串创造出控件,创造方式如下:
MATLAB App Designer入门实战(二)
需要注意到的是,在创建和调整时,字符串必须在括号内,我们在调用时可以有两种调用方式,举将第二行第一列控件文本改为’title’为例:
1直接调用:

app.drawSquareHdl.Num21.Text=‘title’;

2字符串调用

string=‘Num21’;
app.drawSquareHdl.(string).Text=‘title’;
或者
app.drawSquareHdl.(‘Num21’).Text=‘title’;

9.控件的层次

这里只是稍微提一句,由于在startupFcn中创造的控件是最后生成的,所以一般情况下会在所有控件最上层,因此在该程序中,为保证游戏结束界面的控件在数字卡片上面,游戏结束界面控件也写在startupFcn中,同书写位置需要在数字卡片后面,否则就会出现如下情况:

MATLAB App Designer入门实战(二)

10.回调的自主创建与虚控件

我们可以通过按键轻松创造出回调,但是我们自主写在startupFcn中的控件无法增添回调,这时候我们有一个大胆的想法,即创建一个没有任何用处的控件并将其隐藏,我将其称为虚控件,然后我们便可以使我们自主创建的控件和虚控件共享一个回调函数,实现为自主创建的控件增添回调的功能。
如同所示,这里save picture按钮是自主创建的(不然无法出现在数字卡片上方)

MATLAB App Designer入门实战(二)

我们为了为其增添增添回调,需要创建一个无用按钮并隐藏:
MATLAB App Designer入门实战(二)

MATLAB App Designer入门实战(二)

之后为虚控件创建回调:

MATLAB App Designer入门实战(二) 为了让两个按钮公有一个回调,我们在**startupFcn**中写下这么一行
app.SavePicButton.ButtonPushedFcn=createCallbackFcn(app, @SavePicFcn, true)

可以注意到这样主动的回调创建方式与自动创建的回调很类似,都是通过createCallbackFcn创建的:
MATLAB App Designer入门实战(二)
另: 多个自动创建的控件公有一个回调时,回调上方的注释会有显示:
MATLAB App Designer入门实战(二)
但是主动创建的控件使用回调时,并不会在注释中显示:MATLAB App Designer入门实战(二)

11.存储UIFigure为图像

这个真的是无力吐槽了,五六年前就有人提出来了这个问题,至今App designer依旧没有相应的函数,目前主流的方法有两种:
方法一:
将UIFigure中的图像、控件等物件使用figure再重画一遍,再使用figure可使用的函数存储为图片,这个过程中可以设置figure为不可见状态,但这个方法就显得有些不伦不类,明明放弃了figure而使用UIFigure,结果存储图片时却还是要用老方法。
方法二:
。。。。。。。。。。调用java中的函数进行截图,然后获得UIFigure的Position属性。。。。。。然后把需要的那部分图片使用imwrite存储起来,这个2048APP就是使用的这个方法,
代码:
(因为想把边框一并截图,所以会增减一定像素)

screensize=get(0,'screensize');
screensize=1.5*screensize;
robot=java.awt.Robot();
rectangle=java.awt.Rectangle();
rectangle.x=0;
rectangle.y=0;
rectangle.width=screensize(3);
rectangle.height=screensize(4);
image=robot.createScreenCapture(rectangle);
data=image.getData();
temp=zeros(screensize(3)*screensize(4)*3,1);
temp=data.getPixels(0,0,screensize(3),screensize(4),temp);
temp=uint8(temp);
R=temp(1:3:end);
G=temp(2:3:end);
B=temp(3:3:end);
R=reshape(R,[screensize(3),screensize(4)]);
G=reshape(G,[screensize(3),screensize(4)]);
B=reshape(B,[screensize(3),screensize(4)]);
R=R';
G=G';
B=B';
ima=cat(3,R,G,B);
tempPos=app.Game2048AppbyslandarerUIFigure.Position;
xp=tempPos(1);yp=tempPos(2);xl=tempPos(3);yl=tempPos(4);
tempIma=ima(round(yp.*1.5+20):round((yp+yl).*1.5+80),round(xp.*1.5-15):round((xp+xl).*1.5+15),:);
[filename, pathname] = uiputfile({'*.jpg;*.png','All Image Files';...
    '*.jpg','JPG';'*.png','PNG' });
imwrite(tempIma,[pathname,filename]);

12.控件的无法选中状态

这里也是想稍微提一句,控件的无法选中状态(Enable)可以使控件整体的透明度降低,可以用来制作游戏结束的界面:
MATLAB App Designer入门实战(二)
此外如果想要制造这样的界面需要保证各某些控件之间没有重叠的部分,否则便会出现下图的情况:
MATLAB App Designer入门实战(二)


相信认真看完这篇文章的你已经有了还原该mlapp文件的能力,在这里提供m版和mlapp版的连接:
MATLAB 2048小游戏m文件链接:matlab 2048小游戏(第二版)
MATLAB 2048小游戏mlapp文件链接:Game2048App.mlapp