import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EventListener;import javax.swing.JFrame;
import javax.swing.JPanel;/**
 * 
 * 
 * @author Administrator
 * 
 */
public class EventSourceTest {
public static void main(String[] args) {
EventSourceFrame ef = new EventSourceFrame();
ef.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ef.setVisible(true);

}
}@SuppressWarnings("serial")
class EventSourceFrame extends JFrame {
public EventSourceFrame() {
setTitle("EventSourceTest");
setSize(400, 200); final PaintCountPanel panel = new PaintCountPanel();
add(panel); panel.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) {
setTitle("EventSourceTest - " + evt.getNewValue());
}
});
}
}@SuppressWarnings("serial")
class PaintCountPanel extends JPanel { @Override
protected void paintComponent(Graphics g) {
int oldPaintCount = paintCount;
paintCount++;
firePropertyChangeEvent(new PropertyChangeEvent(this, "paintCount",
oldPaintCount, paintCount));
super.paintComponent(g);
} public void addPropertyChangeListener(PropertyChangeListener listener) {
listenerList.add(PropertyChangeListener.class, listener);
} public void removePropertyChangeListener(PropertyChangeListener listener) {
listenerList.remove(PropertyChangeListener.class, listener);
} public void firePropertyChangeEvent(PropertyChangeEvent event) {
EventListener[] listeners = listenerList
.getListeners(PropertyChangeListener.class);
for (EventListener l : listeners)
((PropertyChangeListener) l).propertyChange(event);
} public int getPaintCount() {
return paintCount;
} private int paintCount;
}
看半天 没看懂

解决方案 »

  1.   

    看一下swing编成方面的资料,然后再看这代码。
      

  2.   

    关键是我看了swing方面的书籍 看不太懂代码
      

  3.   

    很久不看GUI的东西了。简单解答下:首先,EventSourceTest是一个运行类,在他内部承载这需要显示的JFrame也就是窗口。而
     EventSourceFrame ef = new EventSourceFrame();
            ef.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ef.setVisible(true);的目的,就是将内部的EventSourceFramem这个窗口显示出来。具体的设置可以去参看J2SE的API。我这里不详细说明了。之后就是EventSourceFramem,它继承字JFrame。虽然JFrame是非抽象的,这里继承的目的就是将Frame的一些属性前期设置好。例如标题、大小以及内部的摆放。JPanel是轻量的容器,作用是更加细分窗口中的布局。就像在Windows变成下的Panel一样。
    class EventSourceFrame extends JFrame {
        public EventSourceFrame() {
            setTitle("EventSourceTest");
            setSize(400, 200);        final PaintCountPanel panel = new PaintCountPanel();
            add(panel);        panel.addPropertyChangeListener(new PropertyChangeListener() {            public void propertyChange(PropertyChangeEvent evt) {
                    setTitle("EventSourceTest - " + evt.getNewValue());
                }
            });
        }
    }
    之后就是内部类PaintCountPanel继承于JPanel。具体的功能已经在上文描述了。下面说一下流程。main()->EventSourceFramem->PaintCountPanel这样一个大体的流程。代码不复杂,仔细看下就可以明白了。另外简述下你上一个贴里问道的内部类的问题。内部类的功能是建立私有的类对象以保证不会被其他类使用。所以不是简简单单的“实现接口,和重写父类方法时候用”就像POJO会将属性定义为private一样。是保证结构的一个规整。内部类一般会声明为private。当然也可以声明为public。声明为public就等同再写一个Class了。而且没有必要在接口中将内部类的方法声明出来。因为接口方法必须是public。这样也就失去了要私有类的目的了。看一下下面这个类的写法:
    public class Parameterized extends Suite {
    /**
     * Annotation for a method which provides parameters to be injected into the
     * test class constructor by <code>Parameterized</code>
     * 定义了Parameters的标注
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public static @interface Parameters {
    }        ...
    }这是JUnit4参数化测试的一个标注写法。可以看到Parameters这个标注的私有类是在Parameterized这个类的私有类,他的目的就是实现了,只有在使用Parameterized标注的测试类里才能使用Parameters这个标注。这也是私有化的一个意义。
      

  4.   


    import java.awt.Graphics;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.util.EventListener;import javax.swing.JFrame;
    import javax.swing.JPanel;/**
     * 
     * 
     * @author Administrator
     * 
     */
    public class EventSourceTest {
    public static void main(String[] args) {
    //創建自定義的frame
    EventSourceFrame ef = new EventSourceFrame();
    //點擊關閉按鈕,程序退出
    ef.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //讓該Frame可顯示
    ef.setVisible(true); }
    }@SuppressWarnings("serial")
    class EventSourceFrame extends JFrame {
    public EventSourceFrame() {
    //设置Frame的标题信息
    setTitle("EventSourceTest");
    //设置Frame为宽400,高200
    setSize(400, 200);

    //创建自定义的Panel,由于要在匿名内部类中使用,所以定义为final类型
    final PaintCountPanel panel = new PaintCountPanel();
    //将panel加在frame的contentPane中
    add(panel);

    //给panel添加属性监听器
    panel.addPropertyChangeListener(new PropertyChangeListener() {

    //监听接口方法的具体实现
    public void propertyChange(PropertyChangeEvent evt) {
    //设置Frame的标题信息(每次拖动Frame,都会执行该方法)
    setTitle("EventSourceTest - " + evt.getNewValue());
    }
    });
    }
    }@SuppressWarnings("serial")
    class PaintCountPanel extends JPanel { @Override
    //重写继承自JComponent的方法
    protected void paintComponent(Graphics g) {
    int oldPaintCount = paintCount;
    //每次Panel变化,则重画次数增加一次,因为会调用paintComponent()方法
    paintCount++;
    //通知监听列表的监听器,属性被改变
    firePropertyChangeEvent(new PropertyChangeEvent(this, "paintCount",
    oldPaintCount, paintCount));
    //为保证画面的完整,调用父类的paintComponent()方法
    super.paintComponent(g);
    } //添加监听器
    public void addPropertyChangeListener(PropertyChangeListener listener) {
    listenerList.add(PropertyChangeListener.class, listener);
    } //移除监听器
    public void removePropertyChangeListener(PropertyChangeListener listener) {
    listenerList.remove(PropertyChangeListener.class, listener);
    } //通知监听器
    public void firePropertyChangeEvent(PropertyChangeEvent event) {
    EventListener[] listeners = listenerList
    .getListeners(PropertyChangeListener.class);
    //此处将会调用监听器的propertyChange()方法,也就是匿名内部类里的方法
    //参数event对象就是new PropertyChangeEvent(this, "paintCount",oldPaintCount, paintCount));
    //保存了事件的源,被改变属性,以前的值和改变后的值
    for (EventListener l : listeners)
    ((PropertyChangeListener) l).propertyChange(event);
    } public int getPaintCount() {
    return paintCount;
    }
    //记录该Panel重画的次数
    private int paintCount;
    }
      

  5.   

    流程是:
    从main函数起动
    ->打开Frame窗口
    ->将Panel加入Frame中,并且给Panel添加监听器
    ->Panel被拖动(拖动Frame,Panel跟着动)或者最小化则通知注册的监听器,重新设置Frame的标题信息其中 Panel中的 paintComponent 在Panel被改变时自动调用,
    监听器的propertyChange方法在    //通知监听器
        public void firePropertyChangeEvent(PropertyChangeEvent event) {
            EventListener[] listeners = listenerList
                    .getListeners(PropertyChangeListener.class);
            //此处将会调用监听器的propertyChange()方法,也就是匿名内部类里的方法
            //参数event对象就是new PropertyChangeEvent(this, "paintCount",oldPaintCount, paintCount));
            //保存了事件的源,被改变属性,以前的值和改变后的值
            for (EventListener l : listeners)
                ((PropertyChangeListener) l).propertyChange(event);//发送属性更改的消息
        }
    红字部分调用后被自动调用。
      

  6.   

    其实我上面说的自动调用,比如那个红字部分的,
    你可以通过看jdk源码看清楚如何触发的。
    可以看下 javaBean构建里绑定属性的内容。
      

  7.   

    我发现 内部类 真好用。import javax.swing.*;
    import java.awt.*;
    public class Test{    
        public static void main(String[] args){       
    TestFrame frame = new TestFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
        }}
    class TestFrame extends JFrame{
    private static int paintCount = 0;
    TestFrame(){
    setSize(500,400);
    add(new TestPanel());
    }
    class TestPanel extends JPanel{
    @Override
    public void paintComponent(Graphics g){
    paintCount++;
    setTitle("TestFrame" + paintCount);
    super.paintComponent(g);
    }
    }
    }