基本上,您希望将数据与视图分离。数据“可能”呈现的方式应该与数据无关。
这个概念通常被称为“模型-视图-控制器”。
首先,您要创建“希尔伯特曲线”的模型,这将是一堆点,每个点代表曲线中的下一个点,例如...
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 级。就个人而言,我会创建一个渲染器,其中包含几个可用于打开或关闭功能的标志,但这演示了继承以及如何使用它来扩展类的功能。
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);
}
}
}
我强烈建议您仔细查看如何在 Swing 中执行自定义绘画和绘画,以更好地了解绘画在 Swing 中的实际工作方式。
此外,一个组件的实例一次只能驻留在一个容器中。如上例所示,您将需要至少两个渲染窗格实例