Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用paintComponent()执行多线程?_Java_Multithreading_Swing_Graphics2d - Fatal编程技术网

Java 如何使用paintComponent()执行多线程?

Java 如何使用paintComponent()执行多线程?,java,multithreading,swing,graphics2d,Java,Multithreading,Swing,Graphics2d,我创建了一个应用程序,其中包含一个正方形,每当它接触到框架边缘时都会反弹。我在应用程序中没有问题,问题是我不知道如何创建不同的线程,以便在框架中有多个正方形。 我尝试了多种方法,但我不知道应该在哪里创建线程。 我还注意到,只有当我将正方形直接添加到框架中时,它才可见,而当我将其放入JPanel中时,它不可见 Square.java public class Square extends JComponent implements ActionListener { int width = 2

我创建了一个应用程序,其中包含一个正方形,每当它接触到框架边缘时都会反弹。我在应用程序中没有问题,问题是我不知道如何创建不同的线程,以便在框架中有多个正方形。 我尝试了多种方法,但我不知道应该在哪里创建线程。 我还注意到,只有当我将正方形直接添加到框架中时,它才可见,而当我将其放入JPanel中时,它不可见

Square.java

public class Square extends JComponent implements ActionListener {

  int width = 20;
  int height = 20;
  double y = Math.random() * 360;
  double x = Math.random() * 360;
  boolean xMax = false;
  boolean yMax = false;
  boolean xMin = true;
  boolean yMin = true;
  Rectangle2D.Double square = new Rectangle2D.Double(x, y, width, height);

  public Square() {
    Timer t = new Timer(2, this);
    t.start();
  }

  public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    super.paintComponent(g);
    g2.setColor(Color.BLUE);
    g2.fill(square);

    x_y_rules();


  }
  public void x_y_rules() {
    if (xMax == true) {
        x = x - 0.5;
        if (x <= 0) {
            xMax = false;
        }
    } else {
        x = x + 0.5;
        if (x >= this.getWidth()) {
            xMax = true;
        }
    }
    if (yMax == true) {
        y = y - 0.5;
        if (y <= 0) {
            yMax = false;
        }
    } else {
        y = y + 0.5;
        if (y >= this.getHeight()) {
            yMax = true;
        }
    }
    square.setFrame(x, y, width, height);
  }

 @Override
 public void actionPerformed(ActionEvent arg0) {
    repaint();
 }
}
尽管我在计时器中设置了时间2,但正方形移动非常缓慢,这正常吗?

问题:

  • 在paintComponent方法内部有程序逻辑,即
    x\u y\u rules()
    方法调用。把它拿出来,因为它不属于那里,而是把它放在计时器的ActionListener代码中它属于的地方
  • 如果你愿意,你可以给每个方块自己的摆动计时器。这实际上不是线程问题,因为每个计时器的ActionListener都将在EDT上运行
  • 在Swing计时器中使用两毫秒是一个不切实际的时间片,没有计时器会运行得那么快。11到13是最快的期望或希望
  • 如果您想让精灵移动得更快,请在移动代码中为其指定更大的delta-x和delta-y值
  • 您的JComponent没有定义首选大小,这可能是它没有显示在JPanel中的原因,因为默认的FlowLayout会将其大小调整为[0,0]。重写它的
    getPreferredSize()
    ,并让它返回一个合理的维度值
  • 在添加所有组件之前,您正在JFrame上调用
    setVisible(true)
    ,这是一个禁忌

  • 好的,我在square类中放置了一个getPreferedSize(),但我遇到了一个问题:这些正方形不是“在一起”,就像它们在单独的面板上反弹一样

    那么你的程序结构就被破坏了。您确实不想创建单独的Swing组件,事实上,您的Square类不应该扩展JComponent或JPanel。相当于

    • Square应该是一个逻辑类,一个从零扩展而来的类(默认对象除外)
    • 给它一个绘图方法,比如说
      publicsvoiddraw(graphicsg){….}
    • 创建一个扩展JPanel的类,比如称为
      DrawingPanel
      ,并重写其paintComponent方法
    • 为DrawingPanel类指定一个
      ArrayList
      ,以便它可以容纳多个方形对象
    • 给DrawingPanel类一个摆动计时器
    • 在DrawingPanel类的计时器中,让它更新ArrayList中所有正方形的位置,然后调用
      repaint()
    • 在paintComponent方法中,使用for循环遍历列表中的所有正方形,并调用每个正方形的draw方法
    例如:

    导入java.awt.Color;
    导入java.awt.Dimension;
    导入java.awt.Graphics;
    导入java.awt.Image;
    导入java.awt.event.ActionEvent;
    导入java.awt.event.ActionListener;
    导入java.awt.image.buffereImage;
    导入java.util.ArrayList;
    导入java.util.List;
    导入javax.swing.*;
    @抑制警告(“串行”)
    公共类DrawingPanel扩展了JPanel{
    专用静态最终整型预调W=600;
    私有静态final int PREF_H=PREF_W;
    专用静态最终int定时器_延迟=20;
    私有静态最终颜色[]方形颜色={Color.BLUE,Color.CYAN,Color.DARK\u GRAY,
    颜色。黑色,颜色。灰色,颜色。绿色,颜色。浅灰色,颜色。洋红,颜色。橙色,
    Color.PINK、Color.RED、Color.YELLOW};
    List squareList=新的ArrayList();
    公共绘图面板(){
    //创建一组正方形
    对于(int i=0;icreateAndShowGui());
    }
    }
    //此类*不*扩展JPanel或JComponent
    阶级广场{
    公共静态最终整数宽度=20;
    //广场位置
    私人双sqrX;
    私人双平方米;
    //X和Y速度
    私人双重征税;
    私人双三角酒店;
    //绘图板JPanel的宽度和高度
    私有int-dpWidth;
    私人室内高度;
    //要绘制的图像
    私有图像;
    公共广场(彩色、int-dpWidth、int-dpHeight){
    this.dpWidth=dpWidth;
    this.dpHeight=dpHeight;
    //以随机速度在随机位置创建正方形
    sqrX=Math.random()*(dpWidth-WIDTH);
    sqrY=Math.random()*(dpHeight-WIDTH);
    deltaX=Math.random()*10-5;
    判定元件
    
    public class App extends JFrame {
    
    public static void main(String[] args) {
        JFrame jf = new JFrame();
        Square sqr = new Square();
        jf.setSize(400, 400);
        jf.setVisible(true);
        jf.add(sqr);
        jf.setDefaultCloseOperation(EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
     }
    }
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class DrawingPanel extends JPanel {
        private static final int PREF_W = 600;
        private static final int PREF_H = PREF_W;
        private static final int TIMER_DELAY = 20;
        private static final Color[] SQUARE_COLOR = { Color.BLUE, Color.CYAN, Color.DARK_GRAY,
                Color.BLACK, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
                Color.PINK, Color.RED, Color.YELLOW };
        List<Square> squareList = new ArrayList<>();
    
        public DrawingPanel() {
            // create a bunch of squares
            for (int i = 0; i < SQUARE_COLOR.length; i++) {
                squareList.add(new Square(SQUARE_COLOR[i], PREF_W, PREF_H));
            }
    
            setBackground(Color.WHITE);
    
            // create and start the timer
            new Timer(TIMER_DELAY, new TimerListener()).start();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
    
            // simply draw all the squares in the list
            for (Square square : squareList) {
                square.draw(g);
            }
        }
    
        // set size of JPanel
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    
        private class TimerListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {            
                // simply iterate through list and move all squares
                for (Square square : squareList) {
                    square.move();
                }
                repaint(); // then repaint the GUI
            }
        }
    
        private static void createAndShowGui() {
            DrawingPanel mainPanel = new DrawingPanel();
    
            JFrame frame = new JFrame("Drawing Panel");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    
    // this class does *not* extend JPanel or JComponent
    class Square {
        public static final int WIDTH = 20;
    
        // location of Square
        private double sqrX;
        private double sqrY;
    
        // X and Y speed
        private double deltaX;
        private double deltaY;
    
        // width and height of DrawingPanel JPanel
        private int dpWidth;
        private int dpHeight;
    
        // image to draw
        private Image image;
    
        public Square(Color color, int dpWidth, int dpHeight) {
            this.dpWidth = dpWidth;
            this.dpHeight = dpHeight;
    
            // create square at random location with random speed
            sqrX = Math.random() * (dpWidth - WIDTH);
            sqrY = Math.random() * (dpHeight - WIDTH);
            deltaX = Math.random() * 10 - 5;
            deltaY = Math.random() * 10 - 5;
    
            // one way to draw it is to create an image and draw it
            image = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_INT_ARGB);
            Graphics g = image.getGraphics();
            g.setColor(color);
            g.fillRect(0, 0, WIDTH, WIDTH);
            g.dispose();
        }
    
        public void move() {
    
            // check that we're not hitting boundaries
            if (sqrX + deltaX < 0) {
                deltaX = Math.abs(deltaX);
            }
            if (sqrX + deltaX + WIDTH >= dpWidth) {
                deltaX = -Math.abs(deltaX);
            }
            sqrX += deltaX;
    
            // check that we're not hitting boundaries
            if (sqrY + deltaY < 0) {
                deltaY = Math.abs(deltaY);
            }
            if (sqrY + deltaY + WIDTH >= dpHeight) {
                deltaY = -Math.abs(deltaY);
            }
            sqrY += deltaY;
    
        }
    
        public void draw(Graphics g) {
            int x = (int) sqrX;
            int y = (int) sqrY;
            g.drawImage(image, x, y, null);
        }
    }