Ravo Ravo - 6 months ago 19
Java Question

Game field using Swing

I have a problem with my task. And by problem I mean i have completely no idea how to do it. I have to make a window of fields, like on the pic. The amount of fields (X x Y) should be set by user. Each field should be able to click (they should work like a buttons) and after click user should have some choices (e.g. change color of field, its name, etc.).

Any advice what components of Swing should I use, any tutorials? I found nothing so far.

enter image description here

Answer

I don't use Swing any more. I would strongly suggest JavaFX instead. But I have done a similar thing (made an Othello game for my son), and then i just used a JTable. You can set almost any object as your table cell object with some fiddling, like an image of particular color, and it comes with listener for clicking cells.

The same solution works for JavaFX using a table to display your clickable images.

Sample of my Table class in Swing:

package spelmeny.table;

import java.awt.Component;
import java.util.Enumeration;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import spelmeny.logik.GameModel;
import spelmeny.style.GameStyle;

/**
*
* @author stefan santesson
*/
public class OthelloTable {

JTable table;
GameModel gameModel;
DefaultTableModel tm;
String[] heading = new String[]{"1", "2", "3", "4", "5", "6", "7", "8"};
GameStyle style;

public OthelloTable(JTable table, GameModel gameModel, GameStyle style) {
    this.table = table;
    table.setRowHeight(GameStyle.CELL_SIZE);
    this.gameModel = gameModel;
    this.style = style;
}

public void setStyle(GameStyle style) {
    this.style = style;
}

public void updateTable() {
    int colCount = table.getColumnModel().getColumnCount();
    Object[][] tableVal = new Object[colCount][8];
    int[][] board = gameModel.getBoardData();
    for (int row = 0; row < 8; row++) {
        for (int col = 0; col < 8; col++) {
            tableVal[row][col] = board[row][col];
        }
    }
    for (int row = 0; row < 8; row++) {
        for (int col = 0; col < colCount; col++) {
            tm.setValueAt(tableVal[row][col], row, col);
        }
    }
}

public void setTable() {
    tm = new MyTableModel(heading);
    IconRenderer icnRenderer = new IconRenderer();
    int[][] board = gameModel.getBoardData();

    for (int row = 0; row < 8; row++) {
        Object[] rowData = new Object[8];
        for (int col = 0; col < 8; col++) {
            rowData[col] = board[row][col];
        }
        tm.addRow(rowData);
    }

    table.setModel(tm);
    Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
    for (int colIndex = 0; colIndex < 8; colIndex++) {
        TableColumn cbCol = table.getColumnModel().getColumn(colIndex);
        cbCol.setCellRenderer(icnRenderer);
        columns.nextElement().setPreferredWidth(GameStyle.CELL_SIZE);
    }
    table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
}

class MyTableModel extends DefaultTableModel {

    public MyTableModel(Object[] os) {
        super();
        for (Object o : os) {
            addColumn(o);
        }
    }

    @Override
    public Class getColumnClass(int columnIndex) {
        switch (columnIndex) {
            default:
                return Integer.class;
        }
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        return false;
    }
}

class IconRenderer extends DefaultTableCellRenderer {

    public IconRenderer() {
        super();
    }

    @Override
    public void setValue(Object value) {
        if (value instanceof Integer) {
            switch ((Integer) value) {
                case GameModel.BLACK:
                    setIcon(style.getBlackIcn());
                    break;
                case GameModel.WHITE:
                    setIcon(style.getWhiteIcn());
                    break;
                case GameModel.POSSIBLE:
                    setIcon(style.getPossibleIcn());
                    break;
                default:
                    setIcon(style.getEmptyIcn());
            }
        }

    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        Object firstColumnValue = table.getValueAt(row, 0);

        setVerticalAlignment(JLabel.TOP);
        setValue(value);
        setBackground(table.getBackground());
        setForeground(table.getForeground());
        return this;
    }
}

}