使用 Java 图形的数字线 API

Number Line using Java Graphics API

我正在尝试创建一个标有 x-axis.Two 问题的数轴:

  1. 0-9 一切正常。但在那之后,数字会被挤在一起,并且在比例上没有正确定位。
  2. 每次我尝试最大化我的 window 时我的主轴线往往会消失,或者有时它不会出现在 all.Every 任何这些发生时,我必须重新编译我的代码,它工作得很好。

对于上述问题的任何帮助将不胜感激。

import java.awt.Graphics;

import javax.swing.JFrame;

/**
* @author Emil Shirima
*
*/
public class Drawing extends JFrame {

/**
 * @param args
 */
int width = 300, height = 300, spacing = 10;
int x1 = 0, y1 = 150, x2 = 300, y2 = 150;

public Drawing() {
    setTitle("Trial");
    setSize(width, height);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
}

@Override
public void paint(Graphics brush) {
    brush.drawLine(x1, y1, x2, y2);
    x1 = 10;
    y1 = 150;
    x2 = 10;
    y2 = 130;
    // brush.drawLine(x1, y1, x2, y2);
    for (int i = 0; i < 12; ++i) {
        String ID = Integer.toString(i);
        x1 = x2 += spacing;
        brush.drawLine(x1, y1, x2, y2);
        if (i < 10) {
            brush.drawString(ID, x1 - 3, y2 + 40);
        } else {
            // With the below implementation, the numbers overlap each other
            // and are not properly oriented on the axis
            brush.drawString(ID, x1 - 3, y2 + 40);
            // TODO: I need to resize the numbers after 10 so as they fit
            // properly on the scale
        }

    }

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Drawing draw_object = new Drawing();

}

当前实施:

最大化 GUI:

您的主要问题:

  • 您在绘画方法中更改了 x1、x2,这些更改将在下一次绘画中保留。换句话说,您是在渲染方法中更改对象的状态,这是您必须避免的事情。
  • 您使用的 "magic" 数字使您的程序难以调试。

其他相关问题:

  • 您直接在 JFrame 中绘图,Swing 绘图教程告诉您绝对不要这样做,因为存在严重副作用的风险。
  • 改为在 JPanel 的 paintComponent 方法中绘制。
  • 你没有调用任何超级绘画方法,因此打破了绘画链。

如果您希望数字线延伸穿过组件,请在绘制方法(同样是 paintComponent)中获取组件的大小,并使用它来帮助确定线的位置。

还可以考虑添加一些 FontMetrics 来帮助放置数字文本。例如,以下代码创建一个可实现的数字行:

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.*;

@SuppressWarnings("serial")
public class SimpleNumberLinePanel extends JPanel {

   private static final int PREF_W = 800;
   private static final int PREF_H = 300;
   private static final int GAP = 10;
   private static final int START = 0;
   private static final int END = 12;
   private static final int VERT_LINE_HEIGHT = 20;
   private static final Font FONT = new Font(Font.MONOSPACED, Font.BOLD, 14);
   private static final int TEXT_GAP = 2;

   @Override
   protected void paintComponent(Graphics g) {
      // call super method
      super.paintComponent(g);

      int width = getWidth();
      int height = getHeight();

      // initialize these guys each time paintComponent is called
      int x1 = GAP;
      int y1 = height / 2;
      int x2 = width - 2 * GAP;
      int y2 = y1;
      g.drawLine(x1, y1, x2, y2);

      for (int i = START; i <= END; i++) {
         int x = (i * (x2 - x1)) / (END - START) + GAP;
         drawNumberAndLine(g, i, x, y1, VERT_LINE_HEIGHT);
      }
   }

   private void drawNumberAndLine(Graphics g, int number, int x, int y,
         int vertLineHeight) {
      int x1 = x;
      int y1 = y;
      int x2 = x;
      int y2 = y - vertLineHeight;
      g.drawLine(x1, y1, x2, y2);

      String text = String.valueOf(number);
      g.setFont(FONT);
      FontMetrics fontMetrics = g.getFontMetrics();
      int textX = x - fontMetrics.stringWidth(text) / 2;
      int textY = y + fontMetrics.getHeight() + TEXT_GAP;
      g.drawString(text, textX, textY);
   }

   @Override // make GUI bigger
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Number Line");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SimpleNumberLinePanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}