如何使用JavaSwing创建点阵数字

如何使用JavaSwing创建点阵数字,java,swing,Java,Swing,如何为时钟项目生成5 x 7点阵式数字 这是我要找的一个例子 我手动编码每个数字中每个点的位置 是否有更好的方法创建点阵数字 更好的意思是更容易代码,更容易验证,使用现有字体或其他组件,或者其他有经验的Swing开发者可能认为是一个重要的考虑因素。 这个问题的其余部分是反对者的背景,他们声称我在阐述我的问题时没有付出足够的努力 因为我提供了这个问题的答案,所以我没有在问题中发布虚假的坏代码。当然,当人们表现出他们的努力时,我们很感激。在我看来,答案中的代码和文本应该是对问题的补充 几天前,当我

如何为时钟项目生成5 x 7点阵式数字

这是我要找的一个例子

我手动编码每个数字中每个点的位置

是否有更好的方法创建点阵数字

更好的意思是更容易代码,更容易验证,使用现有字体或其他组件,或者其他有经验的Swing开发者可能认为是一个重要的考虑因素。 这个问题的其余部分是反对者的背景,他们声称我在阐述我的问题时没有付出足够的努力

因为我提供了这个问题的答案,所以我没有在问题中发布虚假的坏代码。当然,当人们表现出他们的努力时,我们很感激。在我看来,答案中的代码和文本应该是对问题的补充

几天前,当我写这篇文章时,有人提出了一个关于用点阵数字制作时钟的问题。发布问题的人提供了代码和他们创建的图片。此人创建了一个
buffereImage
,在那里他们硬编码了4 x 7点阵数字中每个方点的位置

我对这个人在他的
BufferedImage
中所做的大量工作印象深刻,所以我去了我的Eclipse,想知道如何概括他所做的工作

当我不在的时候,人们评论并结束了他的问题。当我带着我的答案回来时,那个人已经删除了他的问题

因为我有一个我认为很好的答案,所以我寻找一个合适的问题。当我找不到合适的问题时,我创建了一个问题

当然,我更关注我的答案,而不是我的问题。我真傻,我认为这个答案会为这个问题提供背景


好吧,我希望这个解释能让我更清楚地了解为什么我认为这个主题足够重要,可以创建一个问题并寻求答案。

不幸的是,你必须对每个数字中每个点的位置进行编码

但是,您可以灵活地执行此操作

这就是我的意思。5 x 7点阵数字可以表示为二维
int
数组。它也可以表示为
布尔
数组,但是0和1值的矩阵更容易直观验证

举个例子。这里有一个编码零位的方法。您可以看到,它们创建了一个易于验证的可视轮廓

    private int[][] defineZeroMatrix() {
        int[][] matrix = new int[7][];
        matrix[0] = new int[] { 0, 1, 1, 1, 0 };
        matrix[1] = new int[] { 1, 0, 0, 0, 1 };
        matrix[2] = new int[] { 1, 0, 0, 0, 1 };
        matrix[3] = new int[] { 1, 0, 0, 0, 1 };
        matrix[4] = new int[] { 1, 0, 0, 0, 1 };
        matrix[5] = new int[] { 1, 0, 0, 0, 1 };
        matrix[6] = new int[] { 0, 1, 1, 1, 0 };
        
        return matrix;
    }
我花了大约15分钟对所有的点阵数字矩阵进行编码

    private int[][][] matrices;
可以使用稀疏矩阵对点阵数字进行编码。不幸的是,这种想法导致更多的代码在视觉上更难验证

这是一个点阵数字2编码为稀疏坐标矩阵的示例

    private Point[] defineTwoCoordinates() {
        Point[] array = new Point[14];
        array[0] = new Point(0, 1);
        array[1] = new Point(1, 0);
        array[2] = new Point(2, 0);
        array[3] = new Point(3, 0);
        array[4] = new Point(4, 1);
        array[5] = new Point(4, 2);
        array[6] = new Point(3, 3);
        array[7] = new Point(2, 4);
        array[8] = new Point(1, 5);
        array[9] = new Point(0, 6);
        array[10] = new Point(1, 6);
        array[11] = new Point(2, 6);
        array[12] = new Point(3, 6);
        array[13] = new Point(4, 6);
        
        return array;
    }
在我们对所有数字矩阵进行编码之后,我们将创建一个矩阵数组

    private int[][][] matrices;
最左边的索引是数字,从0到9。第二个索引是数字矩阵的行。第三个索引是数字矩阵的列

最后,我们扩展了
JPanel
并覆盖
paintComponent
方法来实际绘制点阵数字

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        g.setColor(dotColor);
        for (int row = 0; row < matrices[digit].length; row++) {
            for (int column = 0; column < matrices[digit][row].length; column++) {
                if (matrices[digit][row][column] != 0) {
                    int x = margin + column * pixelWidth;
                    int y = margin + row * pixelWidth;
                    g.fillOval(x, y, dotWidth, dotWidth);
                }
            }               
        }
    }
有没有更好的方法来创建点阵数字

不知道是否“更好”(取决于是否努力或准确性是首要考虑因素),但有一种方法可以根据数字的
形状计算数组

以下是此计算机上默认单间距字体(粗体)版本的结果

import java.awt.*;
导入java.awt.event.*;
导入java.awt.geom.*;
导入java.awt.font.*;
导入java.awt.image.buffereImage;
导入javax.swing.*;
导入javax.swing.border.EmptyBorder;
公共类FontToDotMatrix{
私有JComponent ui=null;
形状[]形状=新形状[10];
JComboBox字体;
PixelArray[]PixelArray=新的PixelArray[10];
FontToDotMatrix(){
initUI();
}
公共最终无效初始值(){
如果(ui!=null){
回来
}
ui=新的JPanel(新的BorderLayout(4,4));
ui.setboorder(新的空订单(4,4,4,4));
字符串[]fontFamilies=GraphicsEnvironment。
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
字体=新的JComboBox(fontFamilies);
添加(字体、边框布局、页面开始);
JPanel digitPanel=新的JPanel(新的网格布局(2,5,4,4));
ui.add(数字面板);
digitPanel.setBackground(颜色:红色);
对于(int ii=0;ii<10;ii++){
PixelArray PixelArray=新PixelArray();
像素阵列[ii]=像素阵列;
添加(像素阵列);
}
ActionListener侦听器=(ActionEvent e)->{
对于(int ii=0;ii<10;ii++){
像素阵列[ii]。更新像素(getLitPixels(“+ii”);
}
};
字体。addActionListener(listener);
fonts.setSelectedItem(“等距”);
}
私有形状移动形状中心(形状形状){
int w=50;
int h=70;
矩形2D b=shape.getBounds2D();
double-xOff=-b.getX()+((w-b.getWidth())/2d);
双yOff=-b.getY()+((h-b.getHeight())/2d);
AffineTransform move=AffineTransform.getTranslateInstance(xOff,yOff);
返回move.createTransformedShape(shape);
}
专用布尔值[][]getLitPixels(字符串数字){
Font Font=新字体(fonts.getSelectedItem().toString(),Font.BOLD,70);
Shape Shape=getShapeOfCharacter(字体、数字);
Rectangle2D rect=shape.getBounds2D();
double h=rect.getHeight();
倍率=70d/h;
AffineTransform scale=AffineTransform.getScaleInstance(比率,比率);
形状=移动形状中心(scale.createTransformedShape(形状));
布尔值[][]布尔值=新的布尔值[5][7];
对于(int-yy=0;yy<7;yy++){
对于(int xx=0
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class FontToDotMatrix {

    private JComponent ui = null;
    Shape[] shapes = new Shape[10];
    JComboBox fonts;
    PixelArray[] pixelArrays = new PixelArray[10];

    FontToDotMatrix() {
        initUI();
    }

    public final void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        String[] fontFamilies = GraphicsEnvironment.
                getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        fonts = new JComboBox(fontFamilies);
        ui.add(fonts, BorderLayout.PAGE_START);

        JPanel digitPanel = new JPanel(new GridLayout(2, 5, 4, 4));
        ui.add(digitPanel);
        digitPanel.setBackground(Color.RED);
        for (int ii = 0; ii < 10; ii++) {
            PixelArray pixelArray = new PixelArray();
            pixelArrays[ii] = pixelArray;
            digitPanel.add(pixelArray);
        }

        ActionListener listener = (ActionEvent e) -> {
            for (int ii = 0; ii < 10; ii++) {
                pixelArrays[ii].updatePixels(getLitPixels("" + ii));
            }
        };
        fonts.addActionListener(listener);
        fonts.setSelectedItem("Monospaced");
    }

    private Shape moveShapeToCenter(Shape shape) {
        int w = 50;
        int h = 70;
        Rectangle2D b = shape.getBounds2D();
        double xOff = -b.getX() + ((w - b.getWidth()) / 2d);
        double yOff = -b.getY() + ((h - b.getHeight()) / 2d);
        AffineTransform move = AffineTransform.getTranslateInstance(xOff, yOff);
        return move.createTransformedShape(shape);
    }

    private boolean[][] getLitPixels(String digit) {
        Font font = new Font(fonts.getSelectedItem().toString(), Font.BOLD, 70);
        Shape shape = getShapeOfCharacter(font, digit);
        Rectangle2D rect = shape.getBounds2D();
        double h = rect.getHeight();
        double ratio = 70d / h;
        AffineTransform scale = AffineTransform.getScaleInstance(ratio, ratio);
        shape = moveShapeToCenter(scale.createTransformedShape(shape));
        boolean[][] bools = new boolean[5][7];
        for (int yy = 0; yy < 7; yy++) {
            for (int xx = 0; xx < 5; xx++) {
                Point point = new Point((xx * 10) + 5, (yy * 10) + 5);
                bools[xx][yy] = shape.contains(point);
            }
        }
        return bools;
    }

    public JComponent getUI() {
        return ui;
    }

    private Shape getShapeOfCharacter(Font font, String digit) {
        BufferedImage bi = new BufferedImage(
                1, 1, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = bi.createGraphics();

        FontRenderContext frc = g.getFontRenderContext();
        GlyphVector gv = font.createGlyphVector(frc, digit);

        return gv.getOutline();
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception useDefault) {
            }
            FontToDotMatrix o = new FontToDotMatrix();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}

class PixelArray extends JPanel {

    JLabel[][] labels = new JLabel[5][7];

    PixelArray() {
        setLayout(new GridLayout(7, 5));
        BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
        ImageIcon icon = new ImageIcon(bi);
        for (int yy = 0; yy < labels[0].length; yy++) {
            for (int xx = 0; xx < labels.length; xx++) {
                JLabel l = new JLabel(icon);
                labels[xx][yy] = l;
                l.setOpaque(true);
                add(l);
            }
        }
    }

    public void updatePixels(boolean[][] bools) {
        for (int xx = 0; xx < labels.length; xx++) {
            for (int yy = 0; yy < labels[0].length; yy++) {
                JLabel l = labels[xx][yy];
                if (bools[xx][yy]) {
                    l.setBackground(Color.WHITE);
                } else {
                    l.setBackground(Color.BLACK);
                }
            }
        }
    }
}