且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

计时器 t = 新计时器(50, b);停止();不管用

更新时间:2023-12-04 08:38:04

您的代码非常复杂,我相信它受到了名为 圈复杂度,如此之多,您或我们很难看到什么对象正在创建什么其他对象,什么正在运行什么.这是你的问题.您至少有两个 MultipleBall 对象、两个 Ball2 对象,并且您正在为一个 Ball2 对象启动 Timer,并为另一个对象停止它.

Your code is extremely convoluted, I believe that it's suffering from something called cyclomatic complexity, so much so, it is difficult for you or us to see what object is creating what other object, and what is running what. And this is your problem. You have at least two MultipleBall objects, two Ball2 objects, and you're starting the Timer for one of the Ball2 objects and stopping it for the other.

解决办法:大大简化这段代码.

The solution: simplify this code greatly.

  • 创建一个 MultipleBalls 对象,只有一个.
  • 不要让 MultipleBalls 实现 ActionListener.而是为您的 ActionListener 使用匿名内部类,并在您需要的地方创建它.
  • 只创建一个 Ball2 对象,就一个.

另请注意,您几乎从未在 Thread 对象上调用 run() 而是 start(),但话虽如此,我什至不确定您应该在您使用它的地方使用 Thread 对象.

Also note that you almost never call run() on a Thread object but rather start(), but having said that, I'm not even sure that you should be using a Thread object where you're using it.

编辑
我的主类很简单,只有一个主要方法和支持方法来开始工作.类似的东西:

Edit
My main class would be simple, and would simply have a main method and supporting method that gets things started. Something like:

public class MultipleBalls {

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

      JFrame frame = new JFrame("Multiple Balls");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

编辑

关注点分离的例子:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.*;

public class MultipleBallsZ {

   private static void createAndShowGui() {
      BallsPanelZ ballsPanel = new BallsPanelZ();
      new Control(ballsPanel);

      JFrame frame = new JFrame("Multiple Balls");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(ballsPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

@SuppressWarnings("serial")
class BallsPanelZ extends JPanel {
   private static final int TIMER_DELAY = 200;
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;

   private Timer timer = new Timer(TIMER_DELAY, new TimerListener());
   private int counter = 0;
   private Control control = null;

   public BallsPanelZ() {
      timer.start();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public Timer getTimer() {
      return timer;
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         counter++;
         System.out.printf("Count: %03d%n", counter);
      }
   }

   public void setControl(Control control) {
      this.control = control;
      for (Action action : control) {
         add(new JButton(action));
      }
   }
}

@SuppressWarnings("serial")
class Control implements Iterable<Action> {
   private List<Action> actionList = new ArrayList<>();
   private BallsPanelZ ballsPanel;

   public Control(BallsPanelZ ballsPanel) {
      actionList.add(new PauseAction());
      actionList.add(new ResumeAction());

      this.ballsPanel = ballsPanel;
      ballsPanel.setControl(this);
   }

   private class PauseAction extends AbstractAction {
      public PauseAction() {
         super ("Timer Pause");
         putValue(MNEMONIC_KEY, KeyEvent.VK_P);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         ballsPanel.getTimer().stop();
      }
   }

   private class ResumeAction extends AbstractAction {
      public ResumeAction() {
         super("Timer Resume");
         putValue(MNEMONIC_KEY, KeyEvent.VK_R);
         putValue(DISPLAYED_MNEMONIC_INDEX_KEY, 6);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         ballsPanel.getTimer().restart();
      }
   }

   @Override
   public Iterator<Action> iterator() {
      return actionList.iterator();
   }
}