I am trying to make a java GUI program "game".
There are five buttons, each with a character as the button caption. When a button is clicked, the caption of that button is exchanged with the right hand neighbor. If the far right button is clicked, then the far left button has that caption, so they both switch (it wraps around).
The goal is to have them arranged alphabetically, thus ending the game.
I can't think of an intuitive way to have the characters switching without having to make five buttons.
String str = "abcde"; // DEBUG ARGUMENT STRING
setCaptions(str);
Method that takes the string, creates a char array out of them, and creates buttons...
void setCaptions(String string){
char[] charArray = string.toCharArray();
ArrayList<Character> arrList = new ArrayList<Character>();
for (int x=0; x < charArray.length; x++) {
String str = Character.toString(charArray[x]);
btn = new JButton(str);
btn.setFont(myFont);
pane.add(btn, "LR");
btn.addActionListener(new SwitchAction());
arrList.add(str.charAt(0));
}
// check the order...
System.out.print(arrList);
if (arrList.get(0) < arrList.get(1)
&& arrList.get(1) < arrList.get(2)
&& arrList.get(2) < arrList.get(3)
&& arrList.get(3) < arrList.get(4)) {
lbl.setText("SOLVED");
}
}
ActionListener to switch the captions, which I can't figure out...
public class SwitchAction implements ActionListener {
public void actionPerformed(ActionEvent evt) {
String a = btn.getText();
System.out.println(evt.getActionCommand() + " pressed"); // debug
// something goes here...
}
}
You should have an array or ArrayList of JButton, ArrayList<JButton> and put your buttons into this list.
Your ActionListener will need a reference to the original class so it can get a hold of the ArrayList. It can then iterate through the array list find out which button was pressed, which is its neighbor, and do its swap. So pass that reference in via a constructor parameter, and then in the actionPerformed method, call a getList() or similar "getter" method to get the ArrayList and iterate through it.
i.e.,
public class MyListener implements ActionListener {
private OriginalGui gui;
public MyListener(OriginalGui gui) {
this.gui = gui;
}
public void actionPerformed(ActionEvent e) {
JButton pressedButton = (JButton) e.getSource();
ArrayList<JButton> buttonList = gui.getButtonList();
// ... iterate through list and find button.
}
}
Related
Simplified: How to make String value to call specific existed JButton variable name in java?
I'm trying to make a non-ordinary Tic-Tac-Toe game...
Anyway, what I will post here is not really the whole concept of that. I just want to make it simple: I have 9 square jButtons named (3 by 3) (and maybe allow user to make 4x4, 5x5, 10x10 etc. via settings in future):
[markbox_00_00] / [markbox_00_01] / [markbox_00_02]
[markbox_01_00] / [markbox_01_01] / [markbox_01_02]
[markbox_02_00] / [markbox_02_01] / [markbox_02_02]
[btnSave] / [btnUndoActions]
where the first two digit represent the row and the next two is the column; and a save button (btnSave) and undo button(btnUndoActions).
Each markbox have default spring value of "0", when I click it turns "1"; and when I click "1" it turns "0". When you press undo button it will reset to last save.
Here is some of my simplified line of codes:
private byte markboxColLimit = 3, markboxRowLimit = 3, row, col;
private byte[][] saveNumber = new byte[markboxRowLimit][markboxColLimit];
private String buttonName;
public Astral_TicTacToe() {
initComponents();
/* I want something like this, but using a for loop based on markboxColLimit and
markboxRowLimit as limits */
markbox_00_00.setText("0");
markbox_00_01.setText("0");
markbox_00_02.setText("0");
markbox_01_00.setText("0");
markbox_01_01.setText("0");
markbox_01_02.setText("0");
markbox_02_00.setText("0");
markbox_02_01.setText("0");
markbox_02_02.setText("0");
/* I know the line below is wrong... what I'm trying is to avoid
* repetitiveness by looping and dynamically calling the variable
* name of JButtons, or in other ways...
*/
/* Attempting to make an alternative code from above (trying to make a loop instead) */
for(row = 0; row < markboxRowLimit; row++){
for(col = 0; col < markboxColLimit; col++){
buttonName = "markbox_0" + Byte.toString(row) + "_0" + Byte.toString(col);
buttonName.setText("0");
}
}
}
private void btnUndoActionsActionPerformed(java.awt.event.ActionEvent evt) {
markbox_00_00.setText(Byte.toString(saveNumber[0][0]));
markbox_00_01.setText(Byte.toString(saveNumber[0][1]));
markbox_00_02.setText(Byte.toString(saveNumber[0][2]));
markbox_01_00.setText(Byte.toString(saveNumber[1][0]));
markbox_01_01.setText(Byte.toString(saveNumber[1][1]));
markbox_01_02.setText(Byte.toString(saveNumber[1][2]));
markbox_02_00.setText(Byte.toString(saveNumber[2][0]));
markbox_02_01.setText(Byte.toString(saveNumber[2][1]));
markbox_02_02.setText(Byte.toString(saveNumber[2][2]));
}
private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {
saveNumber[0][0] = Byte.parseByte(markbox_00_00.getText());
saveNumber[0][1] = Byte.parseByte(markbox_00_01.getText());
saveNumber[0][2] = Byte.parseByte(markbox_00_02.getText());
saveNumber[1][0] = Byte.parseByte(markbox_01_00.getText());
saveNumber[1][1] = Byte.parseByte(markbox_01_01.getText());
saveNumber[1][2] = Byte.parseByte(markbox_01_00.getText());
saveNumber[2][0] = Byte.parseByte(markbox_02_00.getText());
saveNumber[2][1] = Byte.parseByte(markbox_02_01.getText());
saveNumber[2][2] = Byte.parseByte(markbox_02_02.getText());
}
private void markbox_00_00ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
private void markbox_00_01ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_01.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
....
private void markbox_02_02ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_02_02.setText("1");
else
markbox_02_02.setText("0");
}
In short: how can I make String a specific variable name of JButton for calling/accessing/editing for their properties?
Example:
buttonName = markbox_01_02;
buttonName.setText("2");
is equavalent to markbox_01_02.getText("2");
I really appreciate the help, thank you...
P.S. I use to make JFrame in NetBeans Design (just click and drag the objects in palette window like JPanel, JButton, etc., so I don't type the code manually except making my own logical Method).
You probably need to redo your program and rephrase your question because it's kind of unclear where you're stuck that's why I wrote this answer as a Community Wiki.
The following program creates a GridLayout for the board and add 2 JButtons below it which contain "Save" and "Undo" buttons.
Whenever you press a button it will change it's text to 0 or 1 depending on the previous state of the button, and "Undo" button will undo last clic the same way, if it was 0 it will become 1 and viceversa.
I guess you should read How to write an ActionListener before copy-pasting this example, understand what it says and try to understand how this program works.
The logic to "Save" button is up to you 'cause I'm not sure what you wanna do there and I'm not gonna write all the code for you. This is made only for you to get an idea on how to handle events.
Also, the logic to end the game is left to you for the same reasons as the "Save" button.
I wish I knew how to record my screen in Ubuntu and save as GIF but here's a screenshot on how this program looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TicTacToe implements ActionListener {
JFrame frame;
JButton buttons[];
JPanel pane, buttonPane;
boolean pressed[];
JButton save, undo;
int n = -1;
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < buttons.length; i++) {
if(e.getSource() == buttons[i]) {
pressed[i] = !pressed[i];
buttons[i].setText(pressed[i] ? "1" : "0");
n = i;
break;
}
}
}
public TicTacToe () {
frame = new JFrame("Tic Tac Toe Game");
buttons = new JButton[9];
pane = new JPanel(new GridLayout(3, 3));
pressed = new boolean[9];
buttonPane = new JPanel(new FlowLayout());
save = new JButton("Save");
undo = new JButton("Undo");
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton("0");
pressed[i] = false;
}
for (JButton b : buttons) {
b.addActionListener(this);
pane.add(b);
}
undo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (n == -1) {
return;
}
pressed[n] = !pressed[n];
buttons[n].setText(pressed[n] ? "1" : "0");
}
});
buttonPane.add(save);
buttonPane.add(undo);
frame.add(pane, BorderLayout.PAGE_START);
frame.add(buttonPane, BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main (String args[]) {
new TicTacToe();
}
}
So, I know there is this:
int number = Integer.parseInt("5");
String numtxt = Integer.toString(12);
double number = Double.parseDouble("4.5");
String numbertxt = Double.toString(8.2);
String letter = Character.toString('B');
char letter = "stringText".charAt(0);
so on...
but what I don't know how to make String value to call existed JButton variable name dynamically; is it even possible?
Let's say, I have 4 JButton called btn1, btn2, btn3 and btnFillNumber;
I create a String called buttonName;
package testing;
public class Testing extends javax.swing.JFrame {
String buttonName;
int num;
public Testing() {
initComponents();
}
#SuppressWarnings("unchecked")
// Generated Code <<<-----
private void btnFillNumberActionPerformed(java.awt.event.ActionEvent evt) {
for(num = 1; num <= 3; num++){
buttonName = "btn" + Integer.toString(num);
JButton.parseJButton(buttonName).setText(num);
}
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
// Look and feel stteing code (optional) <<<-----
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Testing().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton btn1;
private javax.swing.JButton btn2;
private javax.swing.JButton btn3;
private javax.swing.JButton btnFillNumber;
// End of variables declaration
}
I know there's no JButton.parseJButton(), I just don't want to make complicated explaination, I simple want a convertion from String to call JButton's variable name dynamically.
See this:
for(num = 1; num <= 3; num++){
buttonName = "btn" + Integer.toString(num);
JButton.parseJButton(buttonName).setText(num);
}
I want to make a loop using a String with
a fixed String value (btn) and
increment number after it (1, 2, 3...) and
make use to call a JButton.
I can just simply do this, but what if I got a 25 or more? So a loop what I wanted...
btn1.setText("1");
btn2.setText("2");
btn3.setText("3");
Note that the value of these JButtons are not necessarily incremental in some purpose.
Output:
My real development:
P.S. I use to make JFrame in NetBeans Design (just click and drag the objects in palette window like JPanel, JButton, etc., so I don't type the code manually except making my own logical Method; and I can't edit the code in grey background in Source View that was made automatically by Design View but in Design View itself. If you have tips and guide, I'll be happy to).
Use a Map:
private Map<String,JButton> buttonMap = new HashMap<String,JButton>();
In your constructor add your buttons:
buttonMap.add("btn1", btn1);
buttonMap.add("btn2", btn2);
buttonMap.add("btn3", btn3);
buttonMap.add("btn4", btn4);
And in your action Listener / Loop whatever make:
String buttonName = "btn1"; //should be parameter or whatever
JButton button = buttonMap.get(buttonName);
As an alternative you could just as well set up an array of JButton:
JButton[] buttons = new JButton[4];
button[0] = new JButton(); //btn1
button[1] = new JButton(); //btn2
button[2] = new JButton(); //btn3
button[3] = new JButton(); //btn4
And access it
JButton but = button[Integer.parseInt(buttonString)-1];
Or by utilizing the possibility of adding custom properties to UI elements (you'll need a JComponent for that)
getContentPane().putClientProperty("btn1", btn1);
and later retrieving whith
JButton but = (JButton)getContentPane().getClientProperty("btn1");
I agree with Kevin's comment. The best concrete Map<K,V> class is probably Hashtable<K,V>. You don't even need to create the button name, just associate an integer with it if they are all numbered (and if btnFillNumber can be 0).
Hashtable<Integer,JButton> buttonTable = new Hashtable<>();
// Fill buttonTable with buttons
JButton button = buttonTable.get(num);
if (button != null) {
// Do something with button
}
Because of autoboxing, you don't need to create Integer objects to query the hashtable, num can be an int primitive.
I'm trying to make a game where the button would light up and the user would have to press the button in a given time.
Currently, my program has 12 buttons that do something. I'm trying to make it so that these buttons are randomly called by the program. So far, I just have these for 12 buttons that just change the text when pressed by the user.
Now I need a way of making it so that they are randomly pressed the program itself and not the user. Any idea's on how this is done in java?
// **** Panels for buttons ****
JPanel panelButtons = new JPanel(); // making the panel for the buttons
panelButtons.setLayout(new GridLayout(3, 4)); // setting the layout of the buttons to 3x4 as shown above
b1 = new JButton(" ⃝"); // creating button and setting its default text
b1.setFont(fontText); // setting the font
b1.addActionListener(new ActionListener(){ // action listener to do something when pressed
public void actionPerformed(ActionEvent e) {
sendMessage(user + "1" ); // sends the name of the user that pressed the button and which button
String field1 = b1.getText(); // gets the text from the button and stores it in a String
if(field1 == " ⃝"){ // checks if the string is equal to an empty circle
b1.setText("⬤"); // if true then change to a full circle
}
else if (field1 == "⬤"){ // opposite of the above if statement
b1.setText(" ⃝");
}
}
});
panelButtons.add(b1); // adding the button to the panel
b2 = new JButton(" ⃝"); // creating button and setting its default text
b2.setFont(fontText); // setting the font
b2.addActionListener(new ActionListener(){ // action listener to do something when pressed
public void actionPerformed(ActionEvent e) {
sendMessage(user + "2" ); // sends the name of the user that pressed the button and which button
String field2 = b2.getText(); // gets the text from the button and stores it in a String
if(field2 == " ⃝"){ // checks if the string is equal to an empty circle
b2.setText("⬤"); // if true then change to a full circle
}
else if (field2 == "⬤"){ // opposite of the above if statement
b2.setText(" ⃝");
}
}
});
panelButtons.add(b2); // adding the button to the panel
You can create a list that holds your button. Use the random number generator to create a random number within the length of the list. Use that (random) index to modify the corresponding button.
Put your twelve buttons in an ordered collection.
Put your twelve corresponding actions in another ordered collection in form of a Consumer<JButton>'(useCallable`(and ignore the return) or just create something like that if you are not using java 8).
Perform a mapping from the Button collection to the action collection.
Create a class implementing ActionListener like this:
private static class Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
button2action.get((JButton)e.getSource()).accept(a);
}
}
pick up a random element from the value set of the map if you want to get random button pressed.
int randomIndex = new random().nextInt(button2action.entrySet().size());
Iterator<Entry<JButton, Consumer<JButton>>> iter = button2action.entrySet().iterator();
for (int i = 0; i < randomIndex; i++){
Entry<JButton, Consumer<JButton>> entry = iter.next();
}
entry.getValue().accept(entry.getKey());
add new button action pairs to the map if you want to add new buttons.
I'm trying to make randomized JTextField's yellow by using Arrays. I've only managed to make 1 textfield yellow, and then white after 1 sec at each click. What I want to do is when you press the button the first randomized Textfield get yellow and then white. And when you press the second time the first randomzied textfield AND the seconds will turn yellow and then White and so on.. The array works as you can see I Printing it and when you press the button it prints all the randomized numbers in order.
The problem is that JTextField can't handle int's, and it apparently have to be "Final" so it makes it very hard to make multiply JTextField's yellow. I pasted my arrays to you so that you can get a better understanding what I'm trying to do. Does anyone know the solution?
//my Arrays
JTextField[] boxes = new JTextField[9]; //Array for the textfields
int[] clicked = new int[100];
int clickAmount = 0;
//At startup it fills the boxes array with the textfield:
boxes[0] = textfield1;
boxes[1] = textfield2;
boxes[2] = textfield3;
boxes[3] = textfield4;
boxes[4] = textfield5;
boxes[5] = textfield6;
boxes[6] = textfield7;
boxes[7] = textfield8;
boxes[8] = textfield9;
public void timePaus (final JTextField textfield) {
new Timer(1000, new ActionListener() {
public void actionPerformed (ActionEvent e) {
textfield.setBackground(Color.white);
// stop the timer
((Timer) e.getSource()).stop();
}
}).start();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { //Button
int randomint = this.randomBox(); //Finds a number between 0-8
final JTextField ThatTextfield = boxes[randomint]; //Puts a textfield into an array
clicked[clickAmount] = randomint+1; //adds textfield number into an array
clickAmount++;
ThatTextfield.setBackground(Color.yellow); //make choosen textfield yellow
for (int i = 0; i < clickAmount; i++)
{
timePaus(ThatTextfield); //make choosen textfield white after 1 sec
System.out.println(clicked[i]);
}
}
Considerations:
Place your JTextFields in an ArrayList<JTextField>, but create them in a for loop for the sake of avoiding unnecessary repetation.
When you want to randomize the ArrayList, call Collections.shuffle(myTextFieldList) on your List of JTextFields.
Give your class an int maxIndex field.
In your Swing timer, iterate through the now randomized List of JTextFields, displaying each one up to the value held by the maxIndex and not above the size of the List.
Increment the maxIndex in the timer.
Alternatively, you could create two more ArrayList<JTextField>, one to shuffle the collected text fields. Then remove the 0th JTextField from this list in your button's listener, and place it into the other ArrayList, and then iterate through the 2nd ArrayList's JTextfield in your Timer.
I am creating a hangman game. I made a button A - Z using the GUI Toolbars in Netbeans as follows:.
My problem is, how can I add an actionlistener to all of it. Is it possible to use a loop? If i click the button A, i will get the character 'a' and so on..
Yes it is possible to use a loop, but since your JButtons were created by using NetBeans code-generation, they won't be in an array or collection initially, and so this is something that you'll have to do: create an array of JButton and fill it with the buttons created by NetBeans. Then it's a trivial matter to create a for loop and in that loop add an ActionListener that uses the ActionEvent's actionCommand (as noted above) in its logic.
Having said this, I think that the better solution is to forgo use of the NetBean's GUI builder (Matisse) and instead to create your Swing code by hand. This will give you much greater control over your code and a much better understanding of it as well. For instance, if you do it this way, then in your for loop you can both create your buttons, add the listeners, and add the button to its container (JPanel).
e.g.,
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Foo2 {
public static void main(String[] args) {
JPanel buttonContainer = new JPanel(new GridLayout(3, 9, 10, 10));
List<JButton> letterButtons = new ArrayList<JButton>(); // *** may not even be necessary
for (char buttonChar = 'A'; buttonChar <= 'Z'; buttonChar++) {
String buttonText = String.valueOf(buttonChar);
JButton letterButton = new JButton(buttonText);
letterButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
System.out.println("actionCommand is: " + actionCommand);
// TODO fill in with your code
}
});
buttonContainer.add(letterButton);
letterButtons.add(letterButton);
}
JOptionPane.showMessageDialog(null, buttonContainer);
}
}
Well, with some pseudo code, wouldn't this make sence for you?
for(button in bord) {
button.addActionListener(my_actionlistener);
}
Then in your actionlistener you can see which button was pressed
public void actionPerformed(ActionEvent e) {
// button pressed
if ("string".equals(e.getActionCommand()) {
// do something
}
// and so forth
}
You'll need to add the buttons to a list of some kind so you can iterate through them, Netbeans doesn't do this for you when you generate the buttons.
After that, just run a for each loop on the list containing all the buttons. To get the values of the characters just cast the relevant ascii value, which starts at 97 for a lower case a or 65 for an upper case A:
int charNum = 97;
for(Button b : board) {
char charVal = (char)charNum;
charNum++;
//add the action listener
}