I am new to java and I am making a Whack a Mole game using a JFrame with JButtons. Currently, I have a 5x5 grid of buttons and that is as far as I got. I am having 3 of the buttons be X (to represent the mole) and 22 be O (to represent an empty hole). I would like for the buttons values to shuffle so that every 2 seconds the values are randomized. How might I go about doing this? Sorry for being such a novice, I literally started java a couple weeks back and JFrames still confuse me lol. Here is the code I currently have, thanks;
import javax.swing.*;
import java.awt.*;
public class Whack_A_Mole extends JFrame {
JButton[][] square = new JButton[5][5];
JButton button1, button2;
static JLabel label = new JLabel();
Whack_A_Mole() {
super("Whack a Mole");
JPanel p = new JPanel(new GridLayout(5,5));
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
square[i][j] = new JButton();
p.add(square[i][j]);
}
}
add(p, BorderLayout.CENTER);
p = new JPanel(new GridLayout(1,2));
setSize(600, 600);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
new Whack_A_Mole();
}
}
If you put the objects in an ArrayList, you can use the shuffle() method to shuffle their order. As to timing, either use Thread.sleep(millisecondsAmt) or a Timer. I prefer the util.Timer, especially when the action repeats indefinitely or for many repetitions.
Create a thread that will add update function into queue every 2 seconds.
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.util.Random;
public class Wack_A_Mole extends JFrame {
JButton[][] square = new JButton[5][5];
JButton button1, button2;
static JLabel label = new JLabel();
private Thread updateWoker;
Whack_A_Mole() {
super("Whack a Mole");
JPanel p = new JPanel(new GridLayout(5,5));
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
square[i][j] = new JButton();
p.add(square[i][j]);
}
}
add(p, BorderLayout.CENTER);
p = new JPanel(new GridLayout(1,2));
setSize(600, 600);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
setLocationRelativeTo(null);
}
void start(){
updateWoker=new Thread(new Runnable(){
public void run(){
Runnable r=new Runnable(){
public void run() {
buttonUpdate(); // call buttonUpdate every two seconds
}
};
while (true){
javax.swing.SwingUtilities.invokeLater(r);
try{Thread.sleep(2000);} catch (InterruptedException ex) {
return;
}
}
}
}
);
updateWoker.start();
}
public void buttonUpdate(){ // random update can be done in this function
Random r=new Random();
for(int i=0;i<square.length;i++){
for(int j=0;j<square[i].length;j++){
if(r.nextInt() %2==0)
square[i][j].setText("O");
else
square[i][j].setText("X");
}
}
}
public void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) { // making sure to stop the thread after gui closes
if(updateWoker.isAlive()){
updateWoker.interrupt();
}
dispose();
}
}
public static void main(String[] args) throws InterruptedException {
final Whack_A_Mole theTest=new Whack_A_Mole();
theTest.start();
}
}
Related
I want to have a for loop, that can implement and add a specified number of JButtons the one after the other. I was trying to implement it and this is my code so far:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ArrayForm extends JFrame implements ActionListener
{
JPanel numPanel = new JPanel();
JPanel opPanel = new JPanel();
JTextField textField = new JTextField(25);
JButton [] buttons = new JButton[10];
JButton [] OPbuttons = new JButton[6];
String num="";
String [] operation = {"+","-","*","/","=","C"};
public static void main(String[] args)
{ArrayForm fobject = new ArrayForm();}
public ArrayForm()
{
setLayout(new FlowLayout());
setSize(400,300);
setTitle("Calculator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
numPanel.setPreferredSize(new Dimension(180,150));
numPanel.setLayout(new FlowLayout());
opPanel.setPreferredSize(new Dimension(200,70));
opPanel.setLayout(new FlowLayout());
for (int i = 0; i<10; i++)
{
//The code in here
}
for (int i = 0; i<6; i++)
{
//The code in here
}
add(textField);
this.textField.setEditable(false);
add(numPanel);
add(opPanel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e)
{
}
}
Can you please help me with for loop part? where the first one is buttons array, and the second one is for OPbuttons array.
Your for loop part might be as follows:
for (int i = 0; i<10; i++)
{
buttons[i] = new JButton(""+i);
numPanel.add(buttons[i]);
buttons[i].addActionListener(this);
}
for (int i = 0; i<6; i++)
{
OPbuttons[i] = new JButton(operation[i]);
opPanel.add(OPbuttons[i]);
OPbuttons[i].addActionListener(this);
}
What i have understood, is that you are trying to add the buttons of a calculator automatically, within two different panels...
NB: don't forget to add the code for your Action Listener.
So I'm new to Java and im definitely new to Swing.
I've got a 80 X 80 array thats going to be used by a maze. I need my gui to have 80 X 80 buttons so they can be tied to the values in my array.
I cant figure out why I'm only getting five or six large buttons from this code. If anyone can tell me how I can get this to work then thank you in advance because I'm stumped.
Just run it and you'll see what I mean...also I guess I've not figured out how to change the color of the buttons and I changed the background color instead.
Heres my code:
public static void draw() {
JFrame f = new JFrame();
f.setTitle("Maze");
f.setSize(800, 800);
f.setVisible(true);
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel c = (JPanel)f.getContentPane();
GridLayout gridLayout = new GridLayout();
c.setLayout(gridLayout);
for(int i =0;i<80;i++){
for(int j =0;j<80;j++){
JButton b = new JButton();
c.add(b, i,j);
b.setSize(10, 10);
b.setOpaque(true);
b.setBackground(Color.red);
}
}
}
}
80 * 10 > f.setSize(800, 800); and your code is not possible to fit in FullHd monitor
use f.pack() instead of f.setSize(800, 800);
f.pack() and f.setVisible(true); (could be a main issue) should be last code lines in non_static and renamed to !public void DrawMe() {!, because draw() is reserved word for/in Java API
c.add(b, i,j); should be last code line too (logical ordering),
c.add(b, i,j); set row and columns for GridLayout instead of injecting the JButton to virtual grid in GridLayout
make me some sense (starting with the numbers of elements)
from
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawMe {
private JFrame frame = new JFrame();
private JPanel c = new JPanel();
private static final int column = 10;
private static final int row = 10;
public DrawMe() {
c.setLayout(new GridLayout(row, column));
for (int i = 0; i < column; i++) {
for (int j = 0; j < row; j++) {
JButton b = new JButton((i + 1) + " " + (j + 1));
c.add(b);
}
}
frame.add(c);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new DrawMe();
}
});
}
}
I am making a fighting game and the player will choose its class. How do I say If (Player chooses Warrior) then (blah) with my code?
import java.awt.GridLayout;
import javax.swing.*;
public class ButtonTest {
static JDialog dialog;
public static void main(String[] args) {
JDialog dialog = null;
JOptionPane optionPane = new JOptionPane();
optionPane.setMessage("Choose Your Class!");
optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3,1));
String[] buttonTxt = {"Warrior","Battlemage","Tank","Archer","Kitty"};
JButton[] buttons = new JButton[buttonTxt.length];
for (int i = 0; i < buttonTxt.length; i++)
{
buttons[i] = new JButton(buttonTxt[i]);
panel.add(buttons[i]);
}
optionPane.setOptionType(JOptionPane.DEFAULT_OPTION);
optionPane.add(panel);
dialog = optionPane.createDialog(null, "Icon/Text Button");
dialog.setVisible(true);
}
}
You can use actionperformed event for all the buttons.
for (int i = 0; i < buttonTxt.length; i++){
buttons[i] = new JButton(buttonTxt[i]);
buttons[i].addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
onClickButton(buttonTxt[i]);
}
});
panel.add(buttons[i]);
}
Make buttonTxt a final variable.
Then you can write your if statement inside onClickButton()
private void onClickButton(String buttonText){
if(buttonText.equals("Warrior")){
//do your stuff
}
}
Hello guys I am a rookie programmer so please excuse me if I am trying something stupid.
I started learning about GUI applications today, and I wanted to do a practice to check if I learned it properly. When I run the program, there is a dot on the screen, and I want it to move right when I click on the start button. I accomplished this, however I wanted it to be an animation, I wanted the dot to look as if it was moving slowly. But When I click to button, it just teleports.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Guila extends JFrame {
private JPanel panel;
private JButton myButton;
private final int WINDOW_WIDTH = 300;
private final int WINDOW_HEIGHT = 600;
private JPanel[] array = new JPanel[900];
private int i = 0;
int j = 0;
int m = 0;
int k = 0;
public Guila() {
setTitle("Simple Animation");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridLayout(30, 30));
while(i < 900) {
array[i] = new JPanel();
if(i == 460) {
array[i].setBackground(Color.BLACK);
}
else {
array[i].setBackground(Color.WHITE);
}
panel.add(array[i]);
i++;
}
JPanel panel2 = new JPanel();
myButton = new JButton("Start");
myButton.addActionListener(new myActionListener());
setLayout(new GridLayout(2,1));
add(panel);
panel2.add(myButton);
add(panel2);
setVisible(true);
}
private class myActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
array[460+j].setBackground(Color.WHITE);
array[461+j].setBackground(Color.BLACK);
repeat();
}
}
public void repeat() {
if (j<11) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
j++;
myButton.doClick();
}
}
public static void main(String[] args) {
new Guila();
}
}
Don't use Thread.sleep() on code that executes on the Event Dispatch Thread.
Use a Swing Timer for animation. Every time the Timer fires you update a property of the component you want to change and then you invoke repaint() on the component.
I agree with using the Swing Timer for animation. Although it might be a challenge to create your desired slow motion effect.
Use the following code to help you get started, if needed:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Bullet extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private static final int SCREEN_WIDTH = 500;
private static final int increments = 5;
int[] xPoints = new int[5];
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0,0,800,800);
g.setColor(Color.BLACK);
for (int i = 0; i < xPoints.length; i++)
{
g.fillRect(xPoints[i]+150, 210, 20, 20);
}
Timer timer = new Timer(100, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i <= 1; i++)
{
if (xPoints[i] + increments < SCREEN_WIDTH)
{
xPoints[i] += increments;
} else {
xPoints[i] = 0;
}
}
repaint();
}
});
timer.start();
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new Bullet());
frame.setVisible(true);
}
}
I'm dumbfounded here. I have a JPanel (defBoardPanel) that I'm adding to a parent JPanel (GamePanel) as follows:
public GamePanel(SetupBoard sb) {
this.setLayout(new BorderLayout());
// this.setBackground(Color.yellow);
JPanel defBoardPanel = new JPanel();
defBoardPanel.setBackground(Color.yellow);
for (int r = 0; r < sb.boardSize; r++){
for (int c = 0; c < sb.boardSize; c++){
Cell c = new Cell(r, c);
c.label.setOpaque(true);
if (sb.getCell(r, c).status == sb.getCell(r,c).status.occupied){
c.label.setBackground(Color.black);
System.out.println("LABEL IS OCCUPIED");
}
else {
c.label.setBackground(Color.white);
}
defBoardPanel.add(c.label);
}
}
defBoardPanel.revalidate();
defBoardPanel.setVisible(true);
this.add(defBoardPanel, BorderLayout.WEST);
this.revalidate();
this.setVisible(true);
This panel is to be added to a JFrame (MainFrame), which is shown below. When the application is launched, the JFrame displays a different type of Panel (SetupBoard), with which the user sets up their game board. When they click "accept", the StartGame() method of the MainFrame is called, which should show the JPanels above.
public MainFrame() {
this.setLayout(new BorderLayout());
this.setSize(500, 500);
SetupBoard sb = new SetupBoard(10, this);
this.setContentPane(sb);
}
void startGame(SetupBoard sb){
GamePanel gp = new GamePanel(sb);
this.setContentPane(gp);
this.revalidate();
}
My issue is that the child panel (defBoardPanel) is not displaying. The GamePanel itself displays (which I've verified using the setBackground(Color.yellow) method you see commented out), but not the panel I've added onto it.
What stupid mistake am I overlooking here?
EDIT: startGame() is being called from within the SetupBoard class:
void startGame(){
mf.startGame(this);
}
where mf is a reference to the MainFrame that created the SetupBoard instance. The fact that the GamePanel displays at all confirms that this is being called correctly.
Seems to work ok if I trim the code I don't have. Most likely the issue is coming from what you are not showing us. Therefore, producing an SSCCE would greatly benefit you. Meanwhile, you can always take advantage (to find the differences with your code) of the following one, which is highly originated from yours (I filled some gaps as I could):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GamePanel extends JPanel {
private static final int COLS = 10;
private static final int ROWS = 10;
public GamePanel() {
this.setLayout(new BorderLayout());
// this.setBackground(Color.yellow);
JPanel defBoardPanel = new JPanel(new GridLayout(ROWS, COLS));
defBoardPanel.setBackground(Color.yellow);
for (int r = 0; r < ROWS; r++) {
for (int c = 0; c < COLS; c++) {
JLabel label = new JLabel((r + 1) + " " + (c + 1));
label.setOpaque(true);
if (Math.random() > 0.5) {
label.setBackground(Color.black);
label.setForeground(Color.WHITE);
System.out.println("LABEL IS OCCUPIED");
} else {
label.setBackground(Color.white);
}
defBoardPanel.add(label);
}
}
this.add(defBoardPanel, BorderLayout.WEST);
}
public static class MainFrame extends JFrame {
public MainFrame() {
this.setLayout(new BorderLayout());
this.setSize(500, 500);
}
void startGame() {
GamePanel gp = new GamePanel();
this.setContentPane(gp);
pack();
setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MainFrame mainFrame = new MainFrame();
mainFrame.startGame();
}
});
}
}
This code sequence replaces the GamePanel after it has been added to MainFrame
public MainFrame() {
this.setLayout(new BorderLayout());
this.setSize(500, 500);
SetupBoard sb = new SetupBoard(10, this); // invokes startGame
this.setContentPane(sb); <----- GamePanel replaced here
}
void startGame(SetupBoard sb) {
GamePanel gp = new GamePanel(sb);
this.setContentPane(gp);
this.revalidate();
}