前言:上一个SWING实在是做了太恶心了点,连退出都没弄,一时仓促忘记了给,不过发这个可真麻烦啊,不知道是不是我RP问题,老发不出去,好不容易发上了BLOG吧好几次是空的,要不就是编辑不能,很是痛苦,后来也就懒惰了去弄程序了,不过这次带来了一个新的框架,决定开始做一个地图编辑器,呵呵,这个应该满好玩的,今天就先实现它最简单的一个步骤,把图片显示到SWING中去,至于地图文件的问题我们以后再做讨论(我也没类似经验,全是临时的想法,边想边实践,呵呵),思想和方法都是最简单的那种。这里先不用涉及到java.io.*,因为图片的导入用的是javax.swing.ImageIcon这个类,在创建ImageIcon对象时就可以给构造函数一个URL,来标明你所用的外部图片的位置。好了前边就先说道这里,我们做一下先。
这次的思路很简单,把ImageIcon放到JLabel控件中去,然后在放到JPanel控件里,最后把这个JPanel放到JFrame就可以了。貌似很麻烦的样子,其实不然,因为这次要用到“布局控制”,要让控件按你的想法摆放,到后来你就会直到这样一个套一个的好处了,呵呵。
关于“布局控制”,容器不都有add方法么,布局后你只管add内容,其他的就交给”布局控制“去管就可以了,SWING提供了蛮多的现成的东东给你弄,甚至你用那些东东可以摆放出任意你能想象出来的“造型”。这里只是做简单介绍,能用上就行,慢慢从例子里面体会时最好的,具体的可以参考JDK文档或者具体的SWING的书籍。首先看最简单最普通的一个布局:FlowLayout。它会让组件(控件,随便叫)直接"流"到表单上,从左到右,从上到下,一行满了再换一行。下面我们来举一个FlowLayout的例子。你会发现,用了FlowLayout之后,组件就会冻结在它的"固有"尺寸上。比如JButton就会根据字符串的长度来安排大小。
e.g. :
import java.awt. * ;
class FlowLayoutEG extends JFrame ... {
// 构造函数
public FlowLayoutEG() ...{
// 设置程序标题
this.setTitle("FlowLayout的简单演示");
// 按X时关闭JVM虚拟机(个人理解不同)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置布局为FlowLayout
this.setLayout(new FlowLayout());
this.setSize(200, 200);
// 添加几个控件进去
this.add(new JButton("JButton"));
this.add(new JLabel("JLabel"));
this.add(new JTextField(30));
this.add(new JLabel("请调整窗口大小看控件的布局"));
// .... add more
}
// main
public static void main(String[] args)...{
// 创建一个实例,调用显示方法
(new FlowLayoutEG()).setVisible(true);
}
}
添加了多点控件效果会好点,真的要看效果的话可以考虑写个循环,比如构造函数这样写:
this.setTitle("FlowLayout的简单演示");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.setSize(200, 200);
// 添加几个控件进去
for(int i = 1; i <= 20; i++)
...{
this.add(new JButton("JButton" + i));
}
}
好了,这样一下子就添了20个按钮上去,改变下窗口大小应该能看出FlowLayout是怎样排布的。
再讲下另一个Layout:BorderLayout。这个一般用作大框架上,它分为上(North),下(South),左(West),右(East),中(Center),或者叫做东南西北中也可以,add控件的时候你要自己指明放那里,不然默认就是放到Center去。比如菜单栏可以放North,状态栏放South,中间放编辑区域,左边放工具栏等,其实看看大多WINDOWS软件就知道大概什么个摆放样子了。也举个例子吧:
e.g. :好了,就这么简单,看到效果了吧,嘿嘿,就这么简单。
关于其他还有很多,比如CardLayout,GridLayout(这个用了多,其实就是网格式的排布,最后的一个程序中会用到,自己来看看大概式怎么用的吧,蛮简单的,不所也应该能看懂),地图显示就是要用到GridLayout,还有超级复杂的GridBagLayout,还有BoxLayout等等,有兴趣的可以自己去找这方面的资料看,JDK里面就蛮多的了。
import java.awt. * ;
class BorderLayoutEG extends JFrame ... {
// 构造函数
public BorderLayoutEG() ...{
// 设置程序标题
this.setTitle("BorderLayout的简单演示");
// 按X时关闭JVM虚拟机(个人理解不同)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置布局为BorderLayout
this.setLayout(new BorderLayout());
this.setSize(200, 200);
// 添加几个控件进去
this.add(BorderLayout.NORTH, new JButton("JButton in North"));
this.add(BorderLayout.SOUTH, new JLabel("JLabel in South"));
this.add(BorderLayout.CENTER, new JTextArea(40, 50));
this.add(BorderLayout.WEST, new JButton("JButton in West"));
this.add(BorderLayout.EAST, new JButton("JButton in East"));
// .... add more
}
// main
public static void main(String[] args)...{
// 创建一个实例,调用显示方法
(new BorderLayoutEG()).setVisible(true);
}
}
在做最后的地图编辑器框架要讲下的思路,地图被拆分为单个很小的地图快,就水,我就设计了4种不同的样式,这样可以变化多端是吧,而且这里可以介绍下使用很广泛的随机数,总之一个子,巧!先是一个JLabel放一个地图块,然后把块放到上层的JPanel去,这个JPanel采用GridLayout的排布方式,测试下你能不能看懂,最后再把这个JPanel放到BorderLayout的中间区域去。再在别的区域加电按钮啊什么之类的东西。由于本来就是想做成J2ME的(给自己手机玩,嘿嘿),所以就把图片处理成PNG的了,JPG、GIF、BMP等都可以的,具体自己试验去吧。这里只是一个框架而已,还没有涉及到具体的算法之类的,不要想太远是吧,一步一步慢慢来,先把总体布局弄好,然后要做的事情就是把想法和创意丢进去了咯~这里还用到了接口ActionListener,它就是用来监听哪个控件响应事件了,这里我很简单,就只对jbOK这个按钮做了监听,按下后也就直接退出程序了。
下面是框架的程序:
为了显示水面的不规则性,我还做了个随机对象,rand。声明一个Random对象后,可以调用其nextXXX方法,比如nextInt(int n),返回一个0~n的随机整数,其他还有很多,比如nextBoolean()啊什么的,具体自己看JDK就可以了。一共设置了34×34大小的地图,那么就放那么多的地形进去就可以了,一个for循环搞定!关于监听这里只是稍稍带到,既然是GUI的,监听自然必不可少,不然怎么响应你的鼠标或者键盘事件啊。注意,既然实现了ActionListener接口,那么就要实现其所有方法,幸好这里只有actionPerformed(ActionEvent e)这么一个,所以在里面判断哪个按下就可以了,当然,被监听的那个控件必须用addActionListener(ActionListener l)方法注册为被监听状态才行。有add自然有remove,自己推敲去吧,呵呵。给个任务,把那个jbCancel也注册成监听,然后点击后也和点击jbOK一样的效果,退出程序,不难吧应该。
import java.awt.event. * ;
import java.awt. * ;
import java.util. * ;
// import java.awt.geom.*;
public class SwingEx extends JFrame implements ActionListener ... {
private JButton jbOK = null, jbCancel = null, jbIcon = null,
jbSave = null;
private JPanel jpIcon = null, jpSouth = null,
jpNorth = null, jpEast = null, jpWest = null;
private JLabel jlMap = null, jlTitle = null;
private static ImageIcon[] mapsWater = ...{
new ImageIcon("mapResource/water/water_left.PNG"),
new ImageIcon("mapResource/water/water_middle.PNG"),
new ImageIcon("mapResource/water/water_right.PNG"),
new ImageIcon("mapResource/water/water_blue.PNG")
};
private Random rand = new Random();
// private Dimension d = null;
public SwingEx (String title) ...{
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// d = new Dimension(11, 20);
// JLabel
jlTitle = new JLabel("SLG地图编辑器");
// JButton
jbSave = new JButton("Save Maps");
jbOK = new JButton("OK");
jbOK.addActionListener(this);
jbCancel = new JButton("Cancel");
jbCancel.setEnabled(true); // 设置按钮是否高亮(能否按)
jbIcon = new JButton("WaterMiddle", mapsWater[1]);
// JPanel
jpSouth = new JPanel(new FlowLayout());
jpSouth.add(jbOK);
jpSouth.add(jbCancel);
jpNorth = new JPanel(new FlowLayout());
jpNorth.add(jlTitle);
jpEast = new JPanel(new GridLayout(2,2));
jpEast.add(jbIcon);
jpEast.add(jbSave);
jpIcon = new JPanel(new GridLayout(34,34)); // 设置34×34个格子的JPanel
for(int i = 0, j = 0; i<34*34; i++)
...{
j = rand.nextInt(4);
jlMap = new JLabel(mapsWater[j]);
jpIcon.add(jlMap);
}
jlMap = new JLabel(mapsWater[3]);
// JFrame
this.setLayout(new BorderLayout());
this.setSize(400, 400);
this.setResizable(true);
this.add(BorderLayout.NORTH, jpNorth);
this.add(BorderLayout.SOUTH, jpSouth);
this.add(BorderLayout.CENTER, jpIcon);
this.add(BorderLayout.EAST, jpEast);
}
/** *//**
* Method actionPerformed
*
*
* @param e
*
*/
public void actionPerformed(ActionEvent e) ...{
// TODO: 在这添加你的代码
if (e.getActionCommand().equals("OK"))
...{
System.exit(0);
}
}
public static void main(String[] args)...{
(new SwingEx("Swing Map Editer")).setVisible(true);
}
}
下次就专门弄个总结改进的版本出来,嘿嘿,老是框架不出实际的东西也是不行的是不是,做框架至少也要做好咯~努力吧!Fightting!