我目前正在用Java编写国际象棋应用程序,但是我在为图块创建边框和图像平滑方面遇到了一些问题。
修改 边界问题已解决。请参阅下面的my answer;
结果:
正如你所看到的,棋子上有锯齿状边缘,缺少瓷砖边框。 但是,如果我添加getScaledInstance(宽度,高度,Image.SCALE_SMOOTH),抗锯齿效果正常,但这会减慢我的应用程序,当我调整窗口大小时,图标看起来很难看。
我的代码:
表类:
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Table {
private final BoardPanel boardPanel;
private final Board chessBoard;
private final static Dimension OUTER_FRAME_DIMENSION = new Dimension(650, 650);
private final static Dimension MIN_FRAME_DIMENSION = new Dimension(550, 550);
public Table(Board chessBoard) {
this.chessBoard = chessBoard;
boardPanel = new BoardPanel(chessBoard);
JFrame gameFrame = new JFrame("Chess");
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
gameFrame.setLayout(new BorderLayout());
gameFrame.setSize(OUTER_FRAME_DIMENSION);
gameFrame.setMinimumSize(MIN_FRAME_DIMENSION);
gameFrame.setJMenuBar(createMenuBar());
gameFrame.add(boardPanel, BorderLayout.CENTER);
gameFrame.pack();
gameFrame.setVisible(true);
}
private JMenuBar createMenuBar() {
final JMenuBar menuBar = new JMenuBar();
menuBar.add(createFileMenu());
menuBar.add(createPreferencesMenu());
return menuBar;
}
private JMenu createFileMenu() {
final JMenu fileMenu = new JMenu("File");
final JMenuItem exitMenuItem = new JMenuItem("Exit");
exitMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
fileMenu.add(exitMenuItem);
return fileMenu;
}
private JMenu createPreferencesMenu() {
final JMenu preferencesMenu = new JMenu("Preferences");
final JMenuItem flipBoardMenuItem = new JMenuItem("Flip Board");
flipBoardMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boardPanel.reverse();
boardPanel.drawBoard();
}
});
preferencesMenu.add(flipBoardMenuItem);
return preferencesMenu;
}
}
BoardPanel类:
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import static javax.swing.SwingUtilities.invokeLater;
import static javax.swing.SwingUtilities.isLeftMouseButton;
import static javax.swing.SwingUtilities.isRightMouseButton;
class BoardPanel extends JPanel {
private final Board chessBoard;
private final TilePanel[][] boardTiles;
private Point start; // first click
private Point target; // second click
private static final Dimension BOARD_PANEL_DIMENSION = new Dimension(650, 650);
private static final Dimension TILE_PANEL_DIMENSION = new Dimension(100, 100);
BoardPanel(Board chessBoard) {
super(new GridLayout(Board.N, Board.N));
this.chessBoard = chessBoard;
this.boardTiles = new TilePanel[Board.N][Board.N];
ImageManager.readPieceImages();
setPreferredSize(BOARD_PANEL_DIMENSION);
fillBoard();
validate();
}
private void fillBoard() {
for (int x = 0; x < Board.N; x++) {
for (int y = 0; y < Board.N; y++) {
TilePanel tilePanel = new TilePanel(new Point(x, y));
boardTiles[x][y] = tilePanel;
}
}
for (int i = Board.N; i > 0; i--) {
for (int j = 0; j < Board.N; j++) {
add(boardTiles[j][i - 1]);
}
}
validate();
}
void drawBoard() {
removeAll();
for (int i = Board.N; i > 0; i--) {
for (int j = 0; j < Board.N; j++) {
boardTiles[j][i - 1].drawTile();
add(boardTiles[j][i - 1]);
}
}
revalidate();
repaint();
}
void reverse() {
// revers coloums
for (int col = 0; col < Board.N; col++) {
for (int row = 0; row < Board.N / 2; row++) {
TilePanel temp = boardTiles[row][col];
boardTiles[row][col] = boardTiles[Board.N - row - 1][col];
boardTiles[Board.N - row - 1][col] = temp;
}
}
// reverse rows
for (int row = 0; row < Board.N; row++) {
for (int col = 0; col < Board.N / 2; col++) {
TilePanel temp = boardTiles[row][col];
boardTiles[row][col] = boardTiles[row][Board.N - col - 1];
boardTiles[row][Board.N - col - 1] = temp;
}
}
}
private class TilePanel extends JPanel {
private final Tile tile;
private Image pieceImage;
TilePanel(final Point p) {
super(new GridBagLayout());
this.tile = chessBoard.getTile(p);
setPreferredSize(TILE_PANEL_DIMENSION);
setColor();
setPieceIcon();
highlightBorder();
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
if (isRightMouseButton(e)) {
start = null;
target = null;
} else if (isLeftMouseButton(e)) {
if (start == null) { // first click
start = tile.isOccupied() ? tile.getPosition() : null;
System.out.println(tile);
} else { // second click
target = tile.getPosition();
Move move = new Move(chessBoard, start, target);
if (move.isValid()) {
System.out.println(move);
chessBoard.movePiece(start, target);
System.out.println(chessBoard);
repaint();
}
start = null;
target = null;
}
}
invokeLater(new Runnable() {
@Override
public void run() {
drawBoard();
}
});
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
validate();
}
private void highlightLegalMoves() {
if (start != null && chessBoard.getTile(start).isOccupied()) {
Piece piece = chessBoard.getTile(start).getPiece();
for (Move move : piece.generateMoves(chessBoard, start)) {
if (tile == move.getStartTile()) {
setBorder(BorderFactory.createLineBorder(new Color(255, 255, 102)));
} else if (tile == move.getTargetTile()) {
setBackground(new Color(255, 255, 102));
}
}
}
}
private void highlightBorder() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));
}
private void setPieceIcon() {
removeAll();
if (tile.isOccupied()) {
Piece piece = tile.getPiece();
pieceImage = ImageManager.getPieceImage(piece.toString());
} else {
pieceImage = null;
}
}
private void drawTile() {
setColor();
setPieceIcon();
highlightLegalMoves();
highlightBorder();
revalidate();
repaint();
}
final AffineTransform getTransform() {
AffineTransform at = new AffineTransform();
at.scale(getWidth() / 900.0,
getHeight() / 900.0);
return at;
}
private void setColor() {
Color light = new Color(247, 236, 202);
Color dark = new Color(102, 68, 46);
boolean black
= (tile.getPosition().x % 2 == 0) == (tile.getPosition().y % 2 == 0);
setBackground(black ? dark : light);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.transform(getTransform());
AffineTransform at = new AffineTransform();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
at.setToTranslation(10, 0);
g2d.drawImage(pieceImage, at, null);
g2d.dispose();
}
}
}
我能解决这个问题吗?非常感谢提前。
答案 0 :(得分:0)
我通过从paintComponent()方法中删除g2d.dispose来修复边框。但我仍然有抗锯齿问题。
答案 1 :(得分:0)
当我调整窗口大小时,图标看起来很难看。