调整JFrame大小后多次执行actionPerformed()

时间:2012-11-09 08:04:00

标签: java swing jframe actionlistener

似乎在我的应用程序中,单击JButton时执行方法的次数与我调整JFrame的大小相关。在下面的示例中,当我启动应用程序并且根本不调整大小时,方法addPanel(Dimension dim)将执行2次。调整大小一次,甚至更多。这怎么解释? ResizeController对此有影响吗? (已经说明的线条涉及另外两个“屏幕”,在这种情况下并不重要)。

Start.java

public class Start {

    public static void main(String[] arg){

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new GroundFrame(Toolkit.getDefaultToolkit().getScreenSize());
            }
        });

    }
}

GroundFrame.java

public class GroundFrame extends JFrame{

    public static final long    serialVersionUID = 55;
    private Container           contentPane;
    public static Flyer         screenFlyer;
    public static Points        screenPoints;
    public static Sponsoren     screenSponsoren;
    public static JFrame        parent;

    public GroundFrame(Dimension screenDimension){
        createAndShowGUI(screenDimension);
        setVisible(true);
    }

    private void createAndShowGUI(Dimension screenDimension){
        setExtendedState(JFrame.MAXIMIZED_BOTH); 

        parent = this;

        contentPane = getContentPane();
        contentPane.setLayout(null);

        //screenFlyer = new Flyer(screenDimension);
        //screenSponsoren = new Sponsoren(screenDimension);
        //screenSponsoren.setVisible(false);
        screenPoints = new Points(screenDimension);
        //screenPoints.setVisible(false);

        ResizeController controller = new ResizeController();
        controller.start();

        //contentPane.add(screenFlyer);
        //contentPane.add(screenSponsoren);
        contentPane.add(screenPoints);
    }

    public static void exit(){
        System.exit(0);
    }
}

Points.java

public class Points extends JPanel{

    public static final long            serialVersionUID = 55;

    private JButton                     buttonNext, buttonExit, buttonAdd;
    private JLabel                      copyright;

    private Vector<PlayerPointsPanel>   panels = new Vector<PlayerPointsPanel>();
    final Color                         BACKGROUND_COLOR = new Color(60,60,60);                         
    private int                         pressed = 0;


    public Points(Dimension screenDimension){
        setLayout(null);
        setBackground(BACKGROUND_COLOR);
        setPreferredSize(screenDimension);
        initialize(screenDimension);
        setupElements(screenDimension);
    }

    private void initialize(Dimension dim){
        copyright = new JLabel("\u00a9 by Valentino Rugolo (2012)", SwingConstants.CENTER);
        buttonAdd = new JButton("+");
        buttonNext = new JButton("");
        buttonExit = new JButton("X");
        /*for(int i=0; i<8; i++){
            PlayerPointsPanel panel = new PlayerPointsPanel(dim, i);
            add(panel);
            panels.add(panel);
        }*/
    }

    private void setupElements(Dimension dim){
        setBounds(0,0,dim.width, dim.height);
        setLayout(null);
        dimensionCP = dim;

        copyright.setBounds((int)(dim.width*0.82), (int)(dim.height*0.9), (int)(dim.width*0.15), (int)(dim.height*0.05));
        copyright.setFont(new Font("Times New Roman", Font.PLAIN, (int)(dim.height*0.017)));
        copyright.setForeground(Color.white);

        buttonNext.setBounds((int)(dim.width*0.01), (int)(dim.height*0.9), (int)(dim.width*0.04), (int)(dim.height*0.04));
        buttonNext.setBackground(Color.DARK_GRAY);
        buttonNext.setForeground(Color.white);
        buttonNext.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                GroundFrame.screenPoints.setVisible(false);
                GroundFrame.screenFlyer.setVisible(true);
            }
        });

        buttonExit.setBackground(Color.DARK_GRAY);
        buttonExit.setForeground(Color.white);
        buttonExit.setBounds((int)(dim.width*0.95), (int)(dim.height*0.01), (int)(dim.width*0.04), (int)(dim.height*0.04));
        buttonExit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                GroundFrame.exit();
            }
        });

        buttonAdd.setBackground(Color.DARK_GRAY);
        buttonAdd.setForeground(Color.white);
        buttonAdd.setBounds((int)(dim.width*0.01), (int)(dim.height*0.01), (int)(dim.width*0.04), (int)(dim.height*0.04));
        buttonAdd.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg1) {
                System.out.println("pressed " + pressed);
                pressed++;  
            }
        });

        add(buttonExit);
        add(buttonNext);
        add(copyright);
        add(buttonAdd);
    }

    public void resizeContent(Dimension dim){
        /*for(int i=0; i<panels.size(); i++){
            panels.elementAt(i).resizeContent(dim, i);
        }*/
        setupElements(dim);
    }
}

ResizeController.java

public class ResizeController extends Thread{

    public int sizebeforeX = GroundFrame.parent.getWidth();
    public int sizebeforeY = GroundFrame.parent.getHeight();

    public ResizeController(){

    }

    public void run(){
        while(true){

            int actualX = GroundFrame.parent.getWidth();
            int actualY = GroundFrame.parent.getHeight();

            if(sizebeforeX != actualX || sizebeforeY != actualY){
                //GroundFrame.screenFlyer.resizeContent(GroundFrame.parent.getSize());
                GroundFrame.screenPoints.resizeContent(GroundFrame.parent.getSize());
                //GroundFrame.screenSponsoren.resizeContent(GroundFrame.parent.getSize());
                sizebeforeX = actualX;
                sizebeforeY = actualY;
            }

            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:4)

每当你调整帧的内容时,你都会调用setupElements(),它会一次又一次地向按钮添加监听器。 只需移动在框架的initialize()方法中添加侦听器的代码。

答案 1 :(得分:4)

  1. (这就是为什么......)使用ComponentListener

  2. 的原因
  3. 最安全的方式是实现ComponentListener

  4. 覆盖其方法componentResized(ComponentEvent e)or

  5. 此方法中的
  6. 以小型javax.swing.Timer开始350-500ms

  7. 如果调整大小仍然继续调用Timer#restart()

  8. Swing Action

  9. 的输出添加Swing Timer
  10. 删除Thread.sleep(int),在调整大小期间导致闪烁或冻结

  11. 所有上述代码都可以替换为正确的Layout ManagerGridBagLayout或自定义(和今天)MigLayout