Java Swing开发随手记(总结整理版)

  Swing开发整体思路
“顺序”相关项详述
常用控件及属性设置
总结
针对与《Java Swing开发随手记(未完待续……)》篇的总结与整理,重新编排了本文,更名为《Java Swing开发随手记(总结整理版)》,首先对4月20日对发生在四川雅安的7.0级大地震中失去生命的同胞表示默哀。
祈福雅安,中国坚强。

Swing开发整体思路
我个人习惯用的开发或书写思路如下:
1.创建窗体继承JFrame,定义需要的控件变量。
2.为每个变量书写getter方法:Alt+Shift+S--->R。其中,getter方法里自带各个空间的初始化操作(new、setText,setBounds,setFont等等,后面详述)。
3.书写构造函数(如果需要,可以重载),内含两个函数:draw(); 和 init(); 。draw()要放在init();语句的前面,具体原因后面详述。
4.draw();是界面绘制函数,负责把菜单栏和面板放入窗体,控件放入面板的操作。此处一定注意顺序,后面详述。
5.init();我单独放入的是当前窗体属性初始化操作,包括setBounds, setVisible, setIconImage, setTitle, setResizable等等。其中注意的是setVisible的位置,要放在最后一条语句,后面详述。
这样,就把大体的框架列出来了,如果要添加控件,思路很清晰,只需要定义新增控件变量--->getter方法(附带初始化)--->修改draw();函数,把控件放入面板中即可。

“顺序”相关项详述
上面也说到了,很多控件的添加、属性的设置、函数的先后执行都有顺序问题。下面列举一下我曾碰到过的问题:

@Warning:明明添加了控件,却不能显示
@Warning:编译时异常:java.lang.NullPointerException 空指针异常(我见过最多的异常了:()。
@Warning:窗体打开的过程中,先会显示部分黑色(也许是一闪而过),然后才能显示其他控件。
@Warning:在设置了背景图片的时候,打开窗口只显示背景不显示其他控件,当鼠标划过的时候才会显示。
@Warning:打开窗口时,可能会一片空白,稍等片刻会加载完全,虽然显示正常,但是让人感觉不舒服。
@Warning:菜单栏按钮的顺序不正确

好吧,如果以上问题你也碰到过,不知道你有没有发现是什么原因造成的。下面就个人经验总结一下出现以上情况的原因:
@Solve:第一条,如果你不是按照我上面写的思路来的,而是把所有控件的初始化放到一个函数里,放在了绘制函数(draw())之前,出现了添加了控件不能显示,那么就是在绘制的过程中,控件添加的顺序有错误。
解决办法:a.检查控件顺序。b.检查是否设置setBounds,问题虽小,但有时确实会忘记。
@Solve:第二条,如果你采用的是我这种写法,把每个控件的初始化分开来,放在各自的getter方法里,很容易出现空指针异常,不过也是好事,可以时刻提醒你要注意绘制顺序。
解决办法:先把“菜单栏”或“面板”放到“窗体(this)”里,再把控件放入面板。


//首先要把面板放入窗口   
this.add(this.getMainPanel());   
//再把控件放入面板   
this.mainPanel.add(this.getTip1());  


这个顺序如果不对,就会空指针异常,因为第二条语句中的mainPanel是基于第一行中getMainPanel()函数中new出来的,如果不先执行getMainPanel(),而去直接调用mainPanel的话,它是指向null的,会报编译时错误。
@Solve:第三条,因为有点强迫症和完美主义,所以出现的黑色让我很是不舒服,一个不经意的发现,才知道跟一条语句的顺序有关:this.setVisible(true); 就是这条设置窗体可见的语句。这句话如果放在窗体其他属性初始化之前,则会出现这种情况,相反,放在最后一条,则就没有了。我认为,可能是因为在执行语句的时候,如果先设置可见,再去设置位置、尺寸等属性的时候,由于JVM的短暂时延,会出现黑色背景的一闪而过。
解决办法:把this.setVisible(true);放在本窗体属性初始化的最后一条。


//设置标题   
this.setTitle("带有计时器的猜词游戏");   
//设置位置和尺寸,FrameUtil为自用工具包内类,提供将窗口居中的setCenter(JFrame frame)方法   
this.setSize(450, 354);   
FrameUtil.setCenter(this);   
//固定大小   
this.setResizable(false);   
//修改图标   
URL url = MainFrame.class.getResource("/images/favicon.png");   
ImageIcon icon = new ImageIcon(url);   
this.setIconImage(icon.getImage());   
//设为可见,本条语句放在最后!   
this.setVisible(true);  


上述示例提供了修改程序图标的方法,推荐采用URL的方式,更加灵活。
其中注意 MainFrame.class.getResource(String path);的用法--->本类名.class.方法名。
@Solve:第四条,背景图片和其他控件的显示问题,要考虑到背景图片的语句和其他控件的语句顺序了,其实背景图片语句就是一个JLabel,也是要放入JPanel里的,但是要放到最后一条,否则就把其他控件覆盖了。通过这个问题,我认为JVM的显示顺序是,上边的语句在下边的语句的上层,那感觉和画画是截然相反的,是一层一层的下层部署,不知道这个认知有没有错误,如果有知道JVM原理的请留言告诉一声,以便纠正。
解决办法:包含背景图片的JLabel语句,要在绘制函数(draw())的最后一条。


//将面板放入窗体   
this.add(this.getMainPanel());   
//将控件放入面板   
this.mainPanel.add(this.getFloatBar());   
……   
//其他控件要放在背景图片前边   
this.mainPanel.add(this.getBackImage());  


这个问题是在开发带有背景图片的软件时所需要特别注意的。
@Solve:第五条,这种情况就关乎到draw()和init()函数的先后顺序了,注意,我的init()和老师的功能是不同的:老师的init()是用来初始化所有控件的,而我用的init()只是来初始化当前窗口的属性的。这个问题的出现就意味着,在构建Swing窗体时,是先要把所有控件都加载到窗口(此时JVM已经启动,控件也都准备好,只是没有显示而已),再通过对窗体的初始化属性一块来显示好,还是先布局出窗体,让JVM慢慢在窗体上显示出其他的好(其实不是慢慢的,JVM很快的,只是突出这个过程的不同)?在我看来,肯定喜欢前者,客户肯定想打开软件展现在眼前的是一个完整的、瞬间的构图,所以我选择了前者。
解决办法:把draw();放在init();前面。


//构造函数初始化   
public MainFrame() {   
    //先draw后init.init功能是初始化当前窗体的属性。   
    draw();   
    init();   
}  


貌似这也关系到JVM底层的运行问题啊,如果知道的大牛请告知一声,谢啦。
@Solve:第六条,菜单栏按钮的顺序是和书写顺序息息相关的,按照从左到右、从上到下的顺序来的。就是说,语句在前的菜单按钮在左边(上边),语句在后的菜单按钮在右边(下边)。
解决办法:检查将JMenuBar加入窗体时是不是用的setJMenuBar()方法,并且按照“从左到右,从上到下”的顺序去检查语句顺序。


//把菜单放入窗体,用setJMenuBar   
this.setJMenuBar(this.getJmb());   
//一层一层的“嵌套”添加   
this.jmb.add(this.getJmFile());   
this.jmFile.add(this.getJmiOpen());   
this.jmFile.addSeparator();//添加分割线   
this.jmFile.add(this.getJmiClose());   
  
this.jmb.add(this.getJmEdit());   
this.jmEdit.add(this.getJmiShow());  


上例的菜单栏就形如:从左到右是: File---Edit,从上到下是:File下有Open---Close,Edit下有Show。

常用控件及属性设置
一、JLabel(标签)

设置背景图片---this.backImage = new JLabel(new ImageIcon(url));
设置位置尺寸---setBounds(x, y, width, height); 各个控件通用
设置字体样式---setFont(new Font("微软雅黑", Font.BOLD, 15));
设置字体颜色---set.Foreground(Color.ORANGE);
设置字体位置---setHorizontalTextPosition(JTextField.CENTER);

二、JTextFields/JTextArea(文本框/域)

设置为不可编辑状态---setEditable(false);
设置背景颜色---setBackground(Color.GRAY);
设置文本域自动换行---setLineWrap(true);

三、JButton(按钮)

点击按钮事件监听---JButton.addActionListener(new ActionListener() { @Override });

四、JFrame(窗体)

修改窗体标题---setTitle(String str);
设置窗体可见---setVisible(true);
固定窗体大小---setResizable(false);
设置关闭窗体时选项---setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);然后再监听窗体关闭事件,达到控制窗口关闭的提问与选择。EXIT_ON_CLOSE,关闭本窗口退出虚拟机。DISPOSE_ON_CLOSE,关闭窗口释放占用的JVM。
修改图标---setIconImage(new ImageIcon(url).getImage());
窗口时间监听---this.addWindowListener(new WindowAdapter() { @Override } );

五、JRadioButton(单选按钮)

实现选择互斥,将按钮放入ButtonGroup
如果将按钮放入ButtonGroup的过程中new过,则放入面板的时候不能重新new了。

六、JComboBox(下拉列表)

获取选择项的下标---getSelectedIndex()
获取选择项(Object类型)---getSelectedItem();

七、JFileChooser(文件选择)

创建文件选择器---JFileChooser jfc = new JFileChooser();
显示打开文件窗口---jfc.showOpenDialog(null);
显示保存文件窗口---jfc.showSaveDialog(null);
获取文件(File类型)---jfc.getSelectedFile();
获取文件路径---jfc.getSelectedFile().toString(); 就是把获取的文件toString一下就是路径了。

八、JOptionPane(弹出选项面板)

创建一个选项面板---JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageType)
面板返回值为int,0是Yes,1是No,2是Cancel,配合if...else语句,选择不同的操作,非常灵活。

九、JMenuBar, JMenu, JMenuItem (菜单栏)

添加JMenuBar到JFrame--- JFrame.setJMenuBar(JMenuBar); 用的是setJMenuBar方法,不是add,因为一个窗口只有一个菜单栏。
JMenuBar不占用JPanel空间,JMenuBar + JPanel = JFrame 。
选项下边还有选项的话,就用JMenu。就是说JMenu里可以有JMenu。


总结
文字写的很多,如果你能看到这里,首先感谢对本文的支持,同时也希望我们能够一起进步。上周六晚上开始着手做一个项目,直至今天上午才排查掉错误,逐步完善好了。
这个程序是,一个学心理学的朋友要做实验项目,要求是屏幕随机产生一个情绪词汇,选择对应的词汇性质,分为正性、中性、负性。每隔N秒刷新词汇,选择错误或者超时不答者算错误。进行不同时间间隔的多次实验,取得一个成功率的数据。
我尝试着用刚学过的知识做了一个功能基本可以实现的小软件,基本囊括了Swing课上所学的控件、菜单、计时器、时间监听等等,我认为在学习的道路上,自己动手开发还是很有乐趣的。先上个图晒晒主界面:

通过这几天的学习和开发,总结了几点个人经验:
1.开发之前的构思很重要。我这次就吃了很多构思的亏,习惯性的一点一点的去添加功能,但是最后忘记添加菜单栏了,再添加进去的时候背景图片错位了。所以以后要特别注意,界面的设计最好在设计之初就构建好,最后一起添加功能。
2.多运用匿名内部类实现事件监听。不管是什么控件,都可以在其中加入监听,可以方便的使用匿名内部类。
3.善于利用try...catch和JOptionPane配合。实现对非法操作的警告或提示。
……

posted @ 2016-05-19 08:07  会飞的小祥  阅读(472)  评论(0编辑  收藏  举报