所以我必须用Swing创建一个Sierpinski Gasket的实现。 我不能使用递归或三角形。我必须使用以下内容 算法:
选择3个点来定义三角形。
选择其中一个顶点作为当前循环50,000次: 随机选择一个顶点作为目标。 在目标和当前之间的中点绘制一个像素。 使当前成为中点。
在下面的图片中,我有时会在编辑时得到它,但有时它会弹出并消失,或者根本不显示。如果它确实显示,然后我调整窗口大小就会消失(我不关心这个,但如果它有帮助。)我只能在编译时产生下面的图像(大约1/3的时间。)图像下方是我的代码,分为两类。
import java.awt.*;
import javax.swing.JFrame;
public class SierpinskiGasket {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("SierpinskiGasket");
frame.setSize(630,580);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawSierpinski Sierpinski = new drawSierpinski();
frame.add(Sierpinski);
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
public class drawSierpinski extends JPanel{
Point point1 = new Point(10,550),
point2 = new Point(300,30),
point3 = new Point(600,555),
current = point1, target;
private int count = 0;
public void paintComponent(Graphics g){
super.paintComponent(g);
while(count<= 50000){
int choice = (int)(Math.random()*3);
switch(choice){
case 0: target = point1; break;
case 1: target = point2; break;
case 2: target = point3; break;
default: System.exit(0);
}
current = midpoint(current,target);
g.drawLine(current.x,current.y,current.x,current.y);
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));
}
}
我假设它与Swing如何处理多线程有关,但不幸的是我对如何解决它没有太多的了解。非常感谢您的帮助!
答案 0 :(得分:2)
这个循环:
while(count<= 50000) {
// ....
}
可能需要一段时间才能完成,同时它将完全阻止Swing事件线程的最关键点 - 同时绘制。更重要的是,任何琐碎的重绘都会触发循环重新运行,再次完全冻结你的GUI。
解决方案:在paintComponent之外进行绘制。而是创建一个与JPanel大小相同的BufferedImage,获取图像的Graphics对象,在BufferedImage中绘制三角形的随机点,然后在JPanel的paintComponent方法中显示该图像。您可以在程序启动时绘制图像,然后在完成后启动GUI,或者您可以启动GUI并在后台线程中绘制到BufferedImage,并在完成后显示它,或者可以正常(如果这是你的GUI应该做的唯一事情。)
例如:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class SierpTest {
public static final int BI_WIDTH = 630;
public static final int BI_HEIGHT = 580;
public static void main(String[] args) {
// do this stuff off the swing event thread
final BufferedImage sierpImg = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = sierpImg.getGraphics();
// draw triangle with g here
g.dispose(); // always dispose of any Graphics you create yourself
// do this on the Swing event thread
SwingUtilities.invokeLater(() -> {
SierpPanel sierpPanel = new SierpPanel(sierpImg); // pass in image
JFrame frame = new JFrame("Siep Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(sierpPanel);
frame.pack(); // size it to the size of the JPanel
frame.setLocationRelativeTo(null); // center it
frame.setVisible(true);
});
}
}
class SierpPanel extends JPanel {
private BufferedImage img = null;
public SierpPanel(BufferedImage img) {
this.img = img;
}
// so that JPanel sizes itself with the image
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
return new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
}
例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class SierpTest {
public static final int BI_WIDTH = 630;
public static final int BI_HEIGHT = 580;
private static final int MAX_COUNT = 100000;
public static void main(String[] args) {
// do this stuff off the swing event thread
Point point1 = new Point(10, 550);
Point point2 = new Point(300, 30);
Point point3 = new Point(600, 555);
Point current = point1;
Point target = current;
int count = 0;
final BufferedImage sierpImg = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = sierpImg.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g.setColor(Color.BLACK);
while (count <= MAX_COUNT) {
int choice = (int) (Math.random() * 3);
switch (choice) {
case 0:
target = point1;
break;
case 1:
target = point2;
break;
case 2:
target = point3;
break;
default:
System.exit(0);
}
current = midpoint(current, target);
g.drawLine(current.x, current.y, current.x, current.y);
count++;
}
// draw triangle with g here
g.dispose(); // always dispose of any Graphics you create yourself
// do this on the Swing event thread
SwingUtilities.invokeLater(() -> {
SierpPanel sierpPanel = new SierpPanel(sierpImg); // pass in image
JFrame frame = new JFrame("Siep Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(sierpPanel);
frame.pack(); // size it to the size of the JPanel
frame.setLocationRelativeTo(null); // center it
frame.setVisible(true);
});
}
public static Point midpoint(Point a, Point b) {
return new Point((Math.round(a.x + b.x) / 2), (Math.round(a.y + b.y) / 2));
}
}
class SierpPanel extends JPanel {
private BufferedImage img = null;
public SierpPanel(BufferedImage img) {
this.img = img;
}
// so that JPanel sizes itself with the image
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
return new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
}
请注意,如果您希望获得幻想并在创建时绘制三角形并延迟,请考虑使用Swing Timer或SwingWorker。