像按钮、下拉框、列表、标签、图片、复选框、编辑框、分割面板、滑动面板、滑动条等都是比较常用的UI类,它们都属于Actor,可以很方便的纳入到舞台的管理中,而且都包含在com.badlogic.gdx.scenes.scene2d.ui包中,

其实仔细看看UI类的实现代码不难发现其实它们都是大部分继承自Widget或者Table,如果需要自定义UI可以继承以上两个类(它们继承自Actor),这里要说明一下libgdx的布局部分使用了TWL,有兴趣的朋友可以去看看。

在介绍每个控件之前我们先来看一下NinePatch,这是最近的一个比较重大的更新。

何为NinePatch?其实android原生即有NinePatch类,常在按钮中使用。

如图,将图片分成九份。中间部分可以根据需要扩大,使按钮的大小内容变动不受图片的限制。

而在libgdx的NinePatch其实就是九个TextureRegion对象。

常用的实例化方法有两个:

public NinePatch (Texture texture, int left, int right, int top, int bottom)

public NinePatch (TextureRegion region, int left, int right, int top, int bottom)

关于其中的四个int型参数如何取值我们可以参考一下源码:

publicNinePatch (TextureRegion region,intleft,intright,inttop,intbottom) {

intmiddleWidth = region.getRegionWidth() - left - right;

intmiddleHeight = region.getRegionHeight() - top - bottom;

this.patches =newTextureRegion[] {newTextureRegion(region,0,0, left, top),

newTextureRegion(region, left,0, middleWidth, top),newTextureRegion(region, left + middleWidth,0, right, top),

newTextureRegion(region,0, top, left, middleHeight),newTextureRegion(region, left, top, middleWidth, middleHeight),

newTextureRegion(region, left + middleWidth, top, right, middleHeight),

newTextureRegion(region,0, top + middleHeight, left, bottom),

newTextureRegion(region, left, top + middleHeight, middleWidth, bottom),

newTextureRegion(region, left + middleWidth, top + middleHeight, right, bottom)};

}

先计算中间部分的宽度和高度。然后开始切图,首先取顶部的最左边的那个,即图中编号1的那块,然后去它右边的,然后再右边的。

取完最上边的那行,然后取中间的那行,然后取最后一行的。

由上自下,由左自右。

而在绘制时又是如何处理的呢?看源码:

publicvoiddraw (SpriteBatch batch,floatx,floaty,floatwidth,floatheight) {

floatcenterColumnX = x;

if(patches[BOTTOM_LEFT] !=null)

centerColumnX += patches[BOTTOM_LEFT].getRegionWidth();

elseif(patches[MIDDLE_LEFT] !=null)

centerColumnX += patches[MIDDLE_LEFT].getRegionWidth();

elseif(patches[TOP_LEFT] !=null)//

centerColumnX += patches[TOP_LEFT].getRegionWidth();

floatrightColumnX = x + width;

if(patches[BOTTOM_RIGHT] !=null)

rightColumnX -= patches[BOTTOM_RIGHT].getRegionWidth();

elseif(patches[MIDDLE_RIGHT] !=null)

rightColumnX += patches[MIDDLE_RIGHT].getRegionWidth();

elseif(patches[TOP_RIGHT] !=null)//

rightColumnX += patches[TOP_RIGHT].getRegionWidth();

floatmiddleRowY = y;

if(patches[TOP_LEFT] !=null)

middleRowY += patches[TOP_LEFT].getRegionHeight();

elseif(patches[TOP_CENTER] !=null)

middleRowY += patches[TOP_CENTER].getRegionHeight();

elseif(patches[TOP_RIGHT] !=null)//

middleRowY += patches[TOP_RIGHT].getRegionHeight();

floattopRowY = y + height;

if(patches[TOP_LEFT] !=null)

topRowY -= patches[TOP_LEFT].getRegionHeight();

elseif(patches[TOP_CENTER] !=null)

topRowY -= patches[TOP_CENTER].getRegionHeight();

elseif(patches[TOP_RIGHT] !=null)//

topRowY -= patches[TOP_RIGHT].getRegionHeight();

// Bottom row

if(patches[BOTTOM_LEFT] !=null) batch.draw(patches[BOTTOM_LEFT], x, y, centerColumnX - x, middleRowY - y);

if(patches[BOTTOM_CENTER] !=null)

batch.draw(patches[BOTTOM_CENTER], centerColumnX, y, rightColumnX - centerColumnX, middleRowY - y);

if(patches[BOTTOM_RIGHT] !=null)

batch.draw(patches[BOTTOM_RIGHT], rightColumnX, y, x + width - rightColumnX, middleRowY - y);

// Middle row

if(patches[MIDDLE_LEFT] !=null) batch.draw(patches[MIDDLE_LEFT], x, middleRowY, centerColumnX - x, topRowY - middleRowY);

if(patches[MIDDLE_CENTER] !=null)

batch.draw(patches[MIDDLE_CENTER], centerColumnX, middleRowY, rightColumnX - centerColumnX, topRowY - middleRowY);

if(patches[MIDDLE_RIGHT] !=null)

batch.draw(patches[MIDDLE_RIGHT], rightColumnX, middleRowY, x + width - rightColumnX, topRowY - middleRowY);

// Top row

if(patches[TOP_LEFT] !=null) batch.draw(patches[TOP_LEFT], x, topRowY, centerColumnX - x, y + height - topRowY);

if(patches[TOP_CENTER] !=null)

batch.draw(patches[TOP_CENTER], centerColumnX, topRowY, rightColumnX - centerColumnX, y + height - topRowY);

if(patches[TOP_RIGHT] !=null)

batch.draw(patches[TOP_RIGHT], rightColumnX, topRowY, x + width - rightColumnX, y + height - topRowY);

}

先计算左右栏的宽度,在计算中间和顶部的高度。然后从下自上的绘制。说实话我觉得这段代码看着很好玩的。

现在来说说几个常用的控件的使用吧。先构建一个舞台。

先来试试Label吧,label是有缓存的,所以替换显示内容不是用setText方法,而是使用setWrappedText方法。

代码如下:

packagecom.cnblogs.htynkn.listener;

importcom.badlogic.gdx.ApplicationListener;

importcom.badlogic.gdx.Gdx;

importcom.badlogic.gdx.graphics.GL10;

importcom.badlogic.gdx.graphics.g2d.BitmapFont;

importcom.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;

importcom.badlogic.gdx.scenes.scene2d.Stage;

importcom.badlogic.gdx.scenes.scene2d.actors.Label;

publicclassFirstGameimplementsApplicationListener {

privateStage stage;

Label label;

@Override

publicvoidcreate() {

stage = newStage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),

true);

label = newLabel("fpsLabel",newBitmapFont(Gdx.files.internal("cf.fnt"),Gdx.files.internal("cf.png"),false),"label1");

label.x=5;

label.y=Gdx.graphics.getHeight()-label.height-5;

stage.addActor(label);

Gdx.input.setInputProcessor(stage);

}

@Override

publicvoiddispose() {

stage.dispose();

}

@Override

publicvoidpause() {

// TODO Auto-generated method stub

}

@Override

publicvoidrender() {

Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

label.setWrappedText("FPS: "+Gdx.graphics.getFramesPerSecond(),

HAlignment.CENTER);

stage.act(Gdx.graphics.getDeltaTime());

stage.draw();

}

@Override

publicvoidresize(intwidth,intheight) {

// TODO Auto-generated method stub

}

@Override

publicvoidresume() {

// TODO Auto-generated method stub

}

}

效果:

然后再看看Button吧,实例化需要一个ButtonStyle,定义了按钮三种状态对应的图片样式,按下和松开时的X,Y偏移还有Button中文字绘制所需的BitmapFont和Color。

按钮的三种状态的图片我就省了,只用一张图片。

修改代码如下:

packagecom.cnblogs.htynkn.listener;

importcom.badlogic.gdx.ApplicationListener;

importcom.badlogic.gdx.Gdx;

importcom.badlogic.gdx.graphics.Color;

importcom.badlogic.gdx.graphics.GL10;

importcom.badlogic.gdx.graphics.Texture;

importcom.badlogic.gdx.graphics.g2d.BitmapFont;

importcom.badlogic.gdx.graphics.g2d.NinePatch;

importcom.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;

importcom.badlogic.gdx.scenes.scene2d.Stage;

importcom.badlogic.gdx.scenes.scene2d.actors.Label;

importcom.badlogic.gdx.scenes.scene2d.ui.Button;

importcom.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;

publicclassFirstGameimplementsApplicationListener {

privateStage stage;

Label label;

Texture texture;

Button button;

@Override

publicvoidcreate() {

stage = newStage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),

true);

texture = newTexture(Gdx.files.internal("06.png"));

NinePatch n1 = newNinePatch(texture,7,7,9,9);

BitmapFont bitmapFont = newBitmapFont(Gdx.files.internal("cf.fnt"),

Gdx.files.internal("cf.png"),false);

label = newLabel("fpsLabel", bitmapFont,"label1");

label.x = 5;

label.y = Gdx.graphics.getHeight() - label.height - 5;

stage.addActor(label);

button = newButton("button",newButtonStyle(n1, n1, n1, 0f, 0f, 0f,

0f, bitmapFont, newColor(1,1,0,0.5f)),"button");

button.x=10;

button.y=10;

button.width=100f;

button.height=32f;

stage.addActor(button);

Gdx.input.setInputProcessor(stage);

}

@Override

publicvoiddispose() {

stage.dispose();

}

@Override

publicvoidpause() {

// TODO Auto-generated method stub

}

@Override

publicvoidrender() {

Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

label.setWrappedText("FPS: "+ Gdx.graphics.getFramesPerSecond(),

HAlignment.CENTER);

stage.act(Gdx.graphics.getDeltaTime());

stage.draw();

}

@Override

publicvoidresize(intwidth,intheight) {

// TODO Auto-generated method stub

}

@Override

publicvoidresume() {

// TODO Auto-generated method stub

}

}

效果:

按钮自然应该有点击事件,通过setClickListener来设置:

button.setClickListener(newClickListener() {

@Override

publicvoidclick(Actor actor) {

Gdx.app.log("Info","点击事件触发了");

}

});

然后再看看CheckBox。CheckBox的样式定义在CheckBoxStyle中,需要4个参数,两种状态的各一张图片,一个BitmapFont和Color。

这里我再添加一张图片:

原理差不多,直接贴代码了。

packagecom.cnblogs.htynkn.listener;

importandroid.graphics.Paint.Align;

importcom.badlogic.gdx.ApplicationListener;

importcom.badlogic.gdx.Gdx;

importcom.badlogic.gdx.graphics.Color;

importcom.badlogic.gdx.graphics.GL10;

importcom.badlogic.gdx.graphics.Texture;

importcom.badlogic.gdx.graphics.g2d.BitmapFont;

importcom.badlogic.gdx.graphics.g2d.NinePatch;

importcom.badlogic.gdx.graphics.g2d.TextureRegion;

importcom.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;

importcom.badlogic.gdx.scenes.scene2d.Actor;

importcom.badlogic.gdx.scenes.scene2d.Stage;

importcom.badlogic.gdx.scenes.scene2d.actors.Label;

importcom.badlogic.gdx.scenes.scene2d.ui.Button;

importcom.badlogic.gdx.scenes.scene2d.ui.CheckBox;

importcom.badlogic.gdx.scenes.scene2d.ui.ClickListener;

importcom.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;

importcom.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle;

publicclassFirstGameimplementsApplicationListener {

privateStage stage;

Label label;

Texture texture1;

Texture texture2;

CheckBox checkBox;

@Override

publicvoidcreate() {

stage = newStage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),

true);

texture1 = newTexture(Gdx.files.internal("06.png"));

texture2 = newTexture(Gdx.files.internal("07.png"));

NinePatch n1 = newNinePatch(texture1,7,7,9,9);

BitmapFont bitmapFont = newBitmapFont(Gdx.files.internal("cf.fnt"),

Gdx.files.internal("cf.png"),false);

label = newLabel("fpsLabel", bitmapFont,"label1");

label.x = 5;

label.y = Gdx.graphics.getHeight() - label.height - 5;

CheckBoxStyle style = newCheckBoxStyle(newTextureRegion(texture1),

newTextureRegion(texture2), bitmapFont,newColor(1,1,1,

0.5f));

checkBox = newCheckBox("checkbox", style,"checkbox");

checkBox.x = 100;

checkBox.y = 100;

checkBox.width = 158f;

checkBox.height = 32f;

checkBox.setText("Yes");

checkBox.setClickListener(newClickListener() {

@Override

publicvoidclick(Actor actor) {

if(checkBox.isChecked) {

checkBox.setText("Yes");

} else{

checkBox.setText("NO");

}

}

});

stage.addActor(checkBox);

stage.addActor(label);

Gdx.input.setInputProcessor(stage);

}

@Override

publicvoiddispose() {

stage.dispose();

}

@Override

publicvoidpause() {

// TODO Auto-generated method stub

}

@Override

publicvoidrender() {

Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

label.setWrappedText("FPS: "+ Gdx.graphics.getFramesPerSecond(),

HAlignment.CENTER);

stage.act(Gdx.graphics.getDeltaTime());

stage.draw();

}

@Override

publicvoidresize(intwidth,intheight) {

// TODO Auto-generated method stub

}

@Override

publicvoidresume() {

// TODO Auto-generated method stub

}

}

效果:

其他的UI大致用法差不多,显示的样式在对应的Style或者Skin中定义。但是要注意有些UI类需要手动设置width和height,不然有些显示会很奇怪的。

最后说一下Slider的用法

SliderStyle需要一个NinePath和Texture,我最初没有想通为什么不是两个NinePath,仔细看一下源码才了解到,NinePath是作为背景,而Texture那个是中间的那个滑动的方块。

关于用配置文件设置Style的问题,google code的wiki上似乎没有写,但是在libgdx的论坛里面有,比如:

somePatch1: [

{ height: 13, width:9, x:761, y:78},

{ height: 13, width:1, x:770, y:78},

{ height: 13, width:9, x:771, y:78},

{ height: 1, width:9, x:761, y:91},

{ height: 1, width:1, x:770, y:91},

{ height: 1, width:9, x:771, y:91},

{ height: 13, width:9, x:761, y:92},

{ height: 13, width:1, x:770, y:92},

{ height: 13, width:9, x:771, y:92}

]

或者

somePatch2: [

{ height: 13, width:9, x:761, y:78},

]

【编辑推荐】

【责任编辑:milk TEL:(010)68476606】

点赞 0

libgdx和android界面结合,Android游戏引擎libgdx使用教程5:常用UI类与舞台相关推荐

  1. android开发重要控件,Android界面编程——Android基本控件

    Android界面编程 Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户. 作为一个程序员 ...

  2. 2D游戏引擎Allegro 系列教程(二) Hello world!

    本系列文章由sky编写,转载请注明出处. http://blog.csdn.net/qq573011406/article/details/8172949 作者:袁全伟   邮箱: qq5730114 ...

  3. 游戏引擎开发入门教程_v20210102

    游戏引擎(Game Engine)是一款游戏的"发动机",是游戏的核心部件,同时也是一个大型软件系统.游戏画面是否绚丽和流畅,游戏场面是否震撼和真实,这些都是由引擎决定的. 从编程 ...

  4. android 游戏引擎libgdx demo cuboc分析

    开始学习android游戏开发也有一段时间了,挑选libgdx这个游戏引擎来进行学习和开发.Libgdx是一款支持2D与3D游戏开发的游戏类库,并且它是夸平台的.例如你可以在windos下开发,同样的 ...

  5. 跨平台(Android, iOS, WP, HTML5)游戏开发libGDX学习教程

    2019独角兽企业重金招聘Python工程师标准>>> 疯狂小土豆的跨平台游戏开发引擎libGDX游戏开发视频,本视频主讲Android和桌面游戏开发.libGdx是一个跨平台的2D ...

  6. Android 8款开源游戏引擎

    1.Angle  (2D    Java) Angle是一款专为Android平台设计的,敏捷且适合快速开发的2D游戏引擎,基于OpenGLES技术开发.该引擎全部用Java代码编写,并且可以根据自己 ...

  7. Java游戏引擎libgdx的简介

    最近想做点小应用,但界面方面是非常不在行,自然想 借助游戏引擎来处理这部分工作.本打算在flex中找一 个比较好的,但找到pushbotton的时候发现官方主页留 下的只有goodbye的页面,留言的 ...

  8. 《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇:简介及目录》(附上完整工程文件)...

    2019独角兽企业重金招聘Python工程师标准>>> 跑酷游戏制作 游戏类型: 此游戏Demo,为跑酷类游戏. 框架简介: 游戏通常由程序代码和资源组成.如果说模型.贴图.声音之类 ...

  9. JAVA游戏引擎!FXGL 教程 总目录

    喜欢打游戏也喜欢编程,总想开发一款自己的游戏,圆自己儿时的一个梦. 我并非要编写一个游戏引擎,故而也用不到LWJGL这种层级的引擎,如果你也是一个和我一样单纯想做一款游戏的javaer,那你也可以和我 ...

最新文章

  1. C++11中std::function的使用
  2. C#判断文件是否存在方法
  3. 关于SQL优化这些你了解吗?
  4. c++面向对象高级编程 学习十七 const, new, delete
  5. python队列只能一个个读取吗_python队列Queue的详解
  6. 我的世界怎么设置服务器维护中,我的世界服务器
  7. python 自动化出报表,python实现报表自动化详解
  8. gitlab 安装gitlabrunner 无法连接tiller_谈一谈GitLab Runner是个什么东东?
  9. CakePHP 中文手册
  10. 【BZOJ1901】Zju2112 Dynamic Rankings
  11. Ubuntu下很给力的下载工具
  12. 修改IDEA格式化单行注释 后增加空格
  13. 计算机二级不看教材只刷题可以吗,中级会计可以只看轻松过关不看教材吗
  14. 茶几上 清明上河图 诗句
  15. 致远oa系统unix 服务器,致远oa服务器设置
  16. 解决App自动化的不稳定因素-弹框及首页启动加载完成判断处理
  17. 微信小程序 常见问题(报错)
  18. linux系统下 USB 摄像头1080分辨率采集帧率低问题的解决方法
  19. python中常用英语口语_常用英语口语100句(超实用)_
  20. java地图点线面_点线面类型互转

热门文章

  1. 比特币的矿工为什么讨厌开发组Core?
  2. RookeyFrame 删除 线下添加的model
  3. Groovy 和 Gradle
  4. mysql启动和关闭外键约束的方法
  5. c#算两个火星坐标的距离(高德or百度)
  6. .NET平台开源项目速览(1)SharpConfig配置文件读写组件
  7. 高性能的MySQL(7)字符集和校对
  8. Android学习——基础组件
  9. 艾伟也谈项目管理,如何做一个合格的项目经理
  10. iOS_多线程(一)