我的目标是在一帧中实现空间填充曲线,在另一帧中实现每个像素的数量。将来,我需要在第三帧中绘制一些坐标。我现在的问题是如何在一帧中绘制曲线而在另一帧中绘制像素。我只把它们放在同一帧中。
以下是代码:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class HilbertCurve extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
HilbertCurve exemplo1 = new HilbertCurve();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(exemplo1);
frame.pack();
frame.setLocation(100,100);
frame.setVisible(true);
JFrame frame1 = new JFrame();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.add(exemplo1);
frame1.pack();
frame1.setLocation(800, 100);
frame1.setVisible(true);
}
});
}
private SimpleGraphics sg = null;
private int dist0 = 512;
private int dist = dist0;
public HilbertCurve() {
sg = new SimpleGraphics();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(520,520);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int level = 4;
dist = dist0;
for (int i = level; i > 0; i--) {
dist /= 2;
}
sg.goToXY(dist / 2, dist / 2);
Graphics2D g2d = (Graphics2D) g.create();
hilbertU(g2d, level);
g2d.dispose();
}
private void hilbertU(Graphics2D g, int level) {
if (level > 0) {
hilbertD(g, level - 1);
sg.lineRel(g, 0, dist);
hilbertU(g, level - 1);
sg.lineRel(g, dist, 0);
hilbertU(g, level - 1);
sg.lineRel(g, 0, -dist);
hilbertC(g, level - 1);
}
}
private void hilbertD(Graphics2D g, int level) {
if (level > 0) {
hilbertU(g, level - 1);
sg.lineRel(g, dist, 0);
hilbertD(g, level - 1);
sg.lineRel(g, 0, dist);
hilbertD(g, level - 1);
sg.lineRel(g, -dist, 0);
hilbertA(g, level - 1);
}
}
private void hilbertC(Graphics2D g, int level) {
if (level > 0) {
hilbertA(g, level - 1);
sg.lineRel(g, -dist, 0);
hilbertC(g, level - 1);
sg.lineRel(g, 0, -dist);
hilbertC(g, level - 1);
sg.lineRel(g, dist, 0);
hilbertU(g, level - 1);
}
}
private void hilbertA(Graphics2D g, int level) {
if (level > 0) {
hilbertC(g, level - 1);
sg.lineRel(g, 0, -dist);
hilbertA(g, level - 1);
sg.lineRel(g, -dist, 0);
hilbertA(g, level - 1);
sg.lineRel(g, 0, dist);
hilbertD(g, level - 1);
}
}
}
SimpleGraphics.java类
import java.awt.Graphics2D;
class SimpleGraphics {
int a = 1;
private int x = 0, y = 0;
public SimpleGraphics() {
}
public void goToXY(int x, int y) {
this.x = x;
this.y = y;
}
public void lineRel(Graphics2D g, int deltaX, int deltaY) {
g.drawLine(x, y, x + deltaX, y + deltaY);
g.drawString(Integer.toString(a++), x+deltaX, y+deltaY);
x += deltaX;
y += deltaY;
}
}
输出为:Output
我想要的输出是:enter image description here
答案 0 :(得分:1)
基本上,您希望从视图中分离数据。 “可能”呈现数据的方式应该与数据无关。
这个概念通常被称为“模型 - 视图 - 控制器”。
首先,你想要创建一个“希尔伯特曲线”的模型,它将是一堆点,每个点代表曲线中的下一个点,例如......
public class HilbertCurveModel {
private List<Point> points;
private int distribution;
private int xDelta, yDelta;
public HilbertCurveModel(int level, int size) {
points = new ArrayList<>(25);
distribution = size;
for (int i = level; i > 0; i--) {
distribution /= 2;
}
hilbertU(level);
}
public int getDistribution() {
return distribution;
}
public List<Point> getPoints() {
List<Point> copy = new ArrayList<>(points.size());
for (Point p : points) {
copy.add(new Point(p));
}
return copy;
}
protected void addLine(int x, int y) {
points.add(new Point(x + xDelta, y + yDelta));
xDelta += x;
yDelta += y;
}
private void hilbertU(int level) {
if (level > 0) {
hilbertD(level - 1);
addLine(0, distribution);
hilbertU(level - 1);
addLine(distribution, 0);
hilbertU(level - 1);
addLine(0, -distribution);
hilbertC(level - 1);
}
}
private void hilbertD(int level) {
if (level > 0) {
hilbertU(level - 1);
addLine(distribution, 0);
hilbertD(level - 1);
addLine(0, distribution);
hilbertD(level - 1);
addLine(-distribution, 0);
hilbertA(level - 1);
}
}
private void hilbertC(int level) {
if (level > 0) {
hilbertA(level - 1);
addLine(-distribution, 0);
hilbertC(level - 1);
addLine(0, -distribution);
hilbertC(level - 1);
addLine(distribution, 0);
hilbertU(level - 1);
}
}
private void hilbertA(int level) {
if (level > 0) {
hilbertC(level - 1);
addLine(0, -distribution);
hilbertA(level - 1);
addLine(-distribution, 0);
hilbertA(level - 1);
addLine(0, distribution);
hilbertD(level - 1);
}
}
}
拥有模型后,您可以在视图之间共享它,以便它们能够以他们认为合适的方式呈现它,例如......
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Test {
public class HilbertCurveModel {
private List<Point> points;
private int distribution;
private int xDelta, yDelta;
public HilbertCurveModel(int level, int size) {
points = new ArrayList<>(25);
distribution = size;
for (int i = level; i > 0; i--) {
distribution /= 2;
}
hilbertU(level);
}
public int getDistribution() {
return distribution;
}
public List<Point> getPoints() {
List<Point> copy = new ArrayList<>(points.size());
for (Point p : points) {
copy.add(new Point(p));
}
return copy;
}
protected void addLine(int x, int y) {
points.add(new Point(x + xDelta, y + yDelta));
xDelta += x;
yDelta += y;
}
private void hilbertU(int level) {
if (level > 0) {
hilbertD(level - 1);
addLine(0, distribution);
hilbertU(level - 1);
addLine(distribution, 0);
hilbertU(level - 1);
addLine(0, -distribution);
hilbertC(level - 1);
}
}
private void hilbertD(int level) {
if (level > 0) {
hilbertU(level - 1);
addLine(distribution, 0);
hilbertD(level - 1);
addLine(0, distribution);
hilbertD(level - 1);
addLine(-distribution, 0);
hilbertA(level - 1);
}
}
private void hilbertC(int level) {
if (level > 0) {
hilbertA(level - 1);
addLine(-distribution, 0);
hilbertC(level - 1);
addLine(0, -distribution);
hilbertC(level - 1);
addLine(distribution, 0);
hilbertU(level - 1);
}
}
private void hilbertA(int level) {
if (level > 0) {
hilbertC(level - 1);
addLine(0, -distribution);
hilbertA(level - 1);
addLine(-distribution, 0);
hilbertA(level - 1);
addLine(0, distribution);
hilbertD(level - 1);
}
}
}
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
HilbertCurveModel model = new HilbertCurveModel(4, 512);
HilbertCurve exemplo1 = new HilbertCurve(model);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(exemplo1);
frame.pack();
frame.setLocation(100, 100);
frame.setVisible(true);
// This is the second window ;)
int xPos = model.getDistribution() / 2;
int yPos = model.getDistribution() / 2;
DefaultListModel listModel = new DefaultListModel();
listModel.addElement(new Point(xPos, yPos));
for (Point p : model.getPoints()) {
listModel.addElement(p);
}
JFrame frame1 = new JFrame();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.add(new JScrollPane(new JList(listModel)));
frame1.pack();
frame1.setLocation(800, 100);
frame1.setVisible(true);
}
});
}
public class HilbertCurve extends JPanel {
private HilbertCurveModel model;
private int xPos, yPos;
public HilbertCurve(HilbertCurveModel model) {
this.model = model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(520, 520);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xPos = model.getDistribution() / 2;
int yPos = model.getDistribution() / 2;
List<Point> points = model.points;
if (points.size() == 0) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(xPos, yPos);
g2d.setColor(Color.BLACK);
Point from = new Point(0, 0);
for (Point point : points) {
Point to = new Point(point);
System.out.println(from + "x" + to);
Line2D line = new Line2D.Double(from, to);
g2d.draw(line);
from = to;
}
g2d.dispose();
}
}
}
这基本上会创建两个窗口,一个将渲染曲线,另一个将显示一个点列表
关于我的代码的问题是我有g.drawLine(x,y,x + deltaX,y + deltaY); g.drawString(Integer.toString(a ++),x + deltaX,y + deltaY);在lineRel方法中,我不知道如何在另一帧中绘制不同的方法。每当我调用paint方法时,它都会绘制相同的东西
好的,这个例子是第n级。就个人而言,我已经创建了一个渲染器,其中包含一些可用于打开或关闭功能的标志,但这表明继承以及您可以如何使用它来扩展类的功能。 / p>
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public class HilbertCurveModel {
private List<Point> points;
private int distribution;
private int xDelta, yDelta;
public HilbertCurveModel(int level, int size) {
points = new ArrayList<>(25);
distribution = size;
for (int i = level; i > 0; i--) {
distribution /= 2;
}
hilbertU(level);
}
public int getDistribution() {
return distribution;
}
public List<Point> getPoints() {
List<Point> copy = new ArrayList<>(points.size());
for (Point p : points) {
copy.add(new Point(p));
}
return copy;
}
protected void addLine(int x, int y) {
points.add(new Point(x + xDelta, y + yDelta));
xDelta += x;
yDelta += y;
}
private void hilbertU(int level) {
if (level > 0) {
hilbertD(level - 1);
addLine(0, distribution);
hilbertU(level - 1);
addLine(distribution, 0);
hilbertU(level - 1);
addLine(0, -distribution);
hilbertC(level - 1);
}
}
private void hilbertD(int level) {
if (level > 0) {
hilbertU(level - 1);
addLine(distribution, 0);
hilbertD(level - 1);
addLine(0, distribution);
hilbertD(level - 1);
addLine(-distribution, 0);
hilbertA(level - 1);
}
}
private void hilbertC(int level) {
if (level > 0) {
hilbertA(level - 1);
addLine(-distribution, 0);
hilbertC(level - 1);
addLine(0, -distribution);
hilbertC(level - 1);
addLine(distribution, 0);
hilbertU(level - 1);
}
}
private void hilbertA(int level) {
if (level > 0) {
hilbertC(level - 1);
addLine(0, -distribution);
hilbertA(level - 1);
addLine(-distribution, 0);
hilbertA(level - 1);
addLine(0, distribution);
hilbertD(level - 1);
}
}
}
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
HilbertCurveModel model = new HilbertCurveModel(4, 512);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new HilbertCurveLineRenderer(model));
frame.pack();
frame.setLocation(100, 100);
frame.setVisible(true);
JFrame frame2 = new JFrame();
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.add(new HilbertCurveLineAndPointRenderer(model));
frame2.pack();
frame2.setLocation(100 + frame.getWidth(), 100);
frame2.setVisible(true);
}
});
}
public abstract class AbstractHilbertCurve extends JPanel {
private HilbertCurveModel model;
public AbstractHilbertCurve(HilbertCurveModel model) {
this.model = model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(520, 520);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xPos = model.getDistribution() / 2;
int yPos = model.getDistribution() / 2;
List<Point> points = model.points;
if (points.size() == 0) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(xPos, yPos);
g2d.setColor(Color.BLACK);
Point from = new Point(0, 0);
int count = 0;
for (Point to : points) {
count++;
// I don't trust you to play nice with my graphics context
Graphics2D copyG = (Graphics2D) g2d.create();
renderLine(copyG, from, to);
renderCurrentPoint(copyG, count, to);
from = to;
copyG.dispose();
}
g2d.dispose();
}
protected void renderLine(Graphics2D g2d, Point from, Point to) {
}
protected void renderCurrentPoint(Graphics2D g2d, int count, Point current) {
}
}
public class HilbertCurveLineRenderer extends AbstractHilbertCurve {
public HilbertCurveLineRenderer(HilbertCurveModel model) {
super(model);
}
protected void renderLine(Graphics2D g2d, Point from, Point to) {
Line2D line = new Line2D.Double(from, to);
g2d.draw(line);
}
}
public class HilbertCurveLineAndPointRenderer extends AbstractHilbertCurve {
public HilbertCurveLineAndPointRenderer(HilbertCurveModel model) {
super(model);
}
protected void renderLine(Graphics2D g2d, Point from, Point to) {
Line2D line = new Line2D.Double(from, to);
g2d.draw(line);
}
@Override
protected void renderCurrentPoint(Graphics2D g2d, int count, Point current) {
String text = Integer.toString(count);
FontMetrics fm = g2d.getFontMetrics();
int x = current.x - (fm.stringWidth(text) / 2);
g2d.drawString(text, x, current.y);
}
}
}
我强烈建议您仔细查看How to perform custom painting和Painting in Swing ,以便更好地了解绘画在Swing中的实际效果。
此外,组件的实例一次只能驻留在一个容器中。如上例所示,您至少需要两个渲染窗格实例