My goal is to implement a space filling curve in one frame, and in the other the number of each pixel in the frame. In the future, I will need to draw some coordinates in the third frame. My question now is how do I draw the curve in one frame and the pixels in the other. I only get them in the same frame.
Here is the code:
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);
}
}
}
And the SimpleGraphics.java class
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;
}
}
The output is:Output
The out put I want is: enter image description here
Basically speaking, you want to decouple the data from the view. The way in which the data "might" be rendered should be irrelevant to the data.
This concept is commonly know as "Model-View-Controller".
To start with, you want to create a model of your "Hilbert Curve", which would be a bunch of points, each point representing the next point in the curve, for example...
Once you have the model, you can share it between views, so that they can render it in what ever way they see fit, for example...
This will basically create two windows, one will render the curve and the other will display a list of points
Updated
Okay, this example goes to the nth degree. Personally, I'd have created a renderer which contained a couple of flags which could be used to turn features on or off, but this demonstrates inheritance and how you might be able to use to use it to expand the functionality of a class.
I would, highly, recommend you take a closer look at How to perform custom painting and Painting in Swing to gain a better understanding into how painting actually works in Swing.
Also, an instance of a component can only reside in one container at a time. As demonstrated in the above example, you will need at least two instances of the render pane