java - 使用java运行风扇

标签 java multithreading swing user-interface

我需要模拟一个正在运行的风扇,有 3 个按钮(启动、反转、停止)和一个滚动条来控制速度。 我写了一个代码,但它们没有错误,但它不起作用。 起初,该类扩展了 Jframe,并且出现了带有按钮和扇形弧的窗口,但是当它扩展了 Japplet 时,它就没有出现。 但这并不是双向的。

package Ass3_10203038;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import  java.awt.Adjustable;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Ass3_10203038 extends JApplet implements Runnable {
private static
    Lock lock = new ReentrantLock();
Graphics fan;
JButton start = new JButton("Start");
JButton stop = new JButton("Stop");
JButton reverse = new JButton("Reverse");
JScrollBar speed = new JScrollBar();
Thread timer = new Thread();
int thr=50;
int strtpt=0;
 JFrame frame= new JFrame();

@Override
public void run() {
    repaint();
    while (true) {
        try {
            Thread.sleep(thr);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

  }

   public Ass3_10203038() {
    final ArcsPanel arcs = new ArcsPanel();

    JPanel p = new JPanel();

    p.setSize(500, 500);
    p.add(arcs);
  //  p.setSize(5000, 5000);
    p.add(start);
    p.add(stop);
    p.add(reverse);
    p.add(speed);
    p.setLayout(new GridLayout());

   frame.add(p);
  add(frame);

   frame.setTitle("Fan");
    start.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent e){
  timer.start();

  for(int x=strtpt;x<362;x++)
 {if(x==361)
 x=0;
 else         
  arcs.initializex(x);
  arcs.paintComponent(fan);
 strtpt=x;
  }   


 }
 });

        stop.addActionListener(new ActionListener(){
 public void actionPerformed(ActionEvent e){

  lock.lock();

   timer.start();

}
});

         reverse.addActionListener(new ActionListener(){
  public void actionPerformed(ActionEvent e){
   timer.start();
    for(int x=strtpt;x>-1;x--)
    {if(x==0)
    x=360;

  else
    arcs.initializex(x);
      arcs.paintComponent(fan);
    strtpt=x;

     }


         }});

            speed.addAdjustmentListener(new AdjustmentListener(){
                    public void adjustmentValueChanged(AdjustmentEvent ae){
                        try {
                            switch (thr){
                                    case AdjustmentEvent.UNIT_INCREMENT:
                                   Thread.sleep( thr+=2);
                                break;

                                    case AdjustmentEvent.UNIT_DECREMENT:
                                      Thread.sleep(thr-=2);
                                        break;
                                            }
                            int value = ae.getValue();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Ass3_10203038.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

            });

    }
   /**
   * Main method
   */
   public static void main(String[] args) {
    Ass3_10203038  window = new Ass3_10203038();

    window.setSize(500, 500);

    window.setLocation(50, 50); // Center the frame
     // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);

   }
  }

 // The class for drawing arcs on a panel
  class ArcsPanel extends JPanel {
   // Draw four blades of a fan

   public int initializex(int x){

  return x;
   }

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    int xCenter = getWidth() / 2;
    int yCenter = getHeight() / 2;
    int radius = (int) (Math.min(getWidth(), getHeight()) * 0.4);


    int x = xCenter - radius;
    int y = yCenter - radius;

    {
        g.fillArc(x, y, 2 * radius, 2 * radius, 0+initializex(x), 30);
        g.fillArc(x, y, 2 * radius, 2 * radius, 90+initializex(x), 30);
        g.fillArc(x, y, 2 * radius, 2 * radius, 180+initializex(x), 30);
        g.fillArc(x, y, 2 * radius, 2 * radius, 270+initializex(x), 30);

    }

  }
   }

最佳答案

这段代码有很多问题,我不会尝试解决所有问题。不过,我将列出我注意到的问题并描述出现的问题。

首先,您的代码因异常而崩溃:

java.lang.IllegalArgumentException: adding a window to a container

这发生在 Ass3_10203038 构造函数中,您尝试将 JFrame 添加到新的 Ass3_10203038 实例(这是一个 JApplet,从而成为一个容器)。由于 JFrame 仅包含 JPanel,因此您可以通过直接将 JPanel 添加到 Ass3_10203038 实例来解决此问题。当作为 Applet 运行时,这至少会显示您的 UI。

接下来,单击按钮将生成 NullPointerException。发生这种情况是因为您直接调用 paintComponent,并传入 fan 作为 Graphics 参数 - 但您从未将 fan 初始化为代码中的任何内容,因此它始终为空。作为解决方案,您不应直接调用 paintComponent,因为您没有Graphics 对象来在屏幕上进行绘制。 。不过,Swing 系统有这个对象,因此我们可以要求它重新绘制,而不是直接调用 paintComponent:

arcs.repaint();

现在,只要按下按钮,程序就会进入无限循环。发生的情况是这个循环永远不会结束:

for (int x = strtpt; x < 362; x++)
{
    if (x == 361)
        x = 0;
    else
        arcs.initializex(x);
    arcs.repaint();
    strtpt = x;
}

它总是保持循环,因为 x 永远不会达到 362。假设您希望风扇连续旋转,这是有道理的,但由于您在 UI 线程上运行此循环,它会卡住整个窗口。除此之外,风扇会非常快速旋转,因为在这个循环中没有计时 - 它会以计算机所能达到的速度运行,这确实非常快。

显然,您试图通过使用名为 timerThread 来解决此问题:

timer.start();

但是,由于 timer 只是一个空白的 Thread 对象,因此这一行绝对不执行任何操作(至少对您的程序没有任何重要作用)。为了在线程中运行代码,您必须扩展 Thread 并重写 run 方法,或者将 Runnable 传递给构造函数线程。然而,我认为原始线程不会让我们到达任何地方,因为它们仍然没有真正解决计时问题。我建议您查看javax.swing.Timer

即使解决了这个问题,您的风扇叶片仍然不会移动。这是因为您的 paintComponent 方法实际上从未将任何角度视为输入。看起来您尝试通过在上面所示的循环和 paintComponent 方法中调用 initializex(x) 来传递角度,但是 initializex除了返回其参数之外,不执行任何操作 - 无论您传入什么,您都会立即返回。因此,在 paintComponent 方法中,initializex(x) 只是返回 x 的值。这意味着您无需编写代码:

g.fillArc(x, y, 2 * radius, 2 * radius, 0 + initializex(x), 30);

你也可以这样写

g.fillArc(x, y, 2 * radius, 2 * radius, 0 + x, 30);

效果完全相同。

我希望这可以解释一些出现的问题。

关于java - 使用java运行风扇,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15509774/

相关文章:

java - java.time 的 Spring DateTimeFormat 配置

java - 我可以使用什么来代替 Java 中的 Vector?

java - 按键绑定(bind)按钮时按钮不显示

java - 如何设置正在运行的应用程序的JProgressbar

C++ 线程 - 在循环中生成一个对象(类)?

java - 如何从jtable中的复选框中获取选中的值?

java - 具有外部属性的 Spring Boot 配置文件

java - 如果我使用 EJB,我是否需要 JPA 提供程序(如 Hibernate)?

java - 格式化 Java 控制台表

java - 使用 Mqtt 订阅者与主类通信