0

我的程序运行并成功绘制了谢尔宾斯基三角形。然而,它只出现片刻,然后就消失了。为什么是这样?

这是我的程序(2 节课)。这是完全可编译和可运行的。

三角面板.java

    import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;

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

public class TrianglePanel extends JPanel {

    int level = 2;
    int width;
    int height;
    Graphics g;

    public static void main(String[] agrs) {
    TrianglePanel panel = new TrianglePanel();
    JFrame frame = new JFrame();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(new Dimension(400, 400));
    frame.setLocationRelativeTo(null);

    frame.add(panel);

    frame.setVisible(true);
    }

    public TrianglePanel() {

    }

    public void paintComponent(Graphics g) {

    this.g = g;

    width = this.getSize().width;
    height = this.getSize().height;

    ArrayList<Line> queue = new ArrayList<Line>();

    queue.add(new Line(new Point(width / 2, 0), new Point(0, height)));
    queue.add(new Line(new Point(0, height), new Point(width, height)));
    queue.add(new Line(new Point(width, height), new Point(width / 2, 0)));

    drawLine(queue.get(0));
    drawLine(queue.get(1));
    drawLine(queue.get(2));

    int counter = 0;

    while (true) {
        if (level > 6) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        break;
        }

        Line[] toDraw = queue.get(0).getTriangleToDraw(level, width, height);

        Point[] toDrawPoints = toDraw[0].getPoints();

        if (Math.sqrt(((Math.pow(toDrawPoints[1].x - toDrawPoints[0].x, 2)) + (Math.pow(toDrawPoints[1].y - toDrawPoints[0].y, 2)))) <= 4) {
        System.out.println("breakyo");
        break;
        }

        drawLine(toDraw[0]);
        drawLine(toDraw[1]);
        drawLine(toDraw[2]);

        queue.remove(0);

        queue.add(toDraw[0]);
        queue.add(toDraw[1]);
        queue.add(toDraw[2]);

        counter++;

        System.out.println(counter + " and " + level);

        if (counter - Math.pow(3, level - 1) == 0) {
        counter = 0;
        level++;
        }

    }
    }

    private void drawLine(Line line) {
    g.drawLine(line.getPoints()[0].x, line.getPoints()[0].y, line.getPoints()[1].x, line.getPoints()[1].y);
    }
}

线.java

import java.awt.Point;

public class Line {

    private Point endpoint1;
    private Point endpoint2;
    private Point midpoint;
    private double slope;

    public Line(Point endpoint1, Point endpoint2) {
    this.endpoint1 = endpoint1;
    this.endpoint2 = endpoint2;

    midpoint = new Point((endpoint1.x + endpoint2.x) / 2, (endpoint1.y + endpoint2.y) / 2);
    slope = (double) (endpoint2.y - endpoint1.y) / (double) (endpoint2.x - endpoint1.x);

    }

    public Point[] getPoints() {
    return new Point[] { endpoint1, endpoint2 };
    }

    public Line[] getTriangleToDraw(int level, int width, int height) {

    Line[] lines = new Line[3];

    if (slope > 0) { //negative slope
        Point left = new Point(midpoint.x - (width / (int)(Math.pow(2, level - 1))), midpoint.y);
        Point middle = new Point(midpoint.x - (width / (int)(Math.pow(2, level))), midpoint.y + (height / (int)(Math.pow(2, level - 1))));

        lines[0] = new Line(midpoint, left);
        lines[1] = new Line(midpoint, middle);
        lines[2] = new Line(middle, left);
    }

    else if (slope < 0) { // positive slope
        Point right = new Point(midpoint.x + (width / (int)(Math.pow(2, level - 1))), midpoint.y);
        Point middle = new Point(midpoint.x + (width / (int)(Math.pow(2, level))), midpoint.y + (height / (int)(Math.pow(2, level - 1))));

        lines[0] = new Line(midpoint, right);
        lines[1] = new Line(midpoint, middle);
        lines[2] = new Line(middle, right);
    }

    else { //zero slope
        Point left = new Point(midpoint.x - (width / (int)(Math.pow(2, level))), midpoint.y - (height / (int)(Math.pow(2, level - 1))));
        Point right = new Point(midpoint.x + (width / (int)(Math.pow(2, level))), midpoint.y - (height / (int)(Math.pow(2, level - 1))));

        lines[0] = new Line(midpoint, left);
        lines[1] = new Line(midpoint, right);
        lines[2] = new Line(left, right);
    }

    return lines;
    }
}
4

2 回答 2

3

这采用了类似于@Hovercraft 建议的方法,但将替换SwingWorker为 a Timer,而不是为标签设置新图标,而是调用repaint().

部分分形图

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.util.ArrayList;

public class TrianglePanel extends JPanel {

    int level = 2;
    int width;
    int height;
    Timer timer;
    BufferedImage canvas;
    JLabel label;

    public static void main(String[] agrs) {
        TrianglePanel panel = new TrianglePanel();
        JFrame frame = new JFrame();

        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationByPlatform(true);

        frame.add(panel);
        frame.pack();

        frame.setVisible(true);

    }

    public TrianglePanel() {
        final int width = 400;
        final int height = 400;
        canvas = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        label = new JLabel(new ImageIcon(canvas));
        add( label );
        final Graphics2D g = canvas.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(255,127,0));

        final ArrayList<Line> queue = new ArrayList<Line>();

        queue.add(new Line(new Point(width / 2, 0), new Point(0, height)));
        queue.add(new Line(new Point(0, height), new Point(width, height)));
        queue.add(new Line(new Point(width, height), new Point(width / 2, 0)));

        drawLine(queue.get(0),g);
        drawLine(queue.get(1),g);
        drawLine(queue.get(2),g);

        ActionListener al = new ActionListener() {
            int counter = 0;

            public void actionPerformed(ActionEvent ae) {
                if (level > 6) {
                    timer.stop();
                    return;
                }

                Line[] toDraw = queue.get(0).getTriangleToDraw(level, width, height);

                Point[] toDrawPoints = toDraw[0].getPoints();

                if (Math.sqrt(((Math.pow(toDrawPoints[1].x - toDrawPoints[0].x, 2)) + (Math.pow(toDrawPoints[1].y - toDrawPoints[0].y, 2)))) <= 4) {
                    System.out.println("breakyo");
                    return;
                }

                drawLine(toDraw[0],g);
                drawLine(toDraw[1],g);
                drawLine(toDraw[2],g);

                queue.remove(0);

                queue.add(toDraw[0]);
                queue.add(toDraw[1]);
                queue.add(toDraw[2]);

                counter++;

                System.out.println(counter + " and " + level);

                if (counter - Math.pow(3, level - 1) == 0) {
                    counter = 0;
                    level++;
                }
                label.repaint();
            }
        };
        timer = new Timer(20,al);
        timer.start();
    }

    private void drawLine(Line line, Graphics g) {
        g.drawLine(line.getPoints()[0].x, line.getPoints()[0].y, line.getPoints()[1].x, line.getPoints()[1].y);
    }
}

class Line {

    private Point endpoint1;
    private Point endpoint2;
    private Point midpoint;
    private double slope;

    public Line(Point endpoint1, Point endpoint2) {
        this.endpoint1 = endpoint1;
        this.endpoint2 = endpoint2;

        midpoint = new Point((endpoint1.x + endpoint2.x) / 2, (endpoint1.y + endpoint2.y) / 2);
        slope = (double) (endpoint2.y - endpoint1.y) / (double) (endpoint2.x - endpoint1.x);

        }

        public Point[] getPoints() {
        return new Point[] { endpoint1, endpoint2 };
    }

    public Line[] getTriangleToDraw(int level, int width, int height) {

        Line[] lines = new Line[3];

        if (slope > 0) { //negative slope
            Point left = new Point(midpoint.x - (width / (int)(Math.pow(2, level - 1))), midpoint.y);
            Point middle = new Point(midpoint.x - (width / (int)(Math.pow(2, level))), midpoint.y + (height / (int)(Math.pow(2, level - 1))));

            lines[0] = new Line(midpoint, left);
            lines[1] = new Line(midpoint, middle);
            lines[2] = new Line(middle, left);
        }

        else if (slope < 0) { // positive slope
            Point right = new Point(midpoint.x + (width / (int)(Math.pow(2, level - 1))), midpoint.y);
            Point middle = new Point(midpoint.x + (width / (int)(Math.pow(2, level))), midpoint.y + (height / (int)(Math.pow(2, level - 1))));

            lines[0] = new Line(midpoint, right);
            lines[1] = new Line(midpoint, middle);
            lines[2] = new Line(middle, right);
        }

        else { //zero slope
            Point left = new Point(midpoint.x - (width / (int)(Math.pow(2, level))), midpoint.y - (height / (int)(Math.pow(2, level - 1))));
            Point right = new Point(midpoint.x + (width / (int)(Math.pow(2, level))), midpoint.y - (height / (int)(Math.pow(2, level - 1))));

            lines[0] = new Line(midpoint, left);
            lines[1] = new Line(midpoint, right);
            lines[2] = new Line(left, right);
        }

        return lines;
    }
}
于 2013-05-01T04:37:40.900 回答
2

您的代码有一些严重的 Swing 线程问题。为了解决这个问题,你真的应该在Event Dispatch Thread (EDT) 中绘制一个 BufferedImage,然后在 EDT 上完成后显示图像。从 BufferedImage 中获取您的 Graphics 对象。我会在SwingWorker<BufferedImage, Void>. 或者,如果您需要显示临时图像,那么SwingWorker<BufferedImage, BufferedImage>

于 2013-05-01T02:48:27.327 回答