Can't get the next JFrame to pop up - java

I'm making the game of battleship and I can't get the JFrame with the win panel nor the JFrame with the lose panel to pop up when the player wins or loses. Any ideas why? I'm thinking it just never gets to the other two loops in the main program, but I'm not sure. I did check to make sure that the global variables correct and incorrect were incrementing correctly, and they are.
//Battleship.java
import javax.swing.*;
import java.awt.*;
import java.util.Scanner;
import java.io.*;
import javax.swing.JOptionPane;
public class Battleship
{
public static String name;
public static void main (String[] args) throws IOException
{
Battleship.name = JOptionPane.showInputDialog("What is your name?");
String answer = JOptionPane.showInputDialog("Welcome to Battleship, "+name+". Would you like instructions?"); //(GUI1) Dialog Box
if(answer.equals ("yes") || answer.equals ("Yes"))
{
JOptionPane.showMessageDialog(null,"In this variant of Battleship, you will try to bomb two randomly-placed ships"
+"\nby clicking on the buttons that represent the field of play. There are two ships:"
+"\nOne 1x2 ship and one 1x3 ship. Green is a hit and red is a miss. Good luck!");
}
//Creates a JFrame and adds the Buttons panel to it
JFrame frame = new JFrame("Battleship");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Buttons b = new Buttons(); //(GUI2) 1-D Array of Buttons
Check c = new Check();
NamePanel n = new NamePanel();
JPanel panel = new JPanel(); //Instantiating a panel
panel.add(c);
panel.add(b); //Adds the 1-D Array of buttons to the panel
panel.setBackground(Color.blue);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
frame.getContentPane().add (panel);
frame.pack();
frame.setVisible(true);
frame.getContentPane().validate();
frame.getContentPane().repaint();
if(Buttons.correct == 5 && (Buttons.incorrect+Buttons.correct)<=15)
{
//Creats a new frame and adds the winner's panel to the frame
JFrame frame1 = new JFrame("Winner!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
WinPanel panel2 = new WinPanel();
frame1.getContentPane().add(panel2);
frame1.pack();
frame1.setVisible(true);
}
else if(Buttons.correct<5 && (Buttons.incorrect+Buttons.correct) >= 15)
{
//Creates a new frame and adds the loser's panel to the frame
JFrame frame1 = new JFrame("You lost");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
LosePanel panel2 = new LosePanel();
frame1.getContentPane().add(panel2);
frame1.pack();
frame1.setVisible(true);
}
}
}
//Buttons.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Scanner;
import java.io.*;
import java.util.Random;
import java.util.*;
public class Buttons extends JPanel
{
JButton[] btn;
static int[] numbers = new int[5];
public static int correct = 0;
public static int incorrect = 0;
public Buttons() throws IOException
{
String[] numberLine = choose(new File("Coords.txt")).split(",");
for(int i = 0; i < 5; i++)
{
numbers[i] = Integer.parseInt(numberLine[i]);
}
btn = new JButton[25];
setLayout(new GridLayout(5,5));
setBackground(Color.blue);
setPreferredSize(new Dimension(300,300));
ButtonListener blisten = new ButtonListener(); //LI
for(int i=0;i<25;i++)
{
btn[i] = new JButton();
btn[i].addActionListener(blisten);
add (btn[i]);
}
} //Ends Constructor
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
Object source = event.getSource();
while((Buttons.correct+Buttons.incorrect)<15 && (Buttons.correct<5))
{
for(int i=0;i<25;i++)
if(source==btn[i])
if(i==numbers[0] || i==numbers[1] || i==numbers[2] || i==numbers[3] || i==numbers[4])
{
btn[i].setBackground(Color.green);
btn[i].setEnabled(false);
Buttons.correct++;
System.out.println(Buttons.correct);
}
else
{
btn[i].setBackground(Color.red);
btn[i].setEnabled(false);
Buttons.incorrect++;
System.out.println(Buttons.incorrect);
}
break;
}
}
}
//Choose method to choose a random line of the imported text file
public static String choose(File f) throws FileNotFoundException
{
String result = null; //String is set to null
Random rand = new Random(); //Instantiating a random number generator
int n = 0;
for(Scanner sc = new Scanner(f); sc.hasNext(); ) //for loop-as long as the file has more to read
{
++n; //Incrementing temp variable
String line = sc.nextLine(); //Reading from the file
if(rand.nextInt(n) == 0)
result = line; //String result is now equal to the text imported from the file
}
return result; //Returning the string
}
} //Ends Program
// LosePanel.java
import javax.swing.*;
import java.awt.*;
public class LosePanel extends JPanel
{
public LosePanel()
{
setPreferredSize(new Dimension(500,500));
setBackground(Color.white);
}
public void paintComponent(Graphics page) //DR
{
super.paintComponent(page);
page.drawOval(165,165,150,150);
page.fillOval(165+47,165+25,10,10);
page.fillOval(165+92,165+25,10,10);
page.drawArc(165+45,165+80,60,30,0,180);
page.drawString("Better luck next time", 182,90);
}
}
// WinPanel.java
import javax.swing.*;
import java.awt.*;
public class WinPanel extends JPanel
{
public WinPanel()
{
setPreferredSize(new Dimension(500,500));
setBackground(Color.white);
}
public void paintComponent(Graphics page) //(DR)
{
super.paintComponent(page);
page.drawOval(165,165,150,150);
page.fillOval(165+47,165+25,10,10);
page.fillOval(165+92,165+25,10,10);
page.drawArc(165+46,165+70,60,30,0,-180);
page.drawString("You've won the game! Congratulations!", 150,90);
}
}

Guis are event driven frame works. That is, the user does something and you respond to it
Basically, what's happening, is you're checking the state of Buttons before anythings actually being done.
Take a look at Creating a GUI in Swing, How to use buttons and How to write an Action Listener for some ideas, examples and suggestions on writing GUI's

Related

java swing get or set unique id for new JButton while create thim on for loop

i have java swing Class that create JButton
it is working but what i need is when i pressed a JButton lets seed that it is number 1 the code in the ActionEvent is to change the Background of the JButton but what i need is if i pressed another JButton the first one i need it to go back to red Color :
Example :
package Classes;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class testbtn {
public JFrame frame = new JFrame();
public int copcounter = 5;
public testbtn() {
JPanel jdb = new JPanel();
jdb.setLayout(new FlowLayout());
for (int x = 1; x <= copcounter; x++) {
JButton btn = new JButton();
btn.setText(String.valueOf(x));
if (x == 1) {
btn.setBackground(Color.yellow);
} else {
btn.setBackground(Color.red);
}
btn.putClientProperty("id", x);
btn.addActionListener((ActionEvent e) -> {
btn.setBackground(Color.yellow);
System.out.println(e.getID());
});
jdb.add(btn);
}
frame.add(jdb);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new testbtn();
}
});
}
}
this code will show form like this :
when i press JButton 4 the output become like this :
but i need it to be like this so the other button will become red color but what i pressed i need it to become yellow ! :
i know that i can use id but how to get the id for them ! or if there is better way ?
No need for an id, simply put all the JButtons into a List<JButton>, say called buttonList, and then iterate through the list in the button's ActionListener, turning backgrounds red for all the buttons in the list, and then turn the current button's background yellow.
And then in the code that uses it:
public void actionPerformed(ActionEvent e) {
// iterate through the list
for (JButton button : buttonList) {
button.setBackground(Color.RED);
}
// then set *this* button's color yellow:
((JButton) e.getSource).setBackground(Color.YELLOW);
}
That's it
or for your code...
public class TestBtn {
public JFrame frame = new JFrame();
public int copcounter = 5;
private List<JButton> buttonList = new ArrayList<>();
public TestBtn() {
JPanel jdb = new JPanel();
jdb.setLayout(new FlowLayout());
for (int x = 1; x <= copcounter; x++) {
JButton btn = new JButton();
// add this
buttonList.add(btn);
btn.setText(String.valueOf(x));
if (x == 1) {
btn.setBackground(Color.yellow);
} else {
btn.setBackground(Color.red);
}
// btn.putClientProperty("id", x);
btn.addActionListener((ActionEvent e) -> {
// iterate through the list
for (JButton button : buttonList) {
button.setBackground(Color.RED);
}
// then set *this* button's color yellow:
((JButton) e.getSource).setBackground(Color.YELLOW);
// show button text
System.out.println(e.getActionCommand());
});
jdb.add(btn);
}
frame.add(jdb);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new testbtn();
}
});
}
}
Also, the ActionEvent's actionCommand String should match the button's text (with some exceptions).

Using JTextFields, JButtons and JLabels on JFrame with ActionListener and if-else Statement Jbutton Does Not Work

I am new to Java and am trying to do my first project. The code below has a button that when clicked, nothing happens. I am working on Eclipse and there are no exceptions thrown.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MTV extends JFrame implements ActionListener {
public JTextField kutucuk1, kutucuk2, kutu3;
public JLabel kutu1, kutu2;
public JButton buton1;
int yas, motorhacmi;
public MTV() {
setLayout(new GridLayout (3,3));
kutu1 = new JLabel("Aracınızın yası");
kutucuk1 = new JTextField(yas);
kutu2 = new JLabel("Aracınızın Motor Hacmi");
kutucuk2 = new JTextField(motorhacmi);
buton1 = new JButton("Hesapla");
kutu3 = new JTextField();
setTitle("MTV Hesaplama");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 500);
setVisible(true);
add(kutu1);
add(kutucuk1);
add(kutu2);
add(kutucuk2);
add(buton1);
add(kutu3);
buton1.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
yas = Integer.parseInt(kutucuk1.getText().toString());
motorhacmi = Integer.parseInt(kutucuk2.getText().toString());
if (motorhacmi <= 1300 && (yas <=3 && yas >=1)) {
kutu3.setText("Ödenecek vergi 743");
}
else if ((motorhacmi > 1300 && motorhacmi <= 1600) && (yas <=3 && yas >=1)) {
kutu3.setText("Ödenecek vergi 1294");
}
}
public static void main(String[] args) {
MTV mtv = new MTV();
}
}
try this link Eclipse Gui if you are using eclipse then instead of creating the text Fields and buttons and all this components you will only drag and drop and the code is already written when you select and component
Or add sizes to the JTextFields and also change the placement of all the elements to before the pane creation:
add(kutu1);
add(kutucuk1);
add(kutu2);
add(kutucuk2);
add(buton1);
add(kutu3);
buton1.addActionListener(this);
setTitle("MTV Hesaplama");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 500);
setVisible(true);

Editable JComboBox gives error: <identifier> expected and illegal start of type

I am trying to create and Editable JComboBox to allow the user to type the name of the song to purchase. However when I set tunes.setEditable(true); I get an error... any help will be appreciated!
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JTextArea;
public class JTunes2 extends JFrame implements ItemListener
{
int songNum,songPrice;
int[] songAmount = {2,5,8,1,4,7,12,10,11,3,6,9};
String result;
JComboBox tunes = new JComboBox();
// set as editable
tunes.setEditable(true);
JLabel labelTunes = new JLabel("Song List");
JLabel outputs = new JLabel();
FlowLayout layout = new FlowLayout();
public JTunes2()
{
super("Song Selector");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(layout);
// add song names to combo box and register an item listener.
tunes.addItem("Song1");
tunes.addItem("Song2");
tunes.addItem("Song3");
tunes.addItem("Song4");
tunes.addItem("Song5");
tunes.addItem("Song6");
tunes.addItem("Song7");
tunes.addItem("Song8");
tunes.addItem("Song9");
tunes.addItem("Song10");
tunes.addItem("Song11");
tunes.addItem("Song12");
tunes.addItemListener(this);
panel.add(labelTunes);
panel.add(tunes);
panel.add(outputs);
//add panel to the frame
setContentPane(panel);
}
public void itemStateChanged(ItemEvent e)
{
//create source object
Object source = e.getSource();
//check the type size
if(source == tunes)
{
songNum = tunes.getSelectedIndex();
songPrice = songAmount[songNum];
result = "Total Price $" + songPrice;
//Display result
outputs.setText(result);
}
}
public static void main(String[] args)
{
// create class object
JTunes frame = new JTunes();
frame.setSize(250, 180);
frame.setVisible(true);
}
}
Thank you!
Actually, Java requires that you setup JComponents in the constructor. In order for your code to work, you need to call on setEditable(true) in the constructor, which means that you just need to move tunes.setEditable(true); to the constructor.
Tip: always allocate memory for JComponents in the constructor (you want to draw the components as soon as you create the Jframe). You can have a reference to the JComboBox at the class level.
Here is another version of your code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JTextArea;
public class JTunes2 extends JFrame implements ItemListener
{
int songNum,songPrice;
int[] songAmount = {2,5,8,1,4,7,12,10,11,3,6,9};
String result;
JComboBox tunes;
JLabel labelTunes = new JLabel("Song List");
JLabel outputs = new JLabel();
FlowLayout layout = new FlowLayout();
public JTunes2()
{
super("Song Selector");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(layout);
tunes = new JComboBox();
// set as editable
tunes.setEditable(true);
// add song names to combo box and register an item listener.
tunes.addItem("Song1");
tunes.addItem("Song2");
tunes.addItem("Song3");
tunes.addItem("Song4");
tunes.addItem("Song5");
tunes.addItem("Song6");
tunes.addItem("Song7");
tunes.addItem("Song8");
tunes.addItem("Song9");
tunes.addItem("Song10");
tunes.addItem("Song11");
tunes.addItem("Song12");
tunes.addItemListener(this);
panel.add(labelTunes);
panel.add(tunes);
panel.add(outputs);
//add panel to the frame
setContentPane(panel);
}
public void itemStateChanged(ItemEvent e)
{
//create source object
Object source = e.getSource();
//check the type size
if(source == tunes)
{
songNum = tunes.getSelectedIndex();
songPrice = songAmount[songNum];
result = "Total Price $" + songPrice;
//Display result
outputs.setText(result);
}
}
public static void main(String[] args)
{
// create class object
JTunes2 frame = new JTunes2();
frame.setSize(250, 180);
frame.setVisible(true);
}
}
You added the tunes.setEditable(true) at the class level, instead of at the method level. No statements allowed at the class level!
Here's a fixed version: I renamed JTunes2 to JTunes to fix the compilation errors, and moved the setEditable to the constructor. Also I fixed the indentation - this makes it harder to make this mistake:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JTextArea;
public class JTunes extends JFrame implements ItemListener
{
int songNum,songPrice;
int[] songAmount = {2,5,8,1,4,7,12,10,11,3,6,9};
String result;
JComboBox tunes = new JComboBox();
JLabel labelTunes = new JLabel("Song List");
JLabel outputs = new JLabel();
FlowLayout layout = new FlowLayout();
public JTunes()
{
super("Song Selector");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(layout);
tunes.setEditable(true);
// add song names to combo box and register an item listener.
tunes.addItem("Song1");
tunes.addItem("Song2");
tunes.addItem("Song3");
tunes.addItem("Song4");
tunes.addItem("Song5");
tunes.addItem("Song6");
tunes.addItem("Song7");
tunes.addItem("Song8");
tunes.addItem("Song9");
tunes.addItem("Song10");
tunes.addItem("Song11");
tunes.addItem("Song12");
tunes.addItemListener(this);
panel.add(labelTunes);
panel.add(tunes);
panel.add(outputs);
//add panel to the frame
setContentPane(panel);
}
public void itemStateChanged(ItemEvent e)
{
//create source object
Object source = e.getSource();
//check the type size
if(source == tunes)
{
songNum = tunes.getSelectedIndex();
songPrice = songAmount[songNum];
result = "Total Price $" + songPrice;
//Display result
outputs.setText(result);
}
}
public static void main(String[] args)
{
// create class object
JTunes frame = new JTunes();
frame.setSize(250, 180);
frame.setVisible(true);
}
}

Changing text of JLabel in ActionEvent

OK, so I'm creating a Tic Tac Toe GUI. I currently having a working frame of 3x3 buttons that will change to either an X or O. My issue is implementing a JLabel on the top of the buttons. The label keeps track of who's turn it is and will change from either "O's turn" or "X's turn" however I can't seem to get the JLabel to update (only spouts errors). Here's a portion of my code showing how Trying to implement this. The program runs fine but as soon as I add the (turn.setText("O's turn");) I get errors.
Any feedback as to why this may not be working would be appreciated.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TicTacToe extends JFrame {
XOButton[] xob = new XOButton[9];
private JLabel turn;
public static int state;
public TicTacToe() {
super("TicTacToe");
//add XOButtons to panel
JPanel center = new JPanel();
state = 0;
JLabel turn = new JLabel("X's turn");
center.setLayout(new GridLayout(3, 3, 2, 2));
//action listener
ButtonListener bl = new ButtonListener();
for (int i = 0; i < 9; i++) {
xob[i] = new XOButton();
xob[i].addActionListener(bl);
center.add(xob[i]);
}
//add panel to frame
setLayout(new BorderLayout());
add(center, BorderLayout.CENTER);
add(turn, BorderLayout.NORTH);
}
//inner action listener class
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent ae) {
for (int i = 0; i < 9; i++) {
if(ae.getSource() == xob[i] && xob[i].getState() == XOButton.NONE && state == 0) {
xob[i].setState(XOButton.X);
state = 1;
//turn.setText("O's turn");
} else if(ae.getSource() == xob[i] && xob[i].getState() == XOButton.NONE && state == 1) {
xob[i].setState(XOButton.O);
state = 0;
}
}
}
}
}
Guess: your error is a NullPointerException because turn is null. Solution: don't shadow the variable. In other words you're re-declaring the turn variable in the constructor leaving the field null.
e.g.,
public class TicTacToe extends JFrame{
XOButton[] xob = new XOButton[9];
private JLabel turn;
public static int state;
public TicTacToe() {
super("TicTacToe");
//add XOButtons to panel
JPanel center = new JPanel();
state = 0;
JLabel turn = new JLabel("X's turn"); // **** you're re-declaring turn here!
Better:
public class TicTacToe extends JFrame{
XOButton[] xob = new XOButton[9];
private JLabel turn;
public static int state;
public TicTacToe() {
super("TicTacToe");
//add XOButtons to panel
JPanel center = new JPanel();
state = 0;
turn = new JLabel("X's turn"); // **** Note the difference?
In the future, if you have similar problems, please post the entire error message and indicate which line throws the exception as it will help us immensely!

CardLayout to close on last card

So I have a JPanel with a CardLayout.
this CardLayout, as expected, manages the switching of panels in the frame.
The switching is done by two buttons: "Back" and "Next".
I want to know if there is a way to close the whole application (i.e. call System.exit(0)) when it is on the last card and "Next" is pressed again.
I have looked for a solution everywhere, but I can't find anything.
The problem is: I don't know how to check which is the last one.
Here is the listener excerpt of my code:
public void actionPerformed(ActionEvent arg0) {
CardLayout l = (CardLayout) holder.getLayout();
if(arg0.getSource() == opt[1]){ //opt[1] is the "Next" button
//Insert if statement here to check if
//the CardLayout is on the last card
{
System.exit(0);
} else {
l.next(holder); //holder is the JPanel with the CardLayout
}
}
}
What about dispose() which is inherited from Window? Make sure you set:
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFrame frame = ...
// ...
frame.setVisible(false); // hide the GUI
frame.dispose(); // destroy and release the GUI resources
For example:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CardLayoutGUI
{
private JFrame frame;
private JButton btnBack;
private JButton btnNext;
private CardLayout cLayout;
private JPanel panUp;
private JPanel panDown;
private static final String[] cards =
{"card1", "card2", "card3", "card4", "card5"};
private int currentCard = 0;
public void init()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
((JPanel)frame.getContentPane()).setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
btnBack = new JButton("Back");
btnNext = new JButton("Next");
btnBack.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
btnNext.setText("Next");
currentCard--;
cLayout.show(panUp, cards[currentCard]);
if(currentCard == 0) btnBack.setVisible(false);
}
});
btnNext.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
btnBack.setVisible(true);
currentCard++;
if(currentCard == cards.length - 1) // last card
{
btnNext.setText("Exit");
cLayout.show(panUp, cards[currentCard]);
}
else if(currentCard >= cards.length)
{
frame.setVisible(false);
frame.dispose();
}
else
{
cLayout.show(panUp, cards[currentCard]);
}
}
});
cLayout = new CardLayout();
panUp = new JPanel(cLayout);
panDown = new JPanel();
frame.add(panUp, BorderLayout.CENTER);
frame.add(panDown, BorderLayout.SOUTH);
panDown.add(btnBack);
panDown.add(btnNext);
for(int i = 0; i < cards.length; i++) createPanels(panUp, cards[i]);
frame.pack();
frame.setLocationRelativeTo(null);
btnBack.setVisible(false);
}
public void showGUI()
{
frame.setVisible(true);
}
private void createPanels(JPanel container, String label)
{
JPanel pan = new JPanel();
pan.add(new JLabel(label));
container.add(pan, label);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
CardLayoutGUI clg = new CardLayoutGUI();
clg.init();
clg.showGUI();
}
});
}
}
I extended CardLayout to add a few features. One of the features is an isNextCardAvailable() method. See Card Layout Focus for all the features.
The issue is determining which card is the last one. You could use a card String array index to manage the current position of the and use the show method to display the next "card". When you exceed the card array index you can then dispose your JFrame.
If you run the System.exit(0), that close all aplication, but if you only close the JFrame you can use JFrameObject.dispose().

Categories

Resources