【问题标题】:2D array grid - placing character in the middle of each cell二维数组网格 - 将字符放置在每个单元格的中间
【发布时间】:2019-05-04 06:37:10
【问题描述】:

有一个代表地图的二维字符数组

char test[][]={{'A','B','C'},{'D','E','F'},{'G','H','I'};

如何使用 java.awt 库创建一个 3x3 网格,每个单元格的中心都有每个字符?

下面的代码给了我一个网格,但我仍然不确定如何将每个字符放在每个单元格的中心。

int sideLength=115;
int distance=sideLength*3;
int i=0;
int j=0;

for ( int x=90; x<=distance; x+=sideLength )
{
    for( int y=30; y<=distance; y+=sideLength )
    {

       g.drawRect(x,y,sideLength, sideLength);
       g.drawString(Character.toString(test[i][j]), sideLength/2, sideLength/2);

    }  
    i++;
    j++;
}          

这段代码给了我这个输出

【问题讨论】:

  • GridLayout 浮现在脑海
  • 然后是每个单元格的 GridBagLayout,因为当一个组件以默认方式添加到使用它的容器时,布局会以组件为中心。
  • 您可能还想开始阅读Working with Text APIs

标签: java arrays user-interface awt


【解决方案1】:

只有烟雾和镜子......

好的,JLabels 和 Borders

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;

public class Test {

  public static void main(String[] args) {
    new Test();
  }

  public Test() {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        JFrame frame = new JFrame();
        frame.add(new TestPane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    });
  }

  public class TestPane extends JPanel {

    public TestPane() {
      setBorder(new EmptyBorder(10, 10, 10, 10));
      setLayout(new GridLayout(0, 3));
      String test[][]={{"A","B","C"},{"D","E","F"},{"G","H","I"}};
      Border paddingBorder = new EmptyBorder(50, 50, 50, 50);
      for (int row = 0; row < 3; row++) {
        for (int col = 0; col < 3; col++) {
          JLabel label = new JLabel(test[row][col]);
          label.setVerticalAlignment(JLabel.CENTER);
          label.setHorizontalAlignment(JLabel.CENTER);

          Border edgeBorder = new MatteBorder(
                  1, 
                  1, 
                  row == 2 ? 1 : 0, 
                  col == 2 ? 1 : 0, 
                  Color.BLACK);
          label.setBorder(new CompoundBorder(edgeBorder, paddingBorder));

          add(label);
        }
      }
    }

  }

}

这个主题有很多变化,但它代表了最简单的方法

自定义绘制路线...

如果您想遵循自定义绘制路线,那么您将需要更好地了解字体的实际工作原理。

我建议从Working with Text APIs 开始以获得基本的了解。

接下来,您将正确递增 ij 属性。 j 需要在渲染每一列之前重置,并且应该为每一行递增。

就个人而言,我会反过来做,您使用每行/列的索引从数组中获取值,然后根据当前行/列索引计算 x/y 位置,但是那只是我。

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

  public static void main(String[] args) {
    new Test();
  }

  public Test() {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        JFrame frame = new JFrame();
        frame.add(new TestPane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    });
  }

  public class TestPane extends JPanel {

    String test[][] = {{"A", "B", "C"}, {"D", "E", "F"}, {"G", "H", "I"}};

    public TestPane() {
    }

    @Override
    public Dimension getPreferredSize() {
      return new Dimension(90 + (115 * 4), 30 + (115 * 4));
    }

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      int sideLength = 115;
      int distance = sideLength * 3;
      int i = 0;

      for (int x = 90; x <= distance; x += sideLength) {
        int j = 0;
        for (int y = 30; y <= distance; y += sideLength) {

          g.drawRect(x, y, sideLength, sideLength);

          FontMetrics fm = g.getFontMetrics();
          int yPos = y + ((sideLength - fm.getHeight()) / 2) + fm.getAscent();
          int xPos = x + ((sideLength - fm.stringWidth(test[i][j])) / 2);

          g.drawString(test[i][j], xPos, yPos);
          j++;
        }
        i++;
      }
    }

  }

}

【讨论】:

    【解决方案2】:

    你很接近,但我会稍微重构你的循环。不是迭代距离,而是迭代数组中的索引。然后使用数组索引推导出位置。

    char[][] test = {{'A','B','C'}, {'D','E','F'}, {'G','H','I'}};
    
    int sideLength=115;
    
    for (int i = 0; i < test.length; i++) {
        int x = 90 + sideLength * i;
        for (int j = 0; j < test[j].length; j++) {
            int y = 30 + sideLength * j;
    
            g.drawRect(x, y, sideLength, sideLength);
            g.drawString(
                Character.toString(test[i][j]), 
                x + sideLength / 2, 
                y + sideLength / 2);
    
        }  
    }       
    

    【讨论】:

    • 此作业不需要使用 MadProgrammers 解决方案所需的布局知识。这符合项目要求。
    • @Julian 对不起,你错过了第二部分吗?您还“忘记”提及“限制”:P
    • @MadProgrammer 你是对的。我确实忘记提了。我赞成您的回答,因为我需要在下一个项目中实现网格布局。我会在以后的问题中更具体:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多