Java在同一JFrame中绘制多个正方形 [英] Java Drawing Multiple Squares in Same JFrame

查看:103
本文介绍了Java在同一JFrame中绘制多个正方形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作多线程动画.我想绘制 n 正方形,其中 n 来自推荐行参数.每个正方形都有其x-y坐标,颜色和速度.它们以不同的速度,颜色和坐标移动到框架的右侧.由于我使用多线程,因此我假设必须控制每个正方形.因此,我必须将每个方形对象存储在ArrayList中.但是,我在画那些正方形时遇到了麻烦.我可以绘制一个正方形,但是当我尝试绘制多个正方形时,它不会显示.这是我到目前为止所做的:

I am trying to make an animation with multiple thread. I want to paint n squares where this n comes from commend-line argument. Every square has their x-y coordinates, colors and speed. They are moving to the right of the frame with different speed, color and coordinates. Since I am using multi thread I assume I have to control each squares. So I have to store each square object in the ArrayList. However, I am having trouble with painting those squares. I can paint one square but when I try to paint multiple squares, it does not show. Here what I have done so far:

DrawSquare.java

import java.awt.Graphics;
import javax.swing.JPanel;

public class DrawSquare extends JPanel {
    public Square square;
    public DrawSquare() {
        square = new Square();
    }

    @Override
    public void paintComponents(Graphics g) {
        // TODO Auto-generated method stub
        super.paintComponents(g);

    }

    @Override
    public void paint(Graphics g) {
        // TODO Auto-generated method stub
        super.paint(g);

        g.setColor(square.getC());
        g.fillRect(square.getX(), square.getY(), square.getR(), square.getR());
    }
}

Square.java

import java.awt.Color;
import java.util.Random;

public class Square {
    private int x,y,r,s;
    private Color c;
    private Random random;

    public Square() {
        random = new Random();
        x = random.nextInt(100) + 30;
        y = random.nextInt(100) + 30;
        r = random.nextInt(50) + 20;
        s = random.nextInt(20) + 5;
        c = new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255));
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getR() {
        return r;
    }

    public int getS() {
        return s;
    }

    public Color getC() {
        return c;
    }
}

Animation.java

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Animation extends JFrame implements Runnable {
    private JPanel panel;
    private DrawSquare square;

    public Animation() {

    }

    public static void main(String[] args) {
        Animation w = new Animation();
        DrawSquare square = new DrawSquare();
        JFrame f = new JFrame("Week 9");
        int n = Integer.parseInt(args[0]);
        f.setVisible(true);
        f.setSize(700,700);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setResizable(false);
        for(int i=0; i<n; i++) {
            f.getContentPane().add(square);
        }
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

    }
}

推荐答案

所以,从...开始.

public class DrawSquare extends JPanel {
    public Square square;
    public DrawSquare() {
        square = new Square();
    }

    @Override
    public void paintComponents(Graphics g) {
        // TODO Auto-generated method stub
        super.paintComponents(g);

    }

    @Override
    public void paint(Graphics g) {
        // TODO Auto-generated method stub
        super.paint(g);

        g.setColor(square.getC());
        g.fillRect(square.getX(), square.getY(), square.getR(), square.getR());
    }
}

作为一般建议,最好将自定义绘画放入 paintComponent 方法中(请注意,结尾没有 s )

As general recommendation, it's preferred to put custom painting in the paintComponent method (note, there's no s at the end)

调用 paint 时,已经将 Graphics 上下文转换为组件坐标位置.这意味着 0x0 是组件的左上角,这也意味着...

When paint is called, the Graphics context has already been translated to the component coordinate position. This means that 0x0 is the top/left corner of the component, this also means that...

g.fillRect(square.getX(), square.getY(), square.getR(), square.getR());

x + x x y + y 上绘制矩形,这至少会在错误的位置绘制矩形,最糟糕的是将其绘制超出了组件的可见范围.

is painting the rect at x + x x y + y, which will, at the very least, paint the rect in the wrong position, at worst paint it beyond the visible scope of the component.

您也没有为组件提供任何尺寸调整提示,因此它的默认大小为 0x0 ,这将阻止其绘制.

You're also not providing any sizing hints for the component, so it's default size will be 0x0, which prevent it from been painted.

由于我使用多线程,因此我假设我必须控制每个正方形.

Since I am using multi thread I assume I have to control each squares.

好吧,因为我真的看不到动画的驱动因素,所以我想当您说多线程"时,您暗示每个正方形都有它自己的线程".在这种情况下,这是个坏主意.让我们暂时搁置线程同步问题,更多的线程并不等于您可以做的更多工作,到某个时候,它将开始降低系统性能.

Well, since I can't really see what's driving the animation, I imagine that when you say "multi thread" you're suggesting that each square has it's own `Thread. In this case, that's a bad idea. Let's put aside the thread synchronisation issues for a moment, more threads doesn't equate to more work you can do, at some point, it will begin to degrade the system performance.

在大多数情况下,您真正​​需要的是一个单一且管理良好的线程.您还必须了解,Swing不是线程安全的.这意味着您不应从事件调度线程的上下文外部更新UI(或声明UI所依赖的状态).

In most cases, a single, well managed thread, is all you really need. You also have to understand that Swing is NOT thread safe. This means that you shouldn't update the UI (or states that the UI relies on) from outside the context of the Event Dispatching Thread.

因此,为什么您要线程可以更新rect的位置,您需要注意确保不会被绘制,以免它们被更新.更新状态后,您需要触发一次绘画过程(本身并不重要)

So, why you're thread can update the position of the rects, you need to take care to ensure that they are not been painted why they are been update. Once you've updated the state, you then need to trigger a paint pass (which is trivial in of itself)

所以我必须将每个正方形对象存储在ArrayList中.

So I have to store each square object in the ArrayList.

是的,好的开始

但是,我在画那些正方形时遇到了麻烦.我可以绘制一个正方形,但是当我尝试绘制多个正方形时,它不会显示.

However, I am having trouble with painting those squares. I can paint one square but when I try to paint multiple squares, it does not show.

好的,所以不要使用多个组件,而要使用一个组件.在此组件的 paintComponent 方法内的 ArrayList 中运行,并为其绘制所有矩形.由于您只需要担心一个容器,因此这提供了一种更简单的方法来管理边界检测之类的事情.

Okay, so instead of using multiple components, use one. Run through your ArrayList within the paintComponent method of this component and paint all the rects to it. This provides a much simpler way to manage things like bounds detection, as you have only one container to worry about.

强烈建议您看看:

  • Java Bouncing Ball which demonstrates many of the concepts discussed here
  • Concurrency in Swing
  • How to use Swing Timers
  • Performing Custom Painting
  • Painting in AWT and Swing

这篇关于Java在同一JFrame中绘制多个正方形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆