用Java绘制Sierpinski的三角形

时间:2013-05-08 06:41:34

标签: java swing graphics geometry awt

我的代码存在一些问题,无法绘制Sierpinski的三角形(或Sierpinski的垫片),但我不确定问题是什么。绘制三角形的线条,然后绘制所有分形线,然后消失。帮助

import javax.swing.*;
import java.awt.*;

public class SierpinskiGasket extends JFrame {

Point x=new Point(5,545),
      y=new Point(300,25),
      z=new Point(605,545),
      current=x, target;
private int count=0;

public SierpinskiGasket () {
    super("Sierpinski Gasket");
    setSize(610,550);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    getContentPane().setBackground(Color.WHITE);
    setLocationRelativeTo(null);
    setResizable(false);
    setVisible(true);
}

public void paint(Graphics g) {
    super.paint(g);
    if(count==0) {
    g.drawLine(x.x,x.y,y.x,y.y);
    g.drawLine(x.x,x.y,z.x,z.y);
    g.drawLine(z.x,z.y,y.x,y.y);
    } else {
        while(count<10000) {
            int choice=(int)(Math.random()*3);
            switch(choice) {
                case 0: target=x; break;
                case 1: target=y; break;
                case 2: target=z; break;
                default: System.exit(0);
            }
            current=midpoint(current,target);
            g.drawRect(current.x,current.y,5,5);
            repaint();
            count++;
        }
    }
    count++;
}

public Point midpoint(Point a, Point b) {
    return new Point((Math.round(a.x+b.x)/2),
                     (Math.round(a.y+b.y)/2));
}

public static void main(String[] args) {
    new SierpinskiGasket();
}
}

3 个答案:

答案 0 :(得分:6)

  1. 不要从顶级容器(例如JFrame)延伸,您不会添加任何有益的东西。
  2. 避免油漆到顶层容器。而是使用JPanel之类的东西。
  3. 避免覆盖paint,请改用paintComponent。有关详细信息,请参阅Performing Custom Painting
  4. 这不是绘画的工作原理(我不会尝试重写你的代码来制作它)。

    当重绘系统决定需要更新部分或全部UI时,将调用Paint以响应许多事件。油漆是破坏性的,也就是说,当调用油漆时,Graphics将被完全刷新,要求您从头开始“重建”输出。

    相反。

    编写一个递归算法,可以绘制BufferedImage之类的内容并在paintComponent ...中绘制...

    <强>更新

    Swing中的绘画由RepaintManager控制,是否有责任确定重绘屏幕的内容和时间。你似乎认为paint是你可以控制的东西,当它不是时。

    您需要准备完全重新绘制UI或准备好可以根据需要在UI上绘制的缓冲区。

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.Path2D;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class SierpinskisGasket {
    
        public static void main(String[] args) {
            new SierpinskisGasket();
        }
    
        public SierpinskisGasket() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                BaseShape base = new BaseShape(Math.min(getWidth(), getHeight()));
                Rectangle bounds = base.getBounds();
                int x = (getWidth() - bounds.width) / 2;
                int y = (getHeight() - bounds.height) / 2;
                base.transform(AffineTransform.getTranslateInstance(x, y));
                g2d.fill(base);
                g2d.dispose();
            }
        }
    
        public class BaseShape extends Path2D.Float {
    
            public BaseShape(float size) {
    
                float subSize = size / 2f;
                Triangle top = new Triangle(subSize);
                top.transform(AffineTransform.getTranslateInstance((size - subSize) / 2, 0));
                append(top, false);
    
                Triangle left = new Triangle(subSize);
                left.transform(AffineTransform.getTranslateInstance(0, subSize));
                append(left, false);
    
                Triangle right = new Triangle(subSize);
                right.transform(AffineTransform.getTranslateInstance(subSize, subSize));
                append(right, false);
    
            }
    
        }
    
        public class Triangle extends Path2D.Float {
    
            public Triangle(float size) {
    
                moveTo(size / 2f, 0);
                lineTo(size, size);
                lineTo(0, size);
                closePath();
    
            }
    
        }
    
    }
    

    你永远不应该从paint调用可以改变UI状态并触发另一个repaint的任何内容,否则你将最终进入重绘的最终循环,最终会消耗你的CPU。

    您还应该查看Painting in AWT and Swing

答案 1 :(得分:1)

int i = ((int)Math.random()*3);    
System.out.println("i:"+i);

当我运行上述内容时,我总是得到0

所以你的“选择”变量总是为零......可能与你的问题有关吗?

答案 2 :(得分:-1)

只需删除repaint()来电就可以修复它。