将圆圈绘制到JFrame

时间:2017-01-18 20:51:56

标签: java swing user-interface graphics jframe

我在向JFrame绘制一些圆圈时遇到问题。我最初使用默认布局,并意识到这只是添加最新的圆,所以我将布局更改为null,现在没有任何东西被绘制。我也尝试了frame.setLayout(new FlowLayout()),但也没有画任何东西。任何帮助将不胜感激!

import java.util.ArrayList;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;

/**
 * @author Christopher Nielson
 *
 */
public class Main {

    private static JFrame frame;
    private static Random rand;
    private static Jiggler jiggler;
    private static ArrayList<JComponent> circles;
    private static int fps;

    public static void main(String[] args) {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setBounds(100, 100, 450, 450);

        rand = new Random();
        circles = new ArrayList<JComponent>();

        int x = frame.getWidth();
        int y = frame.getHeight();

        for (int i = 0; i < Integer.parseInt(args[0]); i++) {
            circles.add(new Circle(rand.nextInt(frame.getWidth()), rand.nextInt(frame.getHeight()), 
                    rand.nextInt(frame.getWidth() / 10) + 100, rand.nextInt(frame.getHeight() / 10) + 100, null));
        }

        circles.forEach(current -> {
            frame.add(current);
        });

        frame.setVisible(true);

        jiggler = new Jiggler(circles, new JLabel("FPS: "));    // TODO add fps
        jiggler.run();
    }
}

1 个答案:

答案 0 :(得分:4)

这就是为什么你会看到我们一次又一次地推荐避免使用瘟疫之类的空布局的原因之一。

话虽如此,你的主要问题是设计问题,而不是布局问题,而问题是你的Circle类不应该扩展JComponent 或任何组件,因为如果你想要绘制多个圆圈,你应该只有一个组件,可能是绘图的JPanel,圆圈应该是逻辑类,具有public void draw(Graphics g)方法的类,而不是组件类。您可以将圆圈列表传递给绘图JPanel,它将通过调用列表中每个圆的draw(g)方法在其paintComponent方法中绘制圆圈。

例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class DrawChit extends JPanel {
    private static final int PREF_W = 900;
    private static final int PREF_H = 700;
    private static final int MAX_SHAPES = 30;
    private List<MyShape> shapes = new ArrayList<>();

    public DrawChit() {
        setBackground(Color.WHITE);

        for (int i = 0; i < MAX_SHAPES; i++) {
            double x = (PREF_W - 100) * Math.random();
            double y = (PREF_H - 100) * Math.random();
            double w = 100 + (Math.random() * PREF_W) / 10;
            double h = 100 + (Math.random() * PREF_H) / 10;
            Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);

            float hue = (float) Math.random();
            double delta = 0.3;
            float saturation = (float) (Math.random() * delta + (1 - delta));
            float brightness = (float) (Math.random() * delta + (1 - delta));
            Color color = Color.getHSBColor(hue, saturation, brightness);
            shapes.add(new MyShape(ellipse, color));
        }

        // we'll throw a black square in the middle!
        int rectW = 200;
        int rectX = (PREF_W - rectW) / 2;
        int rectY = (PREF_H - rectW) / 2;
        shapes.add(new MyShape(new Rectangle(rectX, rectY, rectW, rectW), Color.BLACK));

        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // use anti-aliasing to make graphics smooth
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // iterate through the shapes list, filling all 
        for (MyShape shape : shapes) {
            shape.fill(g2);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class MyMouse extends MouseAdapter {
        private Point p0 = null;
        private MyShape shape = null;

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                return;
            }

            // iterate *backwards* so get top-most Shape
            for (int i = shapes.size() - 1; i >= 0; i--) {
                if (shapes.get(i).contains(e.getPoint())) {
                    p0 = e.getPoint();
                    shape = shapes.get(i);

                    // move selected shape to the top!
                    shapes.remove(shape);
                    shapes.add(shape);

                    repaint();
                    return;
                }
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (p0 != null) {
                moveShape(e.getPoint());
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (p0 != null) {
                moveShape(e.getPoint());
                p0 = null;
                shape = null;
            }
        }

        // translates the shape 
        private void moveShape(Point p1) {
            int deltaX = p1.x - p0.x;
            int deltaY = p1.y - p0.y;
            shape.translate(deltaX, deltaY);
            p0 = p1;
            repaint();
        }
    }

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

        JFrame frame = new JFrame("Draw Chit");
        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());
    }
}

class MyShape {
    private Path2D path = new Path2D.Double();
    private Color color;

    public MyShape(Shape shape, Color color) {
        path.append(shape, true);
        this.color = color;
    }

    public boolean contains(Point p) {
        return path.contains(p);
    }

    public void draw(Graphics2D g2) {
        g2.setColor(color);
        g2.draw(path);
    }

    public void fill(Graphics2D g2) {
        g2.setColor(color);
        g2.fill(path);
    }

    public void translate(int deltaX, int deltaY) {
        path.transform(AffineTransform.getTranslateInstance(deltaX, deltaY));
    }

}