如何在 JFrame 中实现希尔伯特曲线
Posted
技术标签:
【中文标题】如何在 JFrame 中实现希尔伯特曲线【英文标题】:How to implement Hilbert Curve in JFrame 【发布时间】:2018-07-17 06:17:03 【问题描述】:我正在尝试基于希尔伯特曲线制作一个项目。我能够在 Applet 中使用代码,但我需要它在 JFrame 中工作,因为我需要一次打开多个框架来展示我的项目。我有下面applet的代码,但是不知道怎么改成JFrame。
在小程序形式中,如下代码:
import java.awt.*;
import java.applet.*;
public class HilbertCurve extends Applet
private SimpleGraphics sg = null;
private int dist0=256;
private int dist=dist0;
public void init()
resize(dist0, dist0);
sg = new SimpleGraphics(getGraphics());
public void paint(Graphics g)
int level = 4;
dist = dist0;
for(int i=level; i>0; i--) dist/=2;
sg.goToXY (dist/2, dist/2);
HilbertU(level);
private void HilbertU(int level)
if(level>0)
HilbertD(level-1); sg.lineRel(0,dist);
HilbertU(level-1); sg.lineRel(dist,0);
HilbertU(level-1); sg.lineRel(0,-dist);
HilbertC(level-1);
private void HilbertD(int level)
if(level>0)
HilbertU(level-1); sg.lineRel(dist,0);
HilbertD(level-1); sg.lineRel(0,dist);
HilbertD(level-1); sg.lineRel(-dist,0);
HilbertA(level-1);
private void HilbertC(int level)
if(level>0)
HilbertA(level-1); sg.lineRel(-dist,0);
HilbertC(level-1); sg.lineRel(0,-dist);
HilbertC(level-1); sg.lineRel(dist,0);
HilbertU(level-1);
private void HilbertA(int level)
if(level>0)
HilbertC(level-1); sg.lineRel(0,-dist);
HilbertA(level-1); sg.lineRel(-dist,0);
HilbertA(level-1); sg.lineRel(0,dist);
HilbertD(level-1);
import java.awt.*;
import javax.swing.*;
class SimpleGraphics
private Graphics g = null;
private int x =0, y = 0;
public SimpleGraphics(Graphics g)
this.g = g;
public void goToXY(int x, int y)
this.x =x;
this.y= y;
public void lineRel(int deltaX, int deltaY)
g.drawLine(x, y, x+deltaX, y+deltaY);
x+=deltaX;
y+=deltaY;
我尝试自己将它放到 JFrame 中,但我做不到。 JFrame 打开,但 HilbertCurve 没有启动。下面是我的代码,我没有更改 SimpleGraphics 类
import java.awt.*;
import javax.swing.*;
public class HilbertCurve extends JPanel
JFrame frame;
private SimpleGraphics sg = null;
private int dist0=256;
private int dist=dist0;
public static void main(String[] args)
HilbertCurve exemplo1 = new HilbertCurve();
exemplo1.fireUpScreen();
public void fireUpScreen()
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(512,512);
frame.setVisible(true);
frame.add(this);
public void paint(Graphics g)
int level = 4;
dist = dist0;
for(int i=level; i>0; i--) dist/=2;
sg.goToXY (dist/2, dist/2);
HilbertU(level);
private void HilbertU(int level)
if(level>0)
HilbertD(level-1); sg.lineRel(0,dist);
HilbertU(level-1); sg.lineRel(dist,0);
HilbertU(level-1); sg.lineRel(0,-dist);
HilbertC(level-1);
private void HilbertD(int level)
if(level>0)
HilbertU(level-1); sg.lineRel(dist,0);
HilbertD(level-1); sg.lineRel(0,dist);
HilbertD(level-1); sg.lineRel(-dist,0);
HilbertA(level-1);
private void HilbertC(int level)
if(level>0)
HilbertA(level-1); sg.lineRel(-dist,0);
HilbertC(level-1); sg.lineRel(0,-dist);
HilbertC(level-1); sg.lineRel(dist,0);
HilbertU(level-1);
private void HilbertA(int level)
if(level>0)
HilbertC(level-1); sg.lineRel(0,-dist);
HilbertA(level-1); sg.lineRel(-dist,0);
HilbertA(level-1); sg.lineRel(0,dist);
HilbertD(level-1);
【问题讨论】:
首先让frame.setVisible(true);
成为你在fireUpScreen
中调用的最后一件事
已经是了,不是吗。
不,倒数第二件事。接下来,您应该得到一个NullPointerException
,因为sg
是`null
方法名称不应以大写字符开头。学习并遵循 Java 命名约定。自定义绘画是通过覆盖 JPanel 的 paintComponent(...)
完成的,不要忘记调用 super.paintComponent(..)。应该使用传递给 paintComponent() 方法的 Graphics 对象来完成绘画。
【参考方案1】:
首先,我建议您先阅读Performing Custom Painting 和Painting in AWT and Swing,以更好地了解Swing 中绘画的工作原理。
Applet 示例实际上是如何执行绘制的一个坏示例,因为您不应该维护对 Graphics
的引用,并且应该在绘制组件时将其传递给需要它的方法。
您还应该以 NullPointerException
结尾,因为 sg
永远不会初始化。
一般来说,先建立UI,最后调用setVisible
,这样可以解决一些简单的问题。
HilbertCurve
没有理由需要对 JFrame
的引用,框架可以在 main
方法中进行实例化。
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.setLocationRelativeTo(null);
frame.setVisible(true);
);
private SimpleGraphics sg = null;
private int dist0 = 256;
private int dist = dist0;
public HilbertCurve()
sg = new SimpleGraphics();
@Override
public Dimension getPreferredSize()
return new Dimension(512, 512);
@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);
class SimpleGraphics
// private Graphics g = null;
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);
x += deltaX;
y += deltaY;
【讨论】:
谢谢你,非常感谢。我敢打赌这对你来说是小菜一碟,但在这里却是一场艰苦的斗争。干杯! 我怎样才能在新框架中绘制不同的东西。我能够创建新的框架,但不是做曲线,我需要写每个点的计数 (1, 2, 3..)以上是关于如何在 JFrame 中实现希尔伯特曲线的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用希尔伯特指数的情况下对希尔伯特曲线上的点进行排序?