关于Swing

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Swing相关的知识,希望对你有一定的参考价值。

public class HelloWorld extends JFrame
public HelloWorld()

super();//调用本类的父类的构造函数------请告诉我父类的构造函数是什么样的,这个我一直不明白。
如果写成super("xxx");的话,“xxx”是标题吗?

this.setSize(300, 200);
this.getContentPane().setLayout(null);
this.add(getJLabel(), null);
this.add(getJTextField(), null);
this.add(getJButton(), null);//请问这三个组件是怎么排列的
this.setTitle("HelloWorld");


private javax.swing.JLabel getJLabel()
if(jLabel == null) //请问这个null是什么意思?

jLabel = new javax.swing.JLabel(); /*这里这样写对吗?为什么不写成
javax.swing.JLabel jLabel = new javax.swing.JLabel();*/

jLabel.setBounds(34, 49, 53, 18); //这是它的左上角位置和宽与高吧?
jLabel.setText("Name:");

return jLabel;


private javax.swing.JTextField getJTextField()
if(jTextField == null)
jTextField = new javax.swing.JTextField();
jTextField.setBounds(96, 49, 160, 20);

return jTextField;


private javax.swing.JButton getJButton()
if(jButton == null)
jButton = new javax.swing.JButton();
jButton.setBounds(103, 110, 71, 27);
jButton.setText("OK");

return jButton;


public static void main(String[] args)

HelloWorld w = new HelloWorld();
w.setVisible(true);

万分感谢!!!
为什么要调用super();
调用它的结果是什么?

为什么下面这个就不用调用super();

class test extends Frame

public test

setSize(400,400);
setBackground(Color.cyan);
setVisible(true);

参考技术A 如果写成super("xxx");的话,“xxx”是标题吗? 是标题.

你继承了JFrame, super(); 调用了JFrame的构造方法.

不调用也可以啊 设置标题可以用 setTitle("XXX");
参考技术B super();+ this.setTitle("HelloWorld"); = super("HelloWorld");
这下明白了吧?就是调用父类的构造方法,frame是在awt包里的,JFrame是在swing包里的,设计不一样,

Swing:关于Java界面编程的第一课,如何正确的处理界面中的线程

转载:http://blog.csdn.net/sunyiz/article/details/8004573

 

关于 Java 的 GUI ,关于 Swing,其实有一件事情是非常重要的
那就是线程!
如何正确的使用 GUI 线程,
什么样的代码应该在 GUI 线程上执行?
什么样的代码应该用其他线程执行?
其实这些都很重要,
但是,很多关于 Java 的教材都没有强调过这些,甚至有的书完全就忽略了这一点
所以,我在这里要给所以开始接触 Swing 的人,讲述一个重要概念:
Swing 中的线程

---------------------------------------------------------------------------

要说明这个问题,我们要先来看一个贴子:
http://tieba.baidu.com/p/1872190099
这是我昨天发的贴子,里面已经简单叙述了 GUI 中的各个线程

现在,我们先来回顾一下 EDT----这个至关重要的线程
这个 EDT 是干什么的呢?它负责指派所有的 GUI 事件
比如键盘按钮按下后,派发给对应控件的监听器
比如鼠标点击后,派发给对应控件的监听器
比如:绘制控件
所以,我们一般又喜欢把 EDT 叫做 GUI 线程。

EDT 是一种排队的模式,就是各种事件会在其中排队等待,依次执行
其实所有的绘制,在 Swing 内部处理时,全都包装成了 Paint 事件然后进入 EDT 排队
而且 EDT 还会智能的合并多个连续的 Paint 事件,把它们包装成一个 Paint 事件

下面阐述一个重要的规范:Swing 单线程规范
“所有的界面相关更新,都应当在 EDT 中执行”
这个规范非常重要,在你编写 Swing 程序的过程中,请一直牢记他

---------------------------------------------------------------------------

现在,让我们先来设定一个小小的目标,然后我们去实现它,从中探讨和发现问题
就做一个按时间变化的进度条吧,很多新手在刚开始时,都对这个功能的实现表示纠结
下面,我们先来写一段代码:

[java] view plain copy
 
  1. public class ProgressFrame extends JFrame implements ActionListener {  
  2.   
  3.     private JButton btn = new JButton("Start");  
  4.     private JProgressBar bar = new JProgressBar(){  
  5.         public void paint(Graphics g) {  
  6.             super.paint(g);  
  7.             System.out.println("paint");  
  8.         }  
  9.     };  
  10.   
  11.     public ProgressFrame() {  
  12.         init();  
  13.     }  
  14.   
  15.     private void init() {  
  16.         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  17.         setSize(300,200);  
  18.         setLocationRelativeTo(null);  
  19.         setLayout(new FlowLayout());  
  20.         add(btn);  
  21.         add(bar);  
  22.         btn.addActionListener(this);  
  23.         setVisible(true);  
  24.     }  
  25.   
  26.     @Override  
  27.     public void actionPerformed(ActionEvent e) {  
  28.         for (int i = 0; i <= 10; i++) {  
  29.             bar.setValue(i * 10);  
  30.         }  
  31.     }  
  32.       
  33.     public static void main(String[] args) {  
  34.         new ProgressFrame();  
  35.     }  
  36.   
  37. }  




我们的想法很简单,就是在点下按钮后,让进度条设值 11 次,达到动画效果
但是你运行后,点下按钮时,发现几乎是瞬间,进度条就满了,
“paint”也只打印了一次


---------------------------------------------------------------------------


是不是没有延时太快了?
那让我们对 actionPerformed 方法做一点小小的修改:

[java] view plain copy
 
  1. @Override  
  2. public void actionPerformed(ActionEvent e) {  
  3.     for (int i = 0; i <= 10; i++) {  
  4.         try {  
  5.             Thread.sleep(200);  
  6.         } catch (InterruptedException e1) {  
  7.             e1.printStackTrace();  
  8.         }  
  9.         bar.setValue(i * 10);  
  10.     }  
  11. }  




你会发现,按下按钮后,界面如死机般僵硬 2 秒之后,依然是进度条直接满
“paint”也只打印了一次

这是什么原因呢?

下面我们要再说一个在编写 Swing 程序中,应该遵守的规则:

“不要在 EDT 中执行耗时代码,耗时工作应当有一个单独的线程去处理”


因为如果你让耗时代码占用了 EDT,那 EDT 中的那些绘制啊什么的任务都将没空执行
这些事件被压到 EDT 的最后去排队,然后又被 EDT 合并成了一个 Paint 事件
从而结果就是:Paint 只在最后不再 sleep 之后,执行了一次

也许有人会很奇怪,这个 actionPerformed 怎么就在 EDT 中执行了呢?
还记得我们说过的 EDT 的作用么?
它会接受 toolkit 线程传递来的系统事件,
然后传递给对应控件的对应监听器,执行对应的方法
所以其实,这个 actionPerformed ,是由 EDT 调用执行的
其实 Swing 控件的大部分监听器的各种方法,都是在 EDT 上执行的
所以,我们要避免在这些监听器的方法中执行耗时操作,否则界面就会卡死!

---------------------------------------------------------------------------


那我们要如何修改才能实现这样的效果呢?
我们需要让这个耗时的工作,在 EDT 之外的线程执行才行:
再次修改 actionPerformed 方法:
 

[java] view plain copy
 
  1. @Override  
  2.  public void actionPerformed(ActionEvent e) {  
  3.      Runnable runnable = new Runnable() {  
  4.            
  5.          @Override  
  6.          public void run() {  
  7.              for (int i = 0; i <= 10; i++) {  
  8.                  try {  
  9.                      Thread.sleep(200);  
  10.                  } catch (InterruptedException e1) {  
  11.                      e1.printStackTrace();  
  12.                  }  
  13.                  bar.setValue(i * 10);  
  14.              }  
  15.          }  
  16.      };  
  17.      new Thread(runnable).start();  
  18.  }  


我们用了一个单独的线程来执行这段代码,

现在让我们再次执行,终于,我们看到了我们期望中的效果,进度条慢慢增加
“paint”也打印了十一次,那我们的程序是否就 OK 了呢?
答案是否定的,因为我们在这样实现的同时,又破坏了 Swing 的单线程规范
没有在 EDT 中执行界面更新操作,
bar.setValue(i * 10);
这句话,应该在 EDT 中执行。
那这里不就有个矛盾了么?在 EDT 中执行也不行,不在 EDT 中执行也不行……

---------------------------------------------------------------------------

其实我们要的只是 bar.setValue(i * 10); 这一句话在 EDT 中执行而已
而 Swing 提供了一个强大的工具类:SwingUtilities
它提供了好几个功能强大的方法,这里,我们需要的是:invokeLater 这个方法
这个方法的作用是:把一个任务,排队到 EDT 的最后,等待执行,
我们现在再次修改 actionPerformed 方法:

[java] view plain copy
 
  1. @Override  
  2. public void actionPerformed(ActionEvent e) {  
  3.     Runnable runnable = new Runnable() {  
  4.           
  5.         int i = 0;  
  6.           
  7.         @Override  
  8.         public void run() {  
  9.             for (i = 0; i <= 10; i++) {  
  10.                 try {  
  11.                     Thread.sleep(200);  
  12.                 } catch (InterruptedException e1) {  
  13.                     e1.printStackTrace();  
  14.                 }  
  15.                 SwingUtilities.invokeLater(new Runnable() {  
  16.                       
  17.                     @Override  
  18.                     public void run() {  
  19.                         bar.setValue(i * 10);  
  20.                     }  
  21.                 });  
  22.                   
  23.             }  
  24.         }  
  25.     };  
  26.     new Thread(runnable).start();  
  27. }  



再次执行,效果和上一次一样,也满足了规范,皆大欢喜。
其实 Swing 为了处理这种类似的问题,专门提供了一个功能强大的类:SwingWorker
关于这个 SwingWorker 我会在以后找时间进行详细的解释,今天先说这么多吧。

---------------------------------------------------------------------------

当然,其实我们的程序还有一个小小的瑕疵:

[java] view plain copy
 
  1. public static void main(String[] args) {  
  2.     new ProgressFrame();  
  3. }  



这里,new ProgressFrame(); 的过程,其实也包含了大量的界面刷新等等
我们不应该让这样的代码在主线程中执行,应该把它放到 EDT 中去:
这样修改一下:

[java] view plain copy
 
  1. public static void main(String[] args) {  
  2.     SwingUtilities.invokeLater(new Runnable() {  
  3.           
  4.         @Override  
  5.         public void run() {  
  6.             new ProgressFrame();  
  7.         }  
  8.     });      
  9. }  




---------------------------------------------------------------------------

这就是关于 Swing 的最重要的第一课:两个规范
“所有的界面相关更新,都应当在 EDT 中执行”
“不要在 EDT 中执行耗时代码,耗时工作应当有一个单独的线程去处理”

这两条规范,将会伴随你的 Swing 程序,直到永远

以上是关于关于Swing的主要内容,如果未能解决你的问题,请参考以下文章

关于写swing时的继承问题

swing:关于调整 JFrame 大小和条件滚动

Swing:关于Java界面编程的第一课,如何正确的处理界面中的线程

关于swing的一些问题

关于Java swing组件焦点的问题(我猜可能是焦点的问题) 高分求全面

2018-03-19面试之下面关于Java Swing的描述,说法错误的是?