Java Swing在JPanel中居中放置两个JLabel

huangapple go评论68阅读模式
英文:

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.

Java Swing在JPanel中居中放置两个JLabel

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();
}

最终结果:

Java Swing在JPanel中居中放置两个JLabel

英文:

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:

Java Swing在JPanel中居中放置两个JLabel

huangapple
  • 本文由 发表于 2023年3月20日 22:49:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75791786.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定