java - java swing 不能在 java 8 update 45 中工作吗?

标签 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");
} 

}

最佳答案

您的代码一开始就是损坏的代码,因为它忽略了 Swing 线程规则,坦率地说,我很惊讶它在以前版本的 Java 中也能工作。您正在调用一个 while (true) 循环,该循环将绑定(bind)调用它的任何线程。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();
         }
      });
   }
}

关于java - java swing 不能在 java 8 update 45 中工作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30153190/

相关文章:

java - 用正则表达式测试字符串?

java - 在 Weka Java API 中创建字符串属性

java - 在 UML 类图中表示 swing 组件

java - 在 Eclipse 中导入现有的 Java 项目,但 JFrame 的设计 View 不存在?

java - 如何使用子类中的 Action 监听器从父类(super class)中的 JPanel 中删除所有元素?

java - 在保留键盘快捷键的同时更改 JOptionPane.YES_NO_OPTION 的默认值?

java - 使用 Optional wrapper 对多个条件进行 OR

java - 将数据插入新的 Google 工作表

java - 重载paintComponent()

java - Spring Boot 的 Spring Security 默认凭据是什么?