英文:
Java Swing center JLabel in JPanel with two JLabels
问题
我使用 Swing 制作这个象棋游戏。
对于棋盘(JPanel),我使用 new GridLayout(8, 8)
,然后将 64 个方块(JPanel)添加到其中。
在每个方块内部,我有一个用于代数表示(A8、A7 等)的 JLabel,这个标签位置很好。
问题出现在另一个包含棋子图像的 JLabel 上,这个标签在垂直方向上没有居中,如何将此 JLabel 居中放置在方块内。
这是方块的代码:
package org.victorpiles.escacs.client.gui;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* 作者:Víctor Piles
*/
public class Square extends JPanel {
private static final String PIECE_ICON_PATH = "client/src/main/resources/pieces/";
private static final Color LIGHT_COLOR = new Color(118, 150, 86, 255);
private static final Color DARK_COLOR = new Color(238, 238, 210, 255);
private final int position;
public Square(int position) {
super(new BorderLayout());
setAlgebraicNotationLabel(position);
this.position = position;
setBackground(getSquareColor(position));
}
private void setAlgebraicNotationLabel(int position) {
JLabel squarePosition = new JLabel(getAlgebraicNotation(position));
squarePosition.setBorder(new EmptyBorder(5, 5, 5, 5));
add(squarePosition, BorderLayout.PAGE_END);
}
/**
* 计算适当的方块颜色,基于其位置。
*
* @param position 方块位置。
*
* @return 方块颜色:{@link #LIGHT_COLOR 亮} 或 {@link #DARK_COLOR 暗}。
*/
private Color getSquareColor(int position) {
int row = position / 8;
int column = position % 8;
return (row + column) % 2 != 0 ? LIGHT_COLOR : DARK_COLOR;
}
/**
* 计算方块的代数标记,基于其位置。
*
* @param position 方块位置。
*
* @return 方块的代数标记。
*/
private String getAlgebraicNotation(int position) {
int row = 8 - (position / 8);
char column = (char) ('a' + (position % 8));
return ("" + column + row).toUpperCase();
}
public void updatePiece(char piece) {
removeAll();
BufferedImage pieceImage;
if (piece == '-') {
return;
}
String fileName = PIECE_ICON_PATH + piece + ".png";
try {
pieceImage = ImageIO.read(new File(fileName));
System.out.println(position + " -> " + pieceImage.getHeight());
} catch (IOException e) {
// TODO: 20/3/23 处理异常
throw new RuntimeException(e);
}
/* 更新方块 */
setAlgebraicNotationLabel(position);
add(new JLabel(new ImageIcon(pieceImage)));
validate();
}
}
英文:
I'm doing this chess using Swing.
For the board (JPanel) I'm using new GridLayout(8, 8)
then I add 64 Squares (JPanel) to it.
Inside each Square I have a JLabel for the algebraic notation (A8, A7...), this label is well positionated.
The problem comes with the other JLabel containing the piece image, this one is not centered vertically, how can I center this JLabel in the Square?.
Here's the code for the Square:
package org.victorpiles.escacs.client.gui;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* @author Víctor Piles
*/
public class Square extends JPanel {
private static final String PIECE_ICON_PATH = "client/src/main/resources/pieces/";
private static final Color LIGHT_COLOR = new Color(118, 150, 86, 255);
private static final Color DARK_COLOR = new Color(238, 238, 210, 255);
private final int position;
public Square(int position) {
super(new BorderLayout());
setAlgebraicNotationLabel(position);
this.position = position;
setBackground(getSquareColor(position));
}
private void setAlgebraicNotationLabel(int position) {
JLabel squarePosition = new JLabel(getAlgebraicNotation(position));
squarePosition.setBorder(new EmptyBorder(5, 5, 5, 5));
add(squarePosition, BorderLayout.PAGE_END);
}
/**
* Calcula el color adequat per a la casella, basant-se en la seua posició.
*
* @param position La posició de la casella.
*
* @return El color de la casella: {@link #LIGHT_COLOR clar} o {@link #DARK_COLOR fosc}.
*/
private Color getSquareColor(int position) {
int row = position / 8;
int column = position % 8;
return (row + column) % 2 != 0 ? LIGHT_COLOR : DARK_COLOR;
}
/**
* Calcula la notació algebraica per a la casella, basant-se en la seua posició.
*
* @param position La posició de la casella.
*
* @return La notació algebraica per a la casella.
*/
private String getAlgebraicNotation(int position) {
int row = 8 - (position / 8);
char column = (char) ('a' + (position % 8));
return ("" + column + row).toUpperCase();
}
public void updatePiece(char piece) {
removeAll();
BufferedImage pieceImage;
if (piece == '-') {
return;
}
String fileName = PIECE_ICON_PATH + piece + ".png";
try {
pieceImage = ImageIO.read(new File(fileName));
System.out.println(position + " -> " + pieceImage.getHeight());
} catch (IOException e) {
// TODO: 20/3/23 Manejar excepció
throw new RuntimeException(e);
}
/* Actualitza la casella */
setAlgebraicNotationLabel(position);
add(new JLabel(new ImageIcon(pieceImage)));
validate();
}
}
答案1
得分: 1
> 图像未垂直居中,因为其他 JLabel 占用了一部分空间
这是布局管理器的工作原理。组件被分配到二维空间中的位置。所以如果图像是 60 X 60,那么标记标签将显示在图像下方,而不是图像上方。
如果您希望标记标签显示在图像标签上方,您需要将标记标签添加到图像标签中。
您需要将图像标签定义为类中的实例变量。在构造函数中,您可以这样做:
imageLabel = new ImageLabel();
imageLabel.setLayout( new BorderLayout() );
add( imageLabel );
setAlgebraicNotationLabel(position);
...
在 setAlgebraicNotationLabel(...)
方法中,您可以使用:
//add(squarePosition, BorderLayout.PAGE_END);
imageLabel.add(squarePosition, BorderLayout.PAGE_END);
将标记标签添加到图像标签,而不是面板。
然后,您的 updatePiece(...)
方法也需要更改,以使用 setIcon(...)
方法仅更新图像标签的 Icon
,而不是每次创建新标签。
英文:
> the image is not vertically centered because of the other JLabel taking part of the space
That is the way layout managers work. Components are assigned location in 2D space. So if the image is 60 X 60, then the notation label will be displayed below the image, not on top of the image.
If you want the notation label displayed on top of the image label, then you need to add the notation label to the image label.
You would need to define your image label as an instance variable in your class. In your constructor you would do something like:
imageLabel = new ImageLabel();
imageLabel.setLayout( new BorderLayout() );
add( imageLabel );
setAlgebraicNotationLabel(position);
...
In the setAlgebraicNotationLabel(...)
method you would then use:
//add(squarePosition, BorderLayout.PAGE_END);
imageLabel.add(squarePosition, BorderLayout.PAGE_END);
to add the notation label to the image label, not the panel
Your updatePiece(...)
method would then also need to be changed to use the setIcon(...)
method to just update the Icon
of the image label, instead of creating a new label each time.
答案2
得分: 0
我是我的方式这样做:
我在图像标签的PAGE_END处添加了注释标签,为此图像标签布局为setLayout(new BorderLayout());
private JLabel getAlgebraicNotationLabel(int position) {
JLabel notationLabel = new JLabel(getAlgebraicNotation(position));
notationLabel.setBorder(new EmptyBorder(0, 5, 5, 0));
return notationLabel;
}
public void updatePiece(char piece) {
removeAll();
BufferedImage pieceImage;
if (piece == '-') {
return;
}
String fileName = PIECE_ICON_PATH + piece + ".png";
try {
pieceImage = ImageIO.read(new File(fileName));
} catch (IOException e) {
// TODO: 20/3/23 Manejar excepció
throw new RuntimeException(e);
}
/* 更新方格 */
JLabel squareLabel = new JLabel(new ImageIcon(pieceImage));
squareLabel.setLayout(new BorderLayout());
squareLabel.add(getAlgebraicNotationLabel(position),BorderLayout.PAGE_END);
add(squareLabel);
validate();
}
最终结果:
英文:
I did it this way:
I add the notation label at the PAGE_END of the image label, for this purpose the image label layout is setLayout(new BorderLayout());
private JLabel getAlgebraicNotationLabel(int position) {
JLabel notationLabel = new JLabel(getAlgebraicNotation(position));
notationLabel.setBorder(new EmptyBorder(0, 5, 5, 0));
return notationLabel;
}
public void updatePiece(char piece) {
removeAll();
BufferedImage pieceImage;
if (piece == '-') {
return;
}
String fileName = PIECE_ICON_PATH + piece + ".png";
try {
pieceImage = ImageIO.read(new File(fileName));
} catch (IOException e) {
// TODO: 20/3/23 Manejar excepció
throw new RuntimeException(e);
}
/* Actualitza la casella */
JLabel squareLabel = new JLabel(new ImageIcon(pieceImage));
squareLabel.setLayout(new BorderLayout());
squareLabel.add(getAlgebraicNotationLabel(position),BorderLayout.PAGE_END);
add(squareLabel);
validate();
}
The final result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论