java swing不能在java 8更新45中运行吗?

时间:2015-05-10 15:28:59

标签: java swing

以下代码适用于jdk 1.8 update 45和java 1.8 update 31,但不适用于java 1.8 update 45。

程序是一个来回移动的按钮,直到用户按下按钮使其停止并且文本变为“MOVE”。再次按下该按钮时,按钮开始移动,文本变为“STOP”。

在java 8 update 45中,按钮不会开始移动,但文本会发生变化。为什么呢?

package mainpackage;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class mainPanel implements ActionListener {

    JFrame frame1;
    JPanel panel1;
    JButton button = new JButton("STOP");

    boolean buttonPressed = false;
    boolean move = true;
    // 0 = left & 1 = right
    int direction = 1;
    int x = 0;

public static void main(String[] args) {
    new mainPanel().loadGUI();

}    

public void loadGUI() {
    frame1 = new JFrame("Moving button");
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame1.setVisible(true);
    frame1.setSize(300, 58);
    frame1.setResizable(false);

    panel1 = new JPanel(); // Xwidth=294, Yheight=272
    panel1.setSize(300, 30);
    panel1.setLayout(null);
    frame1.add(panel1);

    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    frame1.setLocation(dim.width/2-frame1.getSize().width/2, dim.height/2-frame1.getSize().height/2);

    button.setSize(80, 30); //X, Y
    panel1.add(button);
    button.addActionListener(this);

    while(true) moveButton();


}


public void moveButton() {
    while(move == true) {
        switch(direction) {

            // left
            case 0: {
                while(x > 0) {
                    if(move == false) break;
                    button.setLocation(x, 0);
                    x--;
                    panel1.repaint();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(mainPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                if(buttonPressed == true) {
                    direction = 0;
                    buttonPressed = false;
                } else if(buttonPressed == false) {
                    direction = 1;
                    buttonPressed = false;
                }
            }

            // right
            case 1: {
                while(x < panel1.getWidth() - button.getWidth()) {
                    if(move == false) break;
                    button.setLocation(x, 0);
                    x++;
                    panel1.repaint();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(mainPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                if(buttonPressed == true) {
                    direction = 1;
                    buttonPressed=false;
                } else if(buttonPressed == false) {
                    direction=0; 
                    buttonPressed=false;
                }
            }                
        }
    }
}

@Override
public void actionPerformed(ActionEvent e) {
    if (move == true){
        move=false;
    } else if (move == false) {
        move=true;
    }
    buttonPressed = true;
    if((button.getText()).equals("STOP")) {
        button.setText("MOVE");
    } else button.setText("STOP");
} 

}

2 个答案:

答案 0 :(得分:6)

你的代码是破碎的代码,因为它忽略了Swing线程规则,坦率地说,我很惊讶它在以前版本的Java中有效。你正在调用一个while (true)循环,它将占用它所调用的任何线程.Java 8正在尝试在Swing事件线程上启动你的Swing GUI,这是所有Swing程序应该做的事情。如果你摆脱了可能在Swing事件调度线程上调用的while (true)循环,而是使用Swing Timer,那么你的代码应该可行。 Timer将在后台线程中运行一个循环,但是在ActionListener中重复调用的所有代码都将在Swing事件线程上调用。

例如:

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class MyMainPanel extends JPanel {
   private static final int PREF_W = 300;
   private static final int PREF_H = 30;
   private static final int TIMER_DELAY = 20;
   public static final int DELTA_X = 3;
   private JButton moveButton = new JButton(new MoveButtonAction("Move"));
   private Timer moveTimer = new Timer(TIMER_DELAY, new MoveTimerListener());
   private boolean moveRight = true;

   public MyMainPanel() {
      moveButton.setSize(moveButton.getPreferredSize());

      int y = (getPreferredSize().height - moveButton.getPreferredSize().height) / 2;
      moveButton.setLocation(0, y);

      setLayout(null); // !! lord I hate this
      add(moveButton);

      moveTimer.start();
   }

   @Override
   public Dimension getPreferredSize() {
      Dimension superSz = super.getPreferredSize();
      if (isPreferredSizeSet()) {
         return superSz;
      }
      int prefW = Math.max(superSz.width, PREF_W);
      int prefH = Math.max(superSz.height, PREF_H);
      return new Dimension(prefW, prefH);
   }

   private class MoveButtonAction extends AbstractAction {
      public MoveButtonAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         moveRight = !moveRight;
      }
   }

   private class MoveTimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         if (moveRight) {
            if (moveButton.getLocation().x + moveButton.getWidth() >= getWidth()) {
               moveRight = false;
            }
         } else {
            if (moveButton.getLocation().x <= 0) {
               moveRight = true;
            }
         }
         int x = moveButton.getLocation().x + (moveRight ? DELTA_X : -DELTA_X);
         int y = moveButton.getLocation().y;
         moveButton.setLocation(new Point(x, y));
         repaint();
      }
   }

   private static void createAndShowGui() {
      MyMainPanel mainPanel = new MyMainPanel();

      JFrame frame = new JFrame("GUI Example");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

您需要了解Swing线程安全性以了解程序失败的原因。请参阅Lesson: Concurrency in Swing以了解详情。

编辑停止并开始移动的代码:

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

@SuppressWarnings("serial")
public class MyMainPanel extends JPanel {
   private static final String MOVE = "Move";
   private static final String STOP = "Stop";
   private static final int PREF_W = 300;
   private static final int PREF_H = 30;
   private static final int TIMER_DELAY = 20;
   public static final int DELTA_X = 3;
   private MoveButtonAction moveButtonAction = new MoveButtonAction(STOP);
   private JButton moveButton = new JButton(moveButtonAction);
   private Timer moveTimer = new Timer(TIMER_DELAY, new MoveTimerListener());
   private boolean moveRight = true;

   public MyMainPanel() {
      moveButton.setSize(moveButton.getPreferredSize());

      int y = (getPreferredSize().height - moveButton.getPreferredSize().height) / 2;
      moveButton.setLocation(0, y);

      setLayout(null); // !! lord I hate this
      add(moveButton);

      moveTimer.start();
   }

   @Override
   public Dimension getPreferredSize() {
      Dimension superSz = super.getPreferredSize();
      if (isPreferredSizeSet()) {
         return superSz;
      }
      int prefW = Math.max(superSz.width, PREF_W);
      int prefH = Math.max(superSz.height, PREF_H);
      return new Dimension(prefW, prefH);
   }

   private class MoveButtonAction extends AbstractAction {
      public MoveButtonAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (MOVE.equals(getValue(NAME))) {
            moveTimer.start();
            putValue(NAME, STOP);
            int mnemonic = (int) STOP.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
         } else {
            moveTimer.stop();
            putValue(NAME, MOVE);
            int mnemonic = (int) MOVE.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
         }
         AbstractButton button = (AbstractButton) e.getSource();
         button.setSize(button.getPreferredSize());
         repaint();
      }
   }

   private class MoveTimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         if (moveRight) {
            if (moveButton.getLocation().x + moveButton.getWidth() >= getWidth()) {
               moveRight = false;
            }
         } else {
            if (moveButton.getLocation().x <= 0) {
               moveRight = true;
            }
         }
         int x = moveButton.getLocation().x + (moveRight ? DELTA_X : -DELTA_X);
         int y = moveButton.getLocation().y;
         moveButton.setLocation(new Point(x, y));
         repaint();
      }
   }

   private static void createAndShowGui() {
      MyMainPanel mainPanel = new MyMainPanel();

      JFrame frame = new JFrame("GUI Example");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

答案 1 :(得分:3)

刚刚添加了一些方法并修复了代码中的一些行,您现在可以尝试一下:

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class mainPanel implements ActionListener {

    JFrame frame1;
    JPanel panel1;
    JButton button = new JButton("START");

    boolean buttonPressed = false;
    boolean move = false;
    Timer timer;
    int direction = 1;
    int x = 0;

    public static void main(String[] args) {
        new mainPanel().loadGUI();

    }

    public void loadGUI() {
        frame1 = new JFrame("Moving button");
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame1.setVisible(true);
        frame1.setSize(300, 58);
        frame1.setResizable(false);

        panel1 = new JPanel(); // Xwidth=294, Yheight=272
        panel1.setSize(300, 30);
        panel1.setLayout(null);
        frame1.add(panel1);

        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        frame1.setLocation(dim.width / 2 - frame1.getSize().width / 2, dim.height / 2 - frame1.getSize().height / 2);

        button.setSize(80, 30); //X, Y
        panel1.add(button);
        button.addActionListener(this);

        moveButton();

    }

    public void moveButton() {
        if (timer == null) {
            initTimer();
        }
        move = !move;
        if (move) {
            button.setText("STOP");
            direction = (direction == 0) ? 1 : 0;
            timer.start();
        } else {
            button.setText("MOVE");
            timer.stop();
        }
    }

    public void initTimer() {
        timer = new Timer(10, (e) -> {
            switch (direction) {
                case 0: // right
                    x++;
                    if (x >= panel1.getWidth() - button.getWidth()) {
                        direction = 1;
                    }
                    break;
                case 1: // left
                    x--;
                    if (x <= 0) {
                        direction = 0;
                    }
                    break;
            }
            button.setLocation(x, 0);
            panel1.repaint();
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        moveButton();
    }
}