>我将要做一个什么?
也算是突发奇想,以前一直用C#写的桌面应用,但最近有点沉迷JAVA,加上最近不小心打开了阔别十来年的QQ宠物(现在QQ宠物Client已经变得都是广告了),想起了瑞星小狮子,有点怀旧,就想找找有没有简单、干净一些的桌面宠物养成游戏软件,写代码的时候趴在窗口上卖卖萌也是甚好的。
找了找,还真有。在Github上找到了一个日本人写的开源桌面宠物项目:https://github.com/nonowarn/shimeji4mac。然而不幸的是,作者似乎也很久不开发了,且这个东西是明确标明需要JRE6-32bit才能运行。在JRE9都出来了的今天,为了这么个宠物专门去寻找、并安装一个JRE6,不合适吧;况且这玩意现在也不算很好找了,哪怕是在oracle官网找JRE6的下载地址都要找不少时间。于是就手痒,想自己写一个。
我会尽量不使用除了JDK自带的jar以外的东西,并随缘更新这个系列。由于我不是很喜欢写xml,因此主要将用Swing来进行开发。
>JAVA的运行问题
刚刚提到了Shimoji桌面宠物需要JRE6才能运行的问题,那我现在用JRE,换个没有JRE环境的电脑不就不能运行了?
啊,确实是这样的,不过我们有办法规避这个问题,让你的jar伪装成一个exe,像c#写的桌面应用一样到处跑:http://blog.csdn.net/shenpibaipao/article/details/78701034
>今天的目标
今天的目标是,既然是桌面宠物,那么它一定是能动的。所以我们先从如何解决桌面宠物的动画问题解决起。
下面是完成后的效果演示:(素材取自Undertale贴吧)
>核心问题
核心问题主要有两个:
在Swing中,我习惯用一个JLabel去加载图片:
public JLabel loadPicture(int x,int y,String url){
JLabel jLabel = new JLabel();
ImageIcon icon = new ImageIcon(url);
int picWidth = icon.getIconWidth(),pinHeight = icon.getIconHeight();
icon.setImage(icon.getImage().getScaledInstance(picWidth,pinHeight,Image.SCALE_DEFAULT));
jLabel.setBounds(x,y,picWidth,pinHeight);
jLabel.setIcon(icon);
return jLabel;
}
上面这段代码会返回一个加载了图片的JLabel,其左上角位置相对于父容器为(x,y)。
要让它动起来,我们需要准备一条连续的图片素材:(图片素材和项目Demo代码我会放到最后供下载使用)
其次,我们专门运行一个新的线程,通过sleep的方法去更换帧。这样效率虽然不高,但我们并不是在写什么大工程,作为一个桌面宠物,足矣。
现在,我们修改刚刚加载图片的方法,把它变成一个给指定JLabel更换新图片的方法:
private void cgJLabelImg(JLabel jLabel,String imgUrl){
ImageIcon icon = new ImageIcon(imgUrl);
int picWidth = icon.getIconWidth(),pinHeight = icon.getIconHeight();
icon.setImage(icon.getImage().getScaledInstance(picWidth,pinHeight, Image.SCALE_DEFAULT));
jLabel.setBounds(0,0,picWidth,pinHeight);
jLabel.setIcon(icon);
}
假设上面三张素材图片的名字分别为:"a1.png"、"a2.png"、"a3.png",那么专门处理动画帧的线程就可以这么写了:
// 动画线程 这里用到了JDK8的lambda表达式
new Thread(() -> {
int i=1;
try{
while (true){
Thread.sleep(250);
cgJLabelImg(jLabel,"a"+ i++ +".png");
if(i>3)i=1;
}
} catch (Exception e){
e.printStackTrace();
}
}).start();
我在这里写了个JDK8的Lambda表达式,如果你对这种写法有兴趣,可以看看这里: http://blog.csdn.net/shenpibaipao/article/details/78622456。不过就算不想了解Lambda表达式也没关系,其相当于:
new Thread(new Runnable() {
@Override
public void run() {
int i=1;
try{
while (true){
Thread.sleep(250);
cgJLabelImg(jLabel,"a"+ i++ +".png");
if(i>3)i=1;
}
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
现在就可以去运行程序了。然后你会注意到一个问题,由于我们的素材是背景透明的png图片,但承载JLabel的JFrame的背景却是灰色的实体背景,看着就很丑。而且我们其实也不需要标题栏,那么我们可以给JFrame加上两个属性:
// 框体透明
this.setUndecorated(true); // 取消窗口标题栏
this.setBackground(new Color(0,0,0,0));// 背景透明
完活,今天的任务就到这里结束了。可以到下面的链接去下载具体的素材和代码自己试试。
>素材及Demo代码下载
CSDN下载:http://download.csdn.net/download/shenpibaipao/10143462