I've been trying to follow an MVC pattern on my code and I was creating a system in which I have a JTabbedPane with Jbuttons inside the panel on my View, The content's info in the Model, and a the actionlisteners on my Controller.
The problem I've been having is that I've been trying to put an actionlistener on my Jbuttons but it seems to be only working on my last tab (let's say i have 4 tabs, only the 4th tab with jbuttons work)
Oh, and I should say that I've been using Jbutton arrays
Note that I've been only using only one Jbutton array to place on my panel.
how should this work? I need a sample code for reference.
here is my sample View class
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class View extends JFrame
{
private static final int HEIGHT = 700;
private static final int WIDTH = 700;
private JTabbedPane tabPane = new JTabbedPane();
private JComponent tab1 = makePanel("1");
private JComponent tab2 = makePanel("2");
private JComponent tab3 = makePanel("3");
private JComponent tab4 = makePanel("4");
private JButton[] button;
private String[] buttonlabel;
public View()
{
setLayout(null);
setSize(WIDTH, HEIGHT);
setLocationRelativeTo(null);
setResizable(false);
setVisible(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
tabPane.addTab("firstTab", tab1);
tabPane.addTab("secondTab", tab2);
tabPane.addTab("thirdTab", tab3);
tabPane.addTab("fourtTab", tab4);
add(tabPane);
tabPane.setBounds(20, 20, 400, 400);
}
protected JComponent makePanel(String input)
{
JPanel panel = new JPanel(false);
panel.setLayout(null);
if(input == "1")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button1",
"2button1",
"3button1",
"4button1"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2); y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
else if(input == "2")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button2",
"2button2",
"3button2",
"4button2"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2) && y < 5; y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
else if(input == "3")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button3",
"2button3",
"3button3",
"4button3"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2) && y < 5; y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
else if(input == "4")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button4",
"2button4",
"3button4",
"4button4"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2) && y < 5; y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
return panel;
}
public void buttonListener(ActionListener buttonL)
{
for(int x = 0; x < button.length; x++)
{
button[x].addActionListener(buttonL);
}
}
public static void main(String args[])
{
View view = new View();
Controller control = new Controller(view);
view.setVisible(true);
}
}
here is my sample Controller class
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Controller
{
View view = new View();
public Controller(View view)
{
this.view = view;
this.view.buttonListener(new ButtonListener());
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("BUTTON WORKS!");
}
}
}
You're re-filling the button array with each creation of a JTabbedPane, and in doing so, the references for all the previous buttons have been discarded from the array and only the last remains.
I suggest that you create a class for the panel of the JTabbedPane and allow it to be injected from the control. Keep it simple.
One example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class View2 extends JPanel {
private static final long serialVersionUID = 1L;
private static final String[] TAB_NAMES = {"First Tab", "Second Tab", "Third Tab", "Fourth Tab"};
private static final int PREF_W = 400;
private static final int PREF_H = 150;
private JTabbedPane tabbedPane = new JTabbedPane();
private List<MyTab> myTabs = new ArrayList<>();
private Controller2 controller2;
public View2() {
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
for (int i = 0; i < TAB_NAMES.length; i++) {
int tabNumber = i + 1;
MyTab myTab = new MyTab(TAB_NAMES[i], tabNumber);
tabbedPane.add(myTab.getTabName(), myTab);
myTabs.add(myTab);
}
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefW = Math.max(superSz.width, PREF_W);
int prefH = Math.max(superSz.height, PREF_H);
return new Dimension(prefW, prefH);
}
public Controller2 getController2() {
return controller2;
}
public void setController2(Controller2 controller2) {
this.controller2 = controller2;
for (MyTab myTab : myTabs) {
myTab.setController2(controller2);
}
}
private static void createAndShowGui() {
View2 viewPanel = new View2();
new Controller2(viewPanel);
JFrame frame = new JFrame("View2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(viewPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyTab extends JPanel {
private static final long serialVersionUID = 1L;
private static final int BUTTON_COUNT = 4;
private String tabName;
private int tabNumber;
private List<JButton> buttons = new ArrayList<>();
private Controller2 controller2;
public MyTab(String tabName, int tabNumber) {
this.tabName = tabName;
this.tabNumber = tabNumber;
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
setLayout(new GridLayout(2, 2, 4, 4));
for (int i = 0; i < BUTTON_COUNT; i++) {
String title = (i + 1) + " Button " + tabNumber;
JButton button = new JButton(title);
button.addActionListener(e -> {
if (controller2 != null) {
controller2.buttonAction(e);
}
});
add(button);
buttons.add(button);
}
}
public void setController2(Controller2 controller2) {
this.controller2 = controller2;
}
public String getTabName() {
return tabName;
}
public int getTabNumber() {
return tabNumber;
}
public List<JButton> getButtons() {
return buttons;
}
}
class Controller2 {
private View2 view;
public Controller2(View2 view) {
this.view = view;
view.setController2(this);
}
public void buttonAction(ActionEvent e) {
System.out.println("Button pressed! " + e.getActionCommand());
}
public View2 getView() {
return view;
}
}
This example uses a simple anonymous inner class ActionListener in the view to call a controller method.
Related
I am making a basic platformer game and I need to make it so that every time you jump all the platforms that are below where you jumped disappear and every platform above moves down. It is still in development so just ignore some of the things that are commented out and the messy mode.
Basically, my problem is that when I try to clear all the platforms below the one that you clicked it works fine using this code:
for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(parameters[i][1] > y) {
platforms[i].setVisible(false);
}
}
However later when I try to use .setvisible(true) on the platform that you clicked it doesn't work. Here is the full code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.math.*;
import java.util.*;
public class Main implements ActionListener {
static JFrame frame;
static JPanel panel;
//static JLabel title;
//static JLabel expl;
static JButton[] platforms;
static Random random;
static boolean playing;
static int[][] parameters;
static int platformsMade;
static int clicked;
static int preClicked;
static int score;
static int lives;
static int standing;
static int speed;
static double gravity;
static int jump;
static String action;
public Main(int seed) throws Exception {
frame = new JFrame("Snakes 'n' Adders");
panel = new JPanel(null);
//title = new JLabel("Snakes 'n' Adders", SwingConstants.CENTER);
//expl = new JLabel("");
platforms = new JButton[100000];
random = new Random();
parameters = new int[100000][5];
lives = 3;
speed = 10;
gravity = 9.81;
jump = 5;
action = "";
//panel.add(title);
//panel.add(expl);
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
random.setSeed(seed);
panel.setBackground(Color.CYAN);
//title.setFont(new Font("Arial", Font.PLAIN, 50));
}
public void drawPlatform(int x, int y, int w, int h, int colour) {
platforms[platformsMade] = new JButton();
platforms[platformsMade].addActionListener(this);
platforms[platformsMade].setBounds(x, y, w, h);
switch(colour) {
case 0:
platforms[platformsMade].setBackground(Color.BLUE);
break;
case 1:
platforms[platformsMade].setBackground(Color.GREEN);
break;
case 2:
platforms[platformsMade].setBackground(Color.RED);
break;
case 3:
platforms[platformsMade].setBackground(Color.ORANGE);
break;
case 4:
platforms[platformsMade].setBackground(Color.GRAY);
break;
}
parameters[platformsMade][0] = x;
parameters[platformsMade][1] = y;
parameters[platformsMade][2] = w;
parameters[platformsMade][3] = h;
parameters[platformsMade][4] = colour;
panel.add(platforms[platformsMade]);
platforms[platformsMade].setVisible(true);
panel.repaint();
platformsMade++;
}
public void movePlatforms(int distance, int i) {
if(platforms[i] == null) {
NullPointerException end = new NullPointerException();
throw end;
}
//this.drawPlatform(parameters[i][0], parameters[i][1] + distance, parameters[i][2], parameters[i][3], parameters[i][4]);
//platforms[i].setVisible(false);
platforms[i].setBounds(parameters[i][0], parameters[i][1] + distance, parameters[i][2], parameters[i][3]);
parameters[i][1] = parameters[i][1] + distance;
}
#Override
public void actionPerformed(ActionEvent event) {
preClicked = clicked;
for(int i = 0; i < platforms.length; i++) {
if(event.getSource() == platforms[i]) {
clicked = i;
break;
}
}
int y = parameters[clicked][1];
for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(parameters[i][1] > y) {
platforms[i].setVisible(false);
}
else {
this.movePlatforms(150, i);
}
this.movePlatforms(150, clicked);
}
for(int i = 0; i <= random.nextInt(2); i++) {
this.drawPlatform(random.nextInt(500), random.nextInt(500), 50, 50, random.nextInt(4));
}
/*for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(platforms[i].getY() > frame.getY() - platforms[i].getHeight()) {
platforms[i].setVisible(false);
}
}*/
platforms[clicked].addActionListener(this);
platforms[clicked].setVisible(true);
standing = clicked;
for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(clicked == i) {
platforms[i].setText("|");
}
else {
platforms[i].setText("");
}
}
}
public static void main(String[] args) throws Exception {
Main sna = new Main(7845);
//title.setVisible(true);
//expl.setVisible(false);
//Thread.sleep(5000);
//title.setVisible(false);
//expl.setVisible(true);
//Thread.sleep(40000);
for(int i = 0; i < 3; i++) {
sna.drawPlatform(random.nextInt(500), random.nextInt(500), 50, 50, random.nextInt(4));
}
int ticks = 0;
platforms[standing].setText("|");
}
}
I am writing a video game GUI and I want to firstly open a frame with a menu bar and when the user clicks on play in the menu a JPanel that is in a different class gets added to the current one and it ends up with a frame containing the menu bar and the JPanel. When I run the code bellow I don't get any errors and the console initiates the process. The problem is nothing shows on the screen?? Not the initial frame or anything else.
The code for the frame that calls the class with the JPanel is:
/*-----------------------------------------------------------------------------------------------------*/
package Testes;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Tetris extends JFrame{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 250;
public static final int HEIGHT = 490;
public Tetris() {
JFrame frame = new JFrame();
TetrisBoard janela = new TetrisBoard();
JMenuBar menubar = new JMenuBar();
JMenu start = new JMenu("Start");
JMenuItem play = new JMenuItem("Play");
play.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
janela.startGame();
}
});
start.add(play);
JMenuItem exit = new JMenuItem("Exit");
exit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
start.add(exit);
JMenu help = new JMenu("Help");
JMenuItem manual = new JMenuItem("User Manual");
manual.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(null, "The goal of Tetris is to eliminate \nas many lines as possible before\n the Tetrominoes reach the top.\nControls:\n\u2190 - Move Left\n\u2192 - Move Right\n\u2193 - Drop\n" +
"C - Rotate AntiClockwise\nV - Rotate Clockwise\nP - Pause\nEsc - Quit","Instructions", JOptionPane.OK_OPTION, new ImageIcon());
}
});
help.add(manual);
JMenuItem about = new JMenuItem("About");
about.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JLabel label = new JLabel("<html><center>Tetris made by GG<br>MEEC<br>2020<html>");
label.setHorizontalAlignment(SwingConstants.CENTER);
JOptionPane.showMessageDialog(null, label, "About", JOptionPane.INFORMATION_MESSAGE);
}
});
help.add(about);
menubar.add(start);
menubar.add(help);
frame.add(janela,BorderLayout.CENTER);
frame.add(menubar,BorderLayout.NORTH);
janela.setFocusable(true);
frame.setTitle("Tetris");
frame.setLayout(new BorderLayout());
frame.setSize(250, 490);
//setPreferredSize(new Dimension(255, 495));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.pack();
}
public static void main(String[] args) {
new Tetris();
}
}
/*-----------------------------------------------------------------------------------------------------*/
And the class with the JPanel is:
/*-----------------------------------------------------------------------------------------------------*/
package Testes;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
public class TetrisBoard extends JPanel implements KeyListener/*, ActionListener*/{
private static final long serialVersionUID = 1L;
public static final int COLOR_MIN = 35;
public static final int COLOR_MAX = 255 - COLOR_MIN;
public static final int BORDER_WIDTH = 5;
public static final int COL_COUNT = 10;
public static final int VISIBLE_ROW_COUNT = 20;
public static final int HIDDEN_ROW_COUNT = 2;
public static final int ROW_COUNT = VISIBLE_ROW_COUNT + HIDDEN_ROW_COUNT;
public static final int TILE_SIZE = 24;
public static final int SHADE_WIDTH = 4;
private static final int CENTER_X = COL_COUNT * TILE_SIZE / 2;
public static final int CENTER_Y = VISIBLE_ROW_COUNT * TILE_SIZE / 2;
public static final int PANEL_WIDTH = COL_COUNT * TILE_SIZE + BORDER_WIDTH * 2;
public static final int PANEL_HEIGHT = VISIBLE_ROW_COUNT * TILE_SIZE + BORDER_WIDTH * 2;
public static final Font LARGE_FONT = new Font("Tahoma", Font.BOLD, 16);
public static final Font SMALL_FONT = new Font("Tahoma", Font.BOLD, 12);
public static final long FRAME_TIME = 20L;
public static final int TYPE_COUNT = TileType.values().length;
public boolean isPaused;
public boolean isNewGame;
public boolean isGameOver;
public int level;
public int score;
public Random random;
public Clock logicTimer;
public TileType currentType;
public TileType nextType;
public int currentCol;
private int currentRow;
public int currentRotation;
public int dropCooldown;
public float gameSpeed;
public String difficulty = "Easy";
public int newLevel;
public int lines;
public int cleared;
public TileType[][] tiles;
public TetrisBoard() {
addKeyListener(this);
this.tiles = new TileType[ROW_COUNT][COL_COUNT];
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setBackground(Color.BLACK);
startGame();
}
public void clear() {
for(int i = 0; i < ROW_COUNT; i++) {
for(int j = 0; j < COL_COUNT; j++) {
tiles[i][j] = null;
}
}
}
public boolean isValidAndEmpty(TileType type, int x, int y, int rotation) {
if(x < -type.getLeftInset(rotation) || x + type.getDimension() - type.getRightInset(rotation) >= COL_COUNT) {
return false;
}
if(y < -type.getTopInset(rotation) || y + type.getDimension() - type.getBottomInset(rotation) >= ROW_COUNT) {
return false;
}
for(int col = 0; col < type.getDimension(); col++) {
for(int row = 0; row < type.getDimension(); row++) {
if(type.isTile(col, row, rotation) && isOccupied(x + col, y + row)) {
return false;
}
}
}
return true;
}
public void addPiece(TileType type, int x, int y, int rotation) {
for(int col = 0; col < type.getDimension(); col++) {
for(int row = 0; row < type.getDimension(); row++) {
if(type.isTile(col, row, rotation)) {
setTile(col + x, row + y, type);
}
}
}
}
public int checkLines() {
int completedLines = 0;
for(int row = 0; row < ROW_COUNT; row++) {
if(checkLine(row)) {
completedLines++;
}
}
return completedLines;
}
public boolean checkLine(int line) {
for(int col = 0; col < COL_COUNT; col++) {
if(!isOccupied(col, line)) {
return false;
}
}
for(int row = line - 1; row >= 0; row--) {
for(int col = 0; col < COL_COUNT; col++) {
setTile(col, row + 1, getTile(col, row));
}
}
return true;
}
public boolean isOccupied(int x, int y) {
return tiles[y][x] != null;
}
public void setTile(int x, int y, TileType type) {
tiles[y][x] = type;
}
public TileType getTile(int x, int y) {
return tiles[y][x];
}
//#Override
public void paintComponent(Graphics g) {
this.paintComponent(g);
g.translate(BORDER_WIDTH, BORDER_WIDTH);
if(isPaused()) {
g.setFont(LARGE_FONT);
g.setColor(Color.GREEN);
String msg = "PAUSED";
g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, CENTER_Y);
} else if(isNewGame() || isGameOver()) {
g.setFont(LARGE_FONT);
g.setColor(Color.WHITE);
g.setColor(Color.GREEN);
String msg = isNewGame() ? "TETRIS" : "GAME OVER";
g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, 150);
g.setFont(SMALL_FONT);
msg = "Press Enter to Play" + (isNewGame() ? "" : " Again");
g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, 300);
} else {
for(int x = 0; x < COL_COUNT; x++) {
for(int y = HIDDEN_ROW_COUNT; y < ROW_COUNT; y++) {
TileType tile = getTile(x, y);
if(tile != null) {
drawTile(tile, x * TILE_SIZE, (y - HIDDEN_ROW_COUNT) * TILE_SIZE, g);
}
}
}
TileType type = getPieceType();
int pieceCol = getPieceCol();
int pieceRow = getPieceRow();
int rotation = getPieceRotation();
for(int col = 0; col < type.getDimension(); col++) {
for(int row = 0; row < type.getDimension(); row++) {
if(pieceRow + row >= 2 && type.isTile(col, row, rotation)) {
drawTile(type, (pieceCol + col) * TILE_SIZE, (pieceRow + row - HIDDEN_ROW_COUNT) * TILE_SIZE, g);
}
}
}
g.setColor(Color.DARK_GRAY);
for(int x = 0; x < COL_COUNT; x++) {
for(int y = 0; y < VISIBLE_ROW_COUNT; y++) {
g.drawLine(0, y * TILE_SIZE, COL_COUNT * TILE_SIZE, y * TILE_SIZE);
g.drawLine(x * TILE_SIZE, 0, x * TILE_SIZE, VISIBLE_ROW_COUNT * TILE_SIZE);
}
}
}
g.setColor(Color.GREEN);
g.drawRect(0, 0, TILE_SIZE * COL_COUNT, TILE_SIZE * VISIBLE_ROW_COUNT);
}
public void drawTile(TileType type, int x, int y, Graphics g) {
drawTile(type.getBaseColor(), type.getLightColor(), type.getDarkColor(), x, y, g);
}
public void drawTile(Color base, Color light, Color dark, int x, int y, Graphics g) {
g.setColor(base);
g.fillRect(x, y, TILE_SIZE, TILE_SIZE);
g.setColor(dark);
g.fillRect(x, y + TILE_SIZE - SHADE_WIDTH, TILE_SIZE, SHADE_WIDTH);
g.fillRect(x + TILE_SIZE - SHADE_WIDTH, y, SHADE_WIDTH, TILE_SIZE);
g.setColor(light);
for(int i = 0; i < SHADE_WIDTH; i++) {
g.drawLine(x, y + i, x + TILE_SIZE - i - 1, y + i);
g.drawLine(x + i, y, x + i, y + TILE_SIZE - i - 1);
}
}
public void startGame() {
this.random = new Random();
this.isNewGame = true;
if(this.difficulty.equals("Easy")) {
this.gameSpeed=1.0f;
}else if(this.difficulty.equals("Intermediate")) {
this.gameSpeed=3.0f;
}else if(this.difficulty.equals("Hard")) {
this.gameSpeed=6.0f;
}
this.level=1;
this.cleared=0;
this.newLevel=0;
this.logicTimer = new Clock(gameSpeed);
logicTimer.setPaused(true);
while(true) {
long start = System.nanoTime();
logicTimer.update();
if(logicTimer.hasElapsedCycle()) {
updateGame();
}
//Decrement the drop cool down if necessary.
if(dropCooldown > 0) {
dropCooldown--;
}
renderGame();
long delta = (System.nanoTime() - start) / 1000000L; // delta in miliseconds
if(delta < FRAME_TIME) {
try {
Thread.sleep(FRAME_TIME - delta); // sleeps the difference between the fps and the time for the game to process (delta)
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
public void updateGame() {
if(isValidAndEmpty(currentType, currentCol, currentRow + 1, currentRotation)) {
currentRow++;
} else {
addPiece(currentType, currentCol, currentRow, currentRotation);
cleared = checkLines();
if(cleared > 0) {
lines += cleared;
score += 50 << cleared; // left bit shift - add the number of zeros on the right to the binary version of the number on the right
// score = score + 50 << cleared;
}
//newLevel+=cleared;
gameSpeed += 0.035f;
logicTimer.setCyclesPerSecond(gameSpeed);
logicTimer.reset();
dropCooldown = 25;
if(newLevel<10) {
newLevel+=cleared;
}else if(newLevel>=10) {
level+=1;
newLevel=0;
cleared=0;
}
spawnPiece();
}
}
public void renderGame() {
repaint();
}
public void resetGame() {
this.level = 1;
this.score = 0;
this.lines = 0;
this.newLevel = 0;
this.cleared = 0;
if(this.difficulty.equals("Easy")) {
this.gameSpeed=1.0f;
}else if(this.difficulty.equals("Intermediate")) {
this.gameSpeed=3.0f;
}else if(this.difficulty.equals("Hard")) {
this.gameSpeed=6.0f;
}
this.nextType = TileType.values()[random.nextInt(TYPE_COUNT)];
this.isNewGame = false;
this.isGameOver = false;
clear();
logicTimer.reset();
logicTimer.setCyclesPerSecond(gameSpeed);
spawnPiece();
}
public void spawnPiece() {
this.currentType = nextType;
this.currentCol = currentType.getSpawnColumn();
this.currentRow = currentType.getSpawnRow();
this.currentRotation = 0;
this.nextType = TileType.values()[random.nextInt(TYPE_COUNT)];
if(!isValidAndEmpty(currentType, currentCol, currentRow, currentRotation)) {
lose();
}
}
public void lose()
{
this.isGameOver = true;
logicTimer.setPaused(isPaused);
String info = "";
if (score>HighScore.getHighScores()[9].getScore())
{
info="You got a high score!\n<br>Please enter you name.\n<br>(Note: Only 10 characters will be saved)";
JLabel label = new JLabel("<html><center>GAME OVER\n<br>" + info);
label.setHorizontalAlignment(SwingConstants.CENTER);
String name=JOptionPane.showInputDialog(null, label,"Tetris", JOptionPane.INFORMATION_MESSAGE);
if (name!=null) {
HighScore.addHighScore(new HighScore(score,level,lines,(name.length()>10)?name.substring(0, 10):name,(difficulty.length()>12)?difficulty.substring(0, 12):difficulty));
}
}else {
info="You didn't get a high score:( \n<br>Keep trying you will get it next time!";
JLabel label = new JLabel("<html><center>GAME OVER\n<br>" + info);
label.setHorizontalAlignment(SwingConstants.CENTER);
JOptionPane.showMessageDialog(null, label, "Tetris", JOptionPane.PLAIN_MESSAGE);
}
if (JOptionPane.showConfirmDialog(null, "Do you want to play again?",
"Tetris", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) {
this.score=0;
this.level=0;
this.lines=0;
startGame();
}else
{
//If not, quit
System.exit(0);
}
}
public void rotatePiece(int newRotation) {
int newColumn = currentCol;
int newRow = currentRow;
int left = currentType.getLeftInset(newRotation);
int right = currentType.getRightInset(newRotation);
int top = currentType.getTopInset(newRotation);
int bottom = currentType.getBottomInset(newRotation);
if(currentCol < -left) {
newColumn -= currentCol - left;
} else if(currentCol + currentType.getDimension() - right >= COL_COUNT) {
newColumn -= (currentCol + currentType.getDimension() - right) - COL_COUNT + 1;
}
if(currentRow < -top) {
newRow -= currentRow - top;
} else if(currentRow + currentType.getDimension() - bottom >= ROW_COUNT) {
newRow -= (currentRow + currentType.getDimension() - bottom) - ROW_COUNT + 1;
}
if(isValidAndEmpty(currentType, newColumn, newRow, newRotation)) {
currentRotation = newRotation;
currentRow = newRow;
currentCol = newColumn;
}
}
public boolean isPaused() {
return isPaused;
}
public boolean isGameOver() {
return isGameOver;
}
public boolean isNewGame() {
return isNewGame;
}
public int getScore() {
return score;
}
public int getLevel() {
return level;
}
public String getDiff(){
return difficulty;
}
public int getLines() {
return lines;
}
public TileType getPieceType() {
return currentType;
}
public TileType getNextPieceType() {
return nextType;
}
public int getPieceCol() {
return currentCol;
}
public int getPieceRow() {
return currentRow;
}
public int getPieceRotation() {
return currentRotation;
}
//#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_DOWN:
if(!isPaused && dropCooldown == 0) {
logicTimer.setCyclesPerSecond(25.0f);
}
break;
case KeyEvent.VK_LEFT:
if(!isPaused && isValidAndEmpty(currentType, currentCol - 1, currentRow, currentRotation)) {
currentCol--;
}
break;
case KeyEvent.VK_RIGHT:
if(!isPaused && isValidAndEmpty(currentType, currentCol + 1, currentRow, currentRotation)) {
currentCol++;
}
break;
case KeyEvent.VK_C:
if(!isPaused) {
rotatePiece((currentRotation == 0) ? 3 : currentRotation - 1);
}
break;
case KeyEvent.VK_V:
if(!isPaused) {
rotatePiece((currentRotation == 3) ? 0 : currentRotation + 1);
}
break;
case KeyEvent.VK_P:
if(!isGameOver && !isNewGame) {
isPaused = !isPaused;
logicTimer.setPaused(isPaused);
}
break;
case KeyEvent.VK_ENTER:
if(isGameOver || isNewGame) {
resetGame();
}
break;
case KeyEvent.VK_ESCAPE:
int ans = JOptionPane.showConfirmDialog(null, "Are you sure you want to quit?\n", "Tetris", JOptionPane.INFORMATION_MESSAGE);
if(ans==1 || ans==2) {
//isPaused = !isPaused;
//logicTimer.setPaused(isPaused);
return;
}else if(ans==0) {
System.exit(0);
}
}
}
}
//#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_S:
logicTimer.setCyclesPerSecond(gameSpeed);
logicTimer.reset();
break;
}
}
#Override
public void keyTyped(KeyEvent e) {}
}
First of all, dont add a JMenuBar by frame.add(myJMenuBar,someConstraints). Do it by calling the method frame.setJMenuBar(myJMenuBar);
Secondly, you add the components into the frame (its content pane), and after that you frame.setLayout(new BorderLayout());, while you should first set the layout and AFTER add the components to it:
frame.setLayout(new BorderLayout());
frame.add(janela, BorderLayout.CENTER);
This works:
You might notice it replaces the ridiculously long & complicated TetrisBoard with a red panel with a preferred size of 400 x 200. This is how you should figure such things out. Post a minimal reproducible example in future.
import java.awt.*;
import javax.swing.*;
public class Tetris extends JFrame {
public Tetris() {
JFrame frame = new JFrame();
JPanel janela = new JPanel();
janela.setBackground(Color.RED);
janela.setPreferredSize(new Dimension(400,200));
JMenuBar menubar = new JMenuBar();
JMenu start = new JMenu("Start");
JMenuItem play = new JMenuItem("Play");
start.add(play);
JMenuItem exit = new JMenuItem("Exit");
start.add(exit);
JMenu help = new JMenu("Help");
JMenuItem manual = new JMenuItem("User Manual");
help.add(manual);
JMenuItem about = new JMenuItem("About");
help.add(about);
menubar.add(start);
menubar.add(help);
frame.add(janela, BorderLayout.CENTER);
frame.setJMenuBar(menubar);
janela.setFocusable(true);
frame.setTitle("Tetris");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
new Tetris();
}
}
I am currently trying to program a memory/matching game. I am having a problem with trying to figure out how to disable the button after the user has found matching cards. I understand that I need to store the value of the first click and compare it to the second click but still unsure about how it is not working... If anyone could help it would be very appreciated. Thanks.
Consider this code, i have recreated a more simple version of the game which you can actually run below:
main:
public static void main(String[] args) {
start start = new start();
start.main();
}
}
Class for the frame:
class start {
JToggleButton DisplayCards[][] = new JToggleButton[4][4];
Shuffle shuffle = new Shuffle();
void main() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
int y = 20;
int x = 60;
for (int i = 0; i < DisplayCards.length; ++i) {
for (int j = 0; j < DisplayCards[i].length; ++j) {
DisplayCards[i][j] = new JToggleButton("Click Me!");
DisplayCards[i][j].setBounds(x, y, 90, 126);
y = y + 135;
if (y >= 540) {
y = 20;
x = x + 120;
}
frame.add(DisplayCards[i][j]);
DisplayCards[i][j].addActionListener(new Clicked(i, j, shuffle));
}
}
frame.setLayout(null);
frame.setVisible(true);
}
}
Class that shuffles array:
class Shuffle {
String[][] cards = {
{"A", "B", "C", "D"},
{"E", "F", "G", "H"},
{"A", "B", "C", "D"},
{"E", "F", "G", "H"}
};
public void random() {
for (int i = 0; i < cards.length; i++) {
for (int j = 0; j < cards[i].length; j++) {
int i1 = (int) (Math.random() * cards.length);
int j1 = (int) (Math.random() * cards[i].length);
String temp = cards[i][j];
cards[i][j] = cards[i1][j1];
cards[i1][j1] = temp;
}
}
}
}
Class for the ActionListener:
class Clicked implements ActionListener {
String first;
start matching = new start();
boolean state = false;
Shuffle shuffle;
JToggleButton tBtn;
private int i;
private int j;
int posI;
int posJ;
public Clicked(int i, int j, Shuffle shuffle) {
this.i = i;
this.j = j;
this.shuffle = shuffle;
}
public void actionPerformed(ActionEvent e) {
tBtn = (JToggleButton) e.getSource();
if (tBtn.isSelected()) {
tBtn.setText(shuffle.cards[i][j]);
if (!state) {
first = shuffle.cards[i][j];
posI = i;
posJ = j;
System.out.println(first);
state = true;
} else {
if (first.equals(shuffle.cards[i][j])) {
tBtn.setEnabled(false);
System.out.println("Correct!");
} else if (!first.equals(shuffle.cards[i][j])) {
System.out.println("Not it");
tBtn.setText("Click Me!");
matching.DisplayCards[posI][posJ].setText("Click Me!");
first = null;
posI = 0;
posJ = 0;
state = false;
}
}
} else {
tBtn.setText("Click Me!");
}
}
}
The following is one-file mre (copy paste the entire code into `Start.java' and run).
Please note the comments:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
//Java Naming Conventions: https://www.geeksforgeeks.org/java-naming-conventions/
public class Start {
JToggleButton displayCards[][] = new JToggleButton[4][4];
Shuffle shuffle = new Shuffle();
private static final int NO_PREVIOUS = -1;
//static fileds for i,j of previous button clicked
private int previousI = NO_PREVIOUS, previousJ = NO_PREVIOUS;
void main() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
int y = 20, x = 60;
for (int i = 0; i < displayCards.length; ++i) {
for (int j = 0; j < displayCards[i].length; ++j) {
displayCards[i][j] = new JToggleButton("Click Me!");
displayCards[i][j].setBounds(x, y, 90, 126);
y = y + 135;
if (y >= 540) {
y = 20;
x = x + 120;
}
frame.add(displayCards[i][j]);
displayCards[i][j].addActionListener(new Clicked(i, j, shuffle));
}
}
frame.setLayout(null); //avoid null layout :https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
frame.setVisible(true);
}
public static void main(String[] args) {
Start Start = new Start();
Start.main();
}
//to have easy access to Start members make the ActionListener an inner class
class Clicked implements ActionListener {
private static final String HIDE_TEXT = "Click Me!";
private final Shuffle shuffle;
private final int i, j;
public Clicked(int i, int j, Shuffle shuffle) {
this.i = i;
this.j = j;
this.shuffle = shuffle;
}
#Override
public void actionPerformed(ActionEvent e) {
JToggleButton tBtn = (JToggleButton) e.getSource();
showButtonText(tBtn, i, j);
if( previousI == NO_PREVIOUS || previousJ == NO_PREVIOUS){ //no previous selected btn
previousI = i;
previousJ = j;
return;
}
JToggleButton previous = displayCards[previousI][previousJ]; //reference to previous button clicked
if(match(tBtn, previous)){
matchFound(tBtn, previous);
}else{
matchNotFound(tBtn, previous);
}
}
private void showButtonText(JToggleButton btn, int i, int j) {
btn.setText(shuffle.cards[i][j]);
btn.setEnabled(false);
}
private void resetButton(JToggleButton btn) {
btn.setForeground(Color.BLACK);
btn.setText(HIDE_TEXT);
btn.setSelected(false);
btn.setEnabled(true);
}
private boolean match(JToggleButton btn1, JToggleButton btn2) {
return btn1.getText().equals(btn2.getText());
}
private void matchFound(JToggleButton btn1, JToggleButton btn2) {
System.out.println("Correct!");
btn1.setEnabled(false);
btn2.setEnabled(false);
previousI = NO_PREVIOUS ; previousJ = NO_PREVIOUS;
}
private void matchNotFound(JToggleButton tBtn, JToggleButton previous) {
System.out.println("No match");
resetButton(previous);
previousI = i ; previousJ = j;
}
}
}
class Shuffle {
String[][] cards = {
{"A", "B", "C", "D"},
{"E", "F", "G", "H"},
{"A", "B", "C", "D"},
{"E", "F", "G", "H"}
};
public void random() {
for (int i = 0; i < cards.length; i++) {
for (int j = 0; j < cards[i].length; j++) {
int i1 = (int) (Math.random() * cards.length);
int j1 = (int) (Math.random() * cards[i].length);
String temp = cards[i][j];
cards[i][j] = cards[i1][j1];
cards[i1][j1] = temp;
}
}
}
}
A better implementation using GridLayout instead of null layout:
public class Start {
//static fileds for i,j of previous button clicked
private int previousI = NO_PREVIOUS, previousJ = NO_PREVIOUS;
private static final String HIDE_TEXT = "Click Me!";
private static final int W = 96, H = 126, NO_PREVIOUS = -1, SIZE = 4, GAP = 5;
JToggleButton displayCards[][] = new JToggleButton[SIZE][SIZE];
Shuffle shuffle = new Shuffle();
Start() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel board = new JPanel();
board.setLayout(new GridLayout(displayCards.length, displayCards[0].length, GAP, GAP));
for (int i = 0; i < displayCards.length; ++i) {
for (int j = 0; j < displayCards[i].length; ++j) {
JToggleButton btn = new JToggleButton(HIDE_TEXT);
btn.setPreferredSize(new Dimension(W,H));
btn.addActionListener(new Clicked(i, j, shuffle));
displayCards[i][j] = btn;
board.add(btn);
}
}
frame.add(board);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new Start();
}
//to have easy access to Start members make the ActionListener an inner class
class Clicked implements ActionListener {
private final Shuffle shuffle;
private final int i, j;
public Clicked(int i, int j, Shuffle shuffle) {
this.i = i;
this.j = j;
this.shuffle = shuffle;
}
#Override
public void actionPerformed(ActionEvent e) {
JToggleButton tBtn = (JToggleButton) e.getSource();
showButtonText(tBtn, i, j);
if( previousI == NO_PREVIOUS || previousJ == NO_PREVIOUS){ //no previous selected btn
previousI = i;
previousJ = j;
return;
}
JToggleButton previous = displayCards[previousI][previousJ]; //reference to previous button clicked
if(match(tBtn, previous)){
matchFound(tBtn, previous);
}else{
matchNotFound(tBtn, previous);
}
}
private void showButtonText(JToggleButton btn, int i, int j) {
btn.setText(shuffle.cards[i][j]);
btn.setEnabled(false);
}
private void resetButton(JToggleButton btn) {
btn.setForeground(Color.BLACK);
btn.setText(HIDE_TEXT);
btn.setSelected(false);
btn.setEnabled(true);
}
private boolean match(JToggleButton btn1, JToggleButton btn2) {
return btn1.getText().equals(btn2.getText());
}
private void matchFound(JToggleButton btn1, JToggleButton btn2) {
System.out.println("Correct!");
btn1.setEnabled(false);
btn2.setEnabled(false);
previousI = NO_PREVIOUS ; previousJ = NO_PREVIOUS;
}
private void matchNotFound(JToggleButton tBtn, JToggleButton previous) {
System.out.println("No match");
resetButton(previous);
previousI = i ; previousJ = j;
}
}
}
So, I am working on recreating Minesweeper in Java and right now I need to place all of the buttons on the JFrame in a grid. My code is below:
import javax.swing.*;
import java.util.ArrayList;
import java.awt.*;
import javax.imageio.*;
public class Graphics{
private JFrame frame;
private JPanel panel;
private JLabel label;
private int boardSizeY;
private int boardSizeX;
private ImageIcon ImgEmpty = new ImageIcon("/Images/Empty.png");
private ImageIcon ImgFull = new ImageIcon("/Images/UnSelected.png");
public Graphics(int sizeY, int sizeX){
boardSizeX = sizeX;
boardSizeY = sizeY;
gui();
drawButtons();
}
public void gui() {
frame = new JFrame("Minesweeper");
frame.setVisible(true);
frame.setSize(boardSizeX*20, boardSizeY*20 + 2);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(null);
}
public void drawButtons(){
ArrayList<JButton> buttons = new ArrayList<>();
int x = 0;
int y = 0;
for(int t = 0; t < boardSizeX*boardSizeY; t++){
buttons.add(new JButton(ImgFull));
panel.add(buttons.get(t));
buttons.get(t).setBounds(x*20, y*20, 20, 20);
if(y == boardSizeY-1){
x++;
y = 0;
}
else y++;
}
frame.add(panel);
}
}
The code that I wrote works, however is extremely slow for board sizes greater than 10x10. What changes can I make to my drawButtons() function in order to quicken the process.
This 30 x 30 (900 buttons) version appears almost instantly on this machine. It uses JButton components and lays them out using a GridLayout.
This is what it looks like at 10 x 10 with a larger font.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MineSweeper {
public final static String BOMB = new String(Character.toChars(128163));
private JComponent ui = null;
private MineFieldModel mineFieldModel;
private final Color[] colors = {
Color.BLUE,
Color.CYAN.darker(),
Color.GREEN.darker(),
Color.YELLOW.darker(),
Color.ORANGE.darker(),
Color.PINK.darker(),
Color.MAGENTA,
Color.RED
};
private final int size = 30;
private final float fontSize = 10f;
private JButton[][] buttons;
private JLabel info = new JLabel("Enter the minefield!");
MineSweeper() {
initUI();
}
private JToolBar getToolBar() {
JToolBar tb = new JToolBar();
tb.setFloatable(false);
tb.setLayout(new FlowLayout(FlowLayout.LEADING, 4, 2));
tb.add(info);
return tb;
}
private final Point[] getExposableSquares(Point point) {
Point[] points = null;
int x = point.x;
int y = point.y;
if (mineFieldModel.isBomb(x, y)) {
}
return points;
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(getToolBar(), BorderLayout.PAGE_START);
mineFieldModel = new MineFieldModel(size, (int)(size*size*.4));
JPanel mineFieldContainer = new JPanel(new GridLayout(
size, size));
ui.add(mineFieldContainer, BorderLayout.CENTER);
int in = 5;
Insets insets = new Insets(in, in, in, in);
Font f = getCompatibleFonts().firstElement().deriveFont(fontSize);
buttons = new JButton[size][size];
for (int ii = 0; ii < size; ii++) {
for (int jj = 0; jj < size; jj++) {
JButton b = new SquareButton();
b.setMargin(insets);
b.setFont(f);
b.setText("?");
if (mineFieldModel.isExposed(ii, jj)) {
if (mineFieldModel.isBomb(ii, jj)) {
b.setForeground(Color.red);
b.setForeground(Color.BLACK);
b.setText(BOMB);
} else if (mineFieldModel.countSurroundingMines(ii, jj) > 0) {
int count = mineFieldModel.countSurroundingMines(ii, jj);
if (count > 0) {
b.setForeground(colors[count - 1]);
b.setText("" + count);
}
} else {
b.setText("");
}
}
buttons[ii][jj] = b;
mineFieldContainer.add(b);
}
}
}
private static Vector<Font> getCompatibleFonts() {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Vector<Font> fontVector = new Vector<>();
for (Font font : fonts) {
if (font.canDisplayUpTo("12345678?" + BOMB) < 0) {
fontVector.add(font);
}
}
return fontVector;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MineSweeper o = new MineSweeper();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
class MineFieldModel {
public int size;
/**
* Records bomb locations.
*/
boolean[][] mineField;
/**
* Records whether this location has been exposed.
*/
boolean[][] fieldPlaceExposed;
int numberMines;
Random r = new Random();
MineFieldModel(int size, int numberMines) {
this.size = size;
this.numberMines = numberMines;
mineField = new boolean[size][size];
fieldPlaceExposed = new boolean[size][size];
ArrayList<Point> locations = new ArrayList<>();
for (int ii = 0; ii < this.size; ii++) {
for (int jj = 0; jj < size; jj++) {
mineField[ii][jj] = false;
// must change this to false for the actual game.
fieldPlaceExposed[ii][jj] = true;
Point p = new Point(ii, jj);
locations.add(p);
}
}
Collections.shuffle(locations, r);
for (int ii = 0; ii < numberMines; ii++) {
Point p = locations.get(ii);
mineField[p.x][p.y] = true;
}
}
public boolean isBomb(int x, int y) {
return mineField[x][y];
}
public boolean isExposed(int x, int y) {
return fieldPlaceExposed[x][y];
}
public int getSize() {
return size;
}
public int countSurroundingMines(int x, int y) {
int lowX = x - 1;
lowX = lowX < 0 ? 0 : lowX;
int highX = x + 2;
highX = highX > size ? size : highX;
int lowY = y - 1;
lowY = lowY < 0 ? 0 : lowY;
int highY = y + 2;
highY = highY > size ? size : highY;
int count = 0;
for (int ii = lowX; ii < highX; ii++) {
for (int jj = lowY; jj < highY; jj++) {
if (ii != x || jj != y) {
if (mineField[ii][jj]) {
count++;
}
}
}
}
return count;
}
}
class SquareButton extends JButton {
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int w = d.width;
int h = d.height;
int s = w>h ? w : h;
return new Dimension(s, s);
}
}
I used the code from Hovercraft Full Of Eels and manipulated it a little to get the numbering as I wanted. It looks good now and I can read the status but I can't figure out how to manipulate the individual checkboxes with my buttons on the form. Can someone help?
package and.lotto;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class NewLotto extends JPanel {
public static final int GRID_PANEL_ROWS = 3;
public static final int GRID_PANEL_COLS = 4;
public static final int PANELS = 12;
public static final int BOXES = 12;
private static final int GAP = 1;
private CheckBoxGrid[] checkBoxGrid = new CheckBoxGrid[PANELS];
public NewLotto() {
setLayout(new GridLayout(GRID_PANEL_ROWS, GRID_PANEL_COLS, GAP, GAP));
for (int rows = 0; rows < BOXES; rows++) {
checkBoxGrid[rows] = new CheckBoxGrid(rows,0);
add(checkBoxGrid[rows]);
}
}
private static void createAndShowGui() {
NewLotto mainPanel = new NewLotto();
ButtonPanel buttons = new ButtonPanel();
JFrame frame = new JFrame("Lotto");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(buttons,BorderLayout.NORTH);
frame.add(mainPanel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class ButtonPanel extends JPanel {
JButton generate;
JButton clear;
private ActionListener actionListener = new MyButtonListener();
public ButtonPanel(){
generate = new JButton("Generate numbers");
generate.addActionListener(actionListener);
clear = new JButton("Clear All");
clear.addActionListener(actionListener);
add(generate);
add(clear);
}
private class MyButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Testing");
}
}
}
#SuppressWarnings("serial")
class CheckBoxGrid extends JPanel {
private static final int CHECK_BOXES = 35;
private static final int CHECK_BOX_COLS = 6;
private static final int CHECK_BOX_ROWS = 6;
private static final int GAP = -5;
private JCheckBox[] checkBoxes = new JCheckBox[CHECK_BOXES];
private int gridIndex;
private ItemListener itemListener = new MyCheckBoxListener();
private int row;
private int col;
public CheckBoxGrid(int row, int col) {
this.row = row;
this.col = col;
gridIndex = row + col + 1;
setBorder(BorderFactory.createTitledBorder(String.valueOf(gridIndex)));
setLayout(new GridLayout(CHECK_BOX_ROWS, CHECK_BOX_COLS, GAP, GAP));
for (int cbRow = 0; cbRow < checkBoxes.length; cbRow++) {
JCheckBox checkBox = new JCheckBox();
checkBox.addItemListener(itemListener);
add(checkBox);
checkBox.setRolloverEnabled(false);
checkBox.setRequestFocusEnabled(false);
checkBoxes[cbRow] = checkBox;
}
checkBoxes[0].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red01.png")));
checkBoxes[0].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red01sel.png")));
checkBoxes[1].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red02.png")));
checkBoxes[1].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red02sel.png")));
checkBoxes[2].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red03.png")));
checkBoxes[2].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red03sel.png")));
checkBoxes[3].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red04.png")));
checkBoxes[3].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red04sel.png")));
checkBoxes[4].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red05.png")));
checkBoxes[4].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red05sel.png")));
checkBoxes[5].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red06.png")));
checkBoxes[5].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red06sel.png")));
checkBoxes[6].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red07.png")));
checkBoxes[6].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red07sel.png")));
checkBoxes[7].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red08.png")));
checkBoxes[7].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red08sel.png")));
checkBoxes[8].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red09.png")));
checkBoxes[8].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red09sel.png")));
checkBoxes[9].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red10.png")));
checkBoxes[9].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red10sel.png")));
checkBoxes[10].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red11.png")));
checkBoxes[10].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red11sel.png")));
checkBoxes[11].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red12.png")));
checkBoxes[11].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red12sel.png")));
checkBoxes[12].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red13.png")));
checkBoxes[12].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red13sel.png")));
checkBoxes[13].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red14.png")));
checkBoxes[13].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red14sel.png")));
checkBoxes[14].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red15.png")));
checkBoxes[14].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red15sel.png")));
checkBoxes[15].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red16.png")));
checkBoxes[15].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red16sel.png")));
checkBoxes[16].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red17.png")));
checkBoxes[16].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red17sel.png")));
checkBoxes[17].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red18.png")));
checkBoxes[17].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red18sel.png")));
checkBoxes[18].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red19.png")));
checkBoxes[18].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red19sel.png")));
checkBoxes[19].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red20.png")));
checkBoxes[19].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red20sel.png")));
checkBoxes[20].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red21.png")));
checkBoxes[20].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red21sel.png")));
checkBoxes[21].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red22.png")));
checkBoxes[21].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red22sel.png")));
checkBoxes[22].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red23.png")));
checkBoxes[22].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red23sel.png")));
checkBoxes[23].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red24.png")));
checkBoxes[23].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red24sel.png")));
checkBoxes[24].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red25.png")));
checkBoxes[24].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red25sel.png")));
checkBoxes[25].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red26.png")));
checkBoxes[25].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red26sel.png")));
checkBoxes[26].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red27.png")));
checkBoxes[26].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red27sel.png")));
checkBoxes[27].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red28.png")));
checkBoxes[27].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red28sel.png")));
checkBoxes[28].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red29.png")));
checkBoxes[28].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red29sel.png")));
checkBoxes[29].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red30.png")));
checkBoxes[29].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red30sel.png")));
checkBoxes[30].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red31.png")));
checkBoxes[30].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red31sel.png")));
checkBoxes[31].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red32.png")));
checkBoxes[31].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red32sel.png")));
checkBoxes[32].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red33.png")));
checkBoxes[32].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red33sel.png")));
checkBoxes[33].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red34.png")));
checkBoxes[33].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red34sel.png")));
checkBoxes[34].setIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red35.png")));
checkBoxes[34].setSelectedIcon(new ImageIcon(NewLotto.class.getResource("/and/lotto/img/red35sel.png")));
}
private class MyCheckBoxListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent itemEvt) {
JCheckBox source = (JCheckBox) itemEvt.getSource();
boolean selected = source.isSelected();
int cbRow = -1;
for (int r = 0; r < checkBoxes.length; r++) {
if (source.equals(checkBoxes[r])) {
cbRow = r;
}
}
String text = String.format("Grid %d, selected: %b, at %d",
(row + col + 1), selected, cbRow);
System.out.println(text);
}
}
}
Here is the original question:
I am trying to create a layout with an array of 12 JPanels each containing an array of 35 JCheckboxes. The problem I am having is that although the panels and checkboxes all display fine on the form, I have no way of accessing the properties of the individual checkboxes.
Here is part of the code I use:
JPanel panel_south = new JPanel();
contentPane.add(panel_south, BorderLayout.SOUTH);
panel_south.setLayout(new GridLayout(3, 4, 1, 1));
for(Integer i =0; i<12;i++){
Integer title = i+1;
EtchedBorder border = new EtchedBorder(EtchedBorder.LOWERED, null, null);
TitledBorder titled = new TitledBorder(border,title.toString());
row[i] = new JPanel();
row[i].setBorder(titled);
row[i].setLayout(new GridLayout(6, 6, -6, -5));
panel_south.add(row[i]);
JCheckBox[] rad = new JCheckBox[35];
for (int j = 0;j<35;j++){
rad[j] = new JCheckBox();
row[i].add(rad[j]);
}
When I try to use a line like this in the for loop:
row[i].rad[j].setSelected(true);
I get the error: rad cannot be resolved
What am I doing wrong here?
You should refactor out the JPanel that holds a grid of JTextFields, create a separate class for this, one that accepts a number for it's index, and that holds the JCheckBox grid or a JTable.
e.g.,
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class CheckBoxGridMain extends JPanel {
public static final int GRID_PANEL_ROWS = 3;
public static final int GRID_PANEL_COLS = 4;
private static final int GAP = 1;
private CheckBoxGrid[][] checkBoxGrid = new CheckBoxGrid[GRID_PANEL_ROWS][GRID_PANEL_COLS];
public CheckBoxGridMain() {
setLayout(new GridLayout(GRID_PANEL_ROWS, GRID_PANEL_COLS, GAP, GAP));
for (int row = 0; row < checkBoxGrid.length; row++) {
for (int col = 0; col < checkBoxGrid[row].length; col++) {
checkBoxGrid[row][col] = new CheckBoxGrid(row, col);
add(checkBoxGrid[row][col]);
}
}
}
private static void createAndShowGui() {
CheckBoxGridMain mainPanel = new CheckBoxGridMain();
JFrame frame = new JFrame("CheckBox Grid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class CheckBoxGrid extends JPanel {
private static final int CHECK_BOX_ROWS = 6;
private static final int CHECK_BOX_COLS = 6;
private static final int GAP = -5;
private JCheckBox[][] checkBoxes = new JCheckBox[CHECK_BOX_ROWS][CHECK_BOX_COLS];
private int gridIndex;
private ItemListener itemListener = new MyCheckBoxListener();
private int row;
private int col;
public CheckBoxGrid(int row, int col) {
this.row = row;
this.col = col;
gridIndex = row + col + 1;
setBorder(BorderFactory.createTitledBorder(String.valueOf(gridIndex)));
setLayout(new GridLayout(CHECK_BOX_ROWS, CHECK_BOX_COLS, GAP, GAP));
for (int cbRow = 0; cbRow < checkBoxes.length; cbRow++) {
for (int cbCol = 0; cbCol < checkBoxes[cbRow].length; cbCol++) {
JCheckBox checkBox = new JCheckBox();
checkBox.addItemListener(itemListener);
add(checkBox);
checkBoxes[cbRow][cbCol] = checkBox;
}
}
}
private class MyCheckBoxListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent itemEvt) {
JCheckBox source = (JCheckBox) itemEvt.getSource();
boolean selected = source.isSelected();
int cbRow = -1;
int cbCol = -1;
for (int r = 0; r < checkBoxes.length; r++) {
for (int c = 0; c < checkBoxes[r].length; c++) {
if (source.equals(checkBoxes[r][c])) {
cbRow = r;
cbCol = c;
}
}
}
String text = String.format("Grid %d, selected: %b, at [%d, %d]",
(row + col + 1), selected, cbCol, cbRow); // corrected row/col order
System.out.println(text);
}
}
}
Which displays