Replacing component in panel without it going to the end? - java

I am working on a program that has no errors when I compile, and the logic runs soundly for it's purpose (I'm making a basic Penny Pitch program in GUI). The board is filled with image icons that contain the number of points a player will receive if they land on it, and when they land on a spot the image icon is suppose to switch to a picture of the same spot with a penny on it. However, when the previous icon is removed and the new "occupied" one is assigned, it is assigned at the end of the panel rather than the previous spot the "empty" icon was taken from.
To illustrate:
this is the normal layout,
before "tossing" a penny,
and this is the shifted layout,
after "tossing" a penny.
I can't find any sources explaining how to add a component to a panel in a spot previously occupied by a removed component. If anyone knows how, it would be great help!
-----------------------------------EDIT-----------------------------------------
New pictures:,.
I'm using a GridBagLayout now, and since I'm still not sure what is the cause of the new added component not taking the space of the removed one, I cut down my entire program to illustrate it's aspects:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class PennyPitch extends JFrame implements ItemListener{
//variables
int aa=0, thrown=0, place=0, illit=1, illit2=1;
Random pitch = new Random();
private ImageIcon full = new ImageIcon("pitchFull.png");
//map
private Map tossing;
//jbuttons
private JButton confirm = new JButton (new ImageIcon("pitchPenny.png"));
//map
private Map<Integer, ColorPanel> spot = new HashMap<Integer, ColorPanel>();
//declared icon to use when button is pushed
private ColorPanel rSet = new ColorPanel(Color.white, full);
//panel
private JPanel input = new JPanel(new GridBagLayout ());
private GridBagConstraints c = new GridBagConstraints();
public PennyPitch(){
prepareGUI();
}
public static void main(String[] args){
PennyPitch pitch = new PennyPitch(); }
private void prepareGUI(){
//background
input.setBackground(Color.WHITE);
//button design
confirm.setBorder(BorderFactory.createEmptyBorder());
confirm.setContentAreaFilled(false);
//icon for use
ImageIcon one = new ImageIcon("pitchOne.png");
//components for map
ColorPanel i1 = new ColorPanel(Color.white, one);
ColorPanel i2 = new ColorPanel(Color.white, one);
ColorPanel i3 = new ColorPanel(Color.white, one);
//MAP FOR THE STATS
spot.put(1, i1);
spot.put(2, i2);
spot.put(3, i3);
//PANEL
c.ipady = 50;
c.ipadx = 50;
c.gridx = 1;
c.gridy = 1;
c.gridwidth = 1;
input.add(spot.get(1),c);
c.ipady = 50;
c.ipadx = 50;
c.gridx = 2;
c.gridy = 1;
c.gridwidth = 1;
input.add(spot.get(2),c);
c.ipady = 50;
c.ipadx = 50;
c.gridx = 3;
c.gridy = 1;
c.gridwidth = 1;
input.add(spot.get(3),c);
c.ipady = 50;
c.ipadx = 50;
c.gridx = 4;
c.gridy = 1;
c.gridwidth = 2;
input.add(confirm,c);
//listener for button
confirm.addActionListener (new AddListener());
//CONTAINER
Container container = getContentPane();
container.add(input);
//frame information
Toolkit tk = Toolkit.getDefaultToolkit();
setSize(600, 600);
setTitle("PENNY PITCH");
setMinimumSize(new Dimension(600,600));
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack ();
setVisible(true);
}
private class AddListener implements ActionListener {
public void actionPerformed(ActionEvent a){
if (a.getSource()== confirm) {
//generates number to land on
thrown = pitch.nextInt(3) + 1;
System.out.println(thrown);
place=illit;
spot.put(place, rSet);
Component old = input.getComponent(thrown);
Component newn = input.getComponent(place);
Component[] compSet=input.getComponents();
for(int i=0; i<compSet.length; i++){
if(old.equals(compSet[i])) {
input.remove(old);
c.ipady = 50;
c.ipadx = 50;
c.gridwidth = 1;
input.add(newn, i);
}
}
illit++;
repaint();
}
}
}
public void itemStateChanged(ItemEvent e) {
System.out.println (aa);
}
}
class ImageLabel extends JLabel {
public ImageLabel (String img){
this (new ImageIcon (img));
}
public ImageLabel (ImageIcon icon){
setIcon(icon);
setIconTextGap(0);
setBorder(null);
setText(null);
setSize(icon.getImage().getWidth(null),icon.getImage().getHeight(null));
}
}

Container has a method getComponents(). JPanel is a descendant and will hopefully have it. To check for a given component you do the following:
Component[] cmp=myPanel.getComponents();
for(int i=0; i<cmp.length; i++)
if(myComponent.equals(cmp[i])) {
myPanel.remove(myComponent);
myPanel.add(myNewComponent, i);
}
where myComponent is the component you want to remove and myNewComponent is the component you want to add.
--
Ok your code uses some ColorPanel which I'm not familiar with but lets suppose its something like a JLabel.
I understand that you actually add (in the full code) as many colorpanels as coins in the image.
GridBag is out of my consideration - but maybe you should just skip the ipadx etc and just remove/add. Better yet use some /normal/ layout such as GridLayout or even FlowLayout for testing purposes.
Suggestion: have a JPanel (input) with a GridLayout(5, 5) where you add only the color panels (numbers). Have another JPanel (jp2) where you add the previous JPanel (input) and the button(confirm) - this jp2 is added to the jframe. You should add/remove on the input.
for(i=0; i<25; i++) input.add(new ColorPanel(...));
thrown = pitch.nextInt(25);
System.out.println(thrown);
place=illit;
spot.put(place, rSet);
input.remove(thrown);
Component newn = input.getComponent(place);
input.add(newn, thrown);
Also make sure you call validate after each removal/addition:
input.validate();
In summary, the following is a simplified working program of what you are trying to do:
class T extends Frame {
public T() {
setSize(500, 500);
setLayout(new GridLayout(5, 5));
for(int i=0; i<25; i++) add(new Label(""+i));
setVisible(true);
}
public static void main(String args[]) {
T t=new T();
for(int i=0; i<5; i++) {
int r=(int)(Math.random()*25);
t.remove(r);
t.add(new Label(""+(i+1)), r);
t.validate();
t.repaint();
try { Thread.sleep(5000); } catch(InterruptedException ie) {}
}
}
}

Related

How to create new and dispose jcomponents multiple times?

(Sorry if this question is not done properly, I'm new. But at least I researched a lot before asking my own question)
Hello. I'm writing a blackjack game in java and it's turning quite massive. My problem is how to handle multiple instances of swing components, I guess you can call it. I can't figure out wether to create the components (such as jpanels and jbuttons) as class level, or in specific methods.
If I create them in their corresponding method, then my action listener can't see them, but if I create them as class level, then they get deleted when I call dispose().
class BlackjackGame extends JFrame implements ActionListener{
public void mainMenu(){
JPanel menuPane = new JPanel(new GridBagLayout()); //Init of main menu
GridBagConstraints c = new GridBagConstraints();
menuPane.setBackground(new Color(125,0,0));
menuPane.setBounds(620,220,175,250);
JLabel menuTitle = new JLabel("Welcome to Blackjack!");//Main menu-content
c.gridx = 1;
c.gridy = 0;
c.insets = new Insets(0,0,20,0);
menuPane.add(menuTitle, c);
JButton playButton = new JButton("Play!");
playButton.addActionListener(this);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
c.ipadx = 25;
c.ipady = 25;
c.insets = new Insets(0,0,0,0);
menuPane.add(playButton, c);
JButton exitButton = new JButton("Exit!");
exitButton.addActionListener(this);
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 3;
menuPane.add(exitButton, c);
JButton rulesButton = new JButton("Set rules.");
rulesButton.addActionListener(this);
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 3;
menuPane.add(rulesButton, c);
this.add(menuPane,0);
}
//This is where I get problems
public void actionPerformed (ActionEvent event){
if(event.getSource() == playButton){
//I want the menuPane to disappear, and a transition into the game.
menuPane.dispose();
//Call method for the rest of the game.
}else if(event .getSource() etcetera etcetera){
etcetera etcetera
}
}
}
When done this way, the actionlistener cannot find my components, such as playButton or menuPane. But if I had introduced them as class level objects:
class BlackjackGame extends JFrame implements ActionListener{
JPanel menuPane = new JPanel(new GridBagLayout());
JLabel menuTitle = new JLabel("Welcome to Blackjack!");
JButton playButton = new JButton("Play!");
JButton exitButton = new JButton("Exit!");
JButton rulesButton = new JButton("Set rules.");
public void mainMenu(){
//Rest of code
}
public void actionPerformed(ActionEvent event){
menuPane.dispose();
//Rest of code
}
}
...then as I call menuPane.dispose(), how can I get it back when I want to call mainMenu() again? If I want to go back to the main menu, then I would need to create a new instance of menuPane, as well as all the buttons, but as they are class level and already disposed I can't.
Please help me, and thank you!
PS. I can post my full code as it is atm if it would help.
Edit: Dan's answer has been accepted, as it was indeed the correct answer and it worked for my specific program very well. Thank you and merry christmas!
First, unless I've misunderstood your code, menuPane.dispose() shouldn't work as JPanel does not have a function called dispose()
The best way to do what you want to do if you want to use the same menuPane for the menu. Instead of menuPane.dispose(); use remove(menuPane); and then add(yourOtherPanel);
Working Example
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class BlackjackGame extends JFrame implements ActionListener {
private JPanel menuPane;
private JLabel menuTitle;
private JButton playButton;
private JButton exitButton;
private JButton rulesButton;
private JPanel otherPane;
private JLabel otherTitle;
private JButton otherButton;
public BlackjackGame() {
mainMenu();
otherPanel();
setSize(400, 400);
setVisible(true);
}
private void mainMenu() {
menuPane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
menuPane.setBackground(new Color(125,0,0));
menuPane.setBounds(620,220,175,250);
menuTitle = new JLabel("Welcome to Blackjack!");
c.gridx = 1;
c.gridy = 0;
c.insets = new Insets(0,0,20,0);
menuPane.add(menuTitle, c);
playButton = new JButton("Play!");
playButton.addActionListener(this);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
c.ipadx = 25;
c.ipady = 25;
c.insets = new Insets(0,0,0,0);
menuPane.add(playButton, c);
exitButton = new JButton("Exit!");
exitButton.addActionListener(this);
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 3;
menuPane.add(exitButton, c);
rulesButton = new JButton("Set rules.");
rulesButton.addActionListener(this);
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 3;
menuPane.add(rulesButton, c);
add(menuPane);
}
private void otherPanel() {
otherPane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
otherPane.setBackground(new Color(125,0,0));
otherPane.setBounds(620,220,175,250);
otherTitle = new JLabel("Welcome to Second Pane!");
c.gridx = 1;
c.gridy = 0;
c.insets = new Insets(0,0,20,0);
otherPane.add(otherTitle, c);
otherButton = new JButton("Go Back!");
otherButton.addActionListener(this);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
c.ipadx = 25;
c.ipady = 25;
c.insets = new Insets(0,0,0,0);
otherPane.add(otherButton, c);
}
public void actionPerformed (ActionEvent event) {
if(event.getSource() == playButton) {
remove(menuPane);
add(otherPane);
validate();
repaint();
} else if(event.getSource() == otherButton) {
remove(otherPane);
add(menuPane);
validate();
repaint();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BlackjackGame());
}
}
Edit for comments
So the java method remove() only removes the object from the container, which in this case is the JFrame. This method does not effect the object it moves so the object can be reused later. Hence why in the code above I can just use the remove() and add() methods without redeclaring or remaking menuPane and otherPane.
As for why I declare the objects like this
`private JPanel menuPane;`
And then initialize like this
menuPane = new JPanel(new GridBagLayout());
This is because I want the ActionListener to be able to see the objects without initializing them straight away. The line private JPanel menuPane; makes the object a global variable and the line menuPane = new JPanel(new GridBagLayout()); makes it into what I am going to use. Doing it this way instead of JPanel menuPane = new JPanel(new GridBagLayout()); also means I can reuse the same variable in multiple methods. For example
private JPanel panel;
private void createPanelOne() {
panel = new JPanel(new FlowLayout());
...
add(panel);
}
private void createPanelTwo() {
panel = new JPanel(new GridBagLayout());
...
add(panel);
}
After doing this, you will have two JPanels in your JFrame and they will be different, but you only need to use one JPanel
This is the other way of declaring it and it makes a local variable. Local variables aren't visible to other methods outside of the method you are using unless you pass them through.
JPanel panel = new JPanel();
I wouldn't say this is a con in the slightest. I think sometimes it is good to use local variables in a method that shouldn't be visible to other methods.
Finally to pass local variables through to other methods you can use arguments in a method you have made. For example
public void setSomeValue(int val) {
someValue = val;
}

Which layout should I be using?

I have created a form with 5 buttons using a GridBagLayout to get this form:
What I want is for The buttons to be bigger and more evenly spaced like this:
Here is my code:
package com.GUI;
import java.awt.Color;
import javax.swing.*;
import com.seaglasslookandfeel.*;
public class JFramePlus extends JFrame{
public JFramePlus(){
super("OmegaBrain");
setSize(1000,800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
getContentPane().setBackground(Color.black);
setResizable(false);
}
}
This is the superclass of the class in question.
package com.GUI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.util.Stack;
class GamePlay extends JFramePlus implements ActionListener{
//Create Stack
Stack sequence = new Stack();
//Declare Variables
String greekSequence;
int stackCount;
int timeLeft;
static int optionNo;
//Create Constraints
GridBagConstraints c = new GridBagConstraints();
//Defining new objects
JLabel timeDisplay, sequenceViewer;
JButton mainMenu, input1, input2, input3, input4, input5;
JPanel timerPane, centerPane, exitPane;
Timer t;
GamePlay(){
//Create Labels
timeDisplay = new JLabel();
sequenceViewer = new JLabel();
//Create Panels
timerPane = new JPanel();
centerPane = new JPanel();
exitPane = new JPanel();
//Change layout of centerPane
centerPane.setLayout(new GridBagLayout());
//Creates JButtons
mainMenu = new JButton("Main Menu");
input1 = new JButton("Ξ");
c.gridx = 0;
c.gridy = 1;
centerPane.add(input1, c);
input2 = new JButton("Ω");
c.gridx = 2;
c.gridy = 1;
centerPane.add(input2, c);
input3 = new JButton("Ψ");
c.gridx = 4;
c.gridy = 1;
centerPane.add(input3, c);
input4 = new JButton("Φ");
c.gridx = 1;
c.gridy = 2;
centerPane.add(input4, c);
input5 = new JButton("Γ");
c.gridx = 3;
c.gridy = 2;
centerPane.add(input5, c);
//Create Timer
t = new Timer(1000, this);
//Changes the size of the font
timeDisplay.setFont(timeDisplay.getFont().deriveFont(64.0f));
//Generate Sequence
sequenceGenerator();
//Add components to panels
timerPane.add(timeDisplay);
centerPane.add(sequenceViewer, c);
exitPane.add(mainMenu);
//add panels to frame
add(timerPane, BorderLayout.LINE_END);
add(centerPane, BorderLayout.CENTER);
add(exitPane, BorderLayout.SOUTH);
//Change colors to fit theme
timeDisplay.setForeground(Color.WHITE);
sequenceViewer.setForeground(Color.WHITE);
timerPane.setBackground(Color.BLACK);
centerPane.setBackground(Color.BLACK);
exitPane.setBackground(Color.BLACK);
//Add ActionListeners to buttons
mainMenu.addActionListener(this);
input1.addActionListener(this);
input2.addActionListener(this);
input3.addActionListener(this);
input4.addActionListener(this);
input5.addActionListener(this);
}
public void sequenceGenerator(){
sequence.push(1 + (int)(Math.random() * optionNo));
stackCount++;
greekSequence = "";
for(int i = 0; i < stackCount; i++){
if (sequence.get(i) == 1){
greekSequence = greekSequence + 'Ξ';
}
}
sequenceViewer.setText(greekSequence);
}
void startTimer() {
t.start();
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if(source == t){
timeDisplay.setText(String.valueOf(timeLeft));
timeLeft--;
if(timeLeft == -1){
t.stop();
}
}
else if(source == mainMenu){
int yesNo = JOptionPane.showConfirmDialog(
null,
"Are you sure you want to exit? Your current score will be saved as it is." ,
"Exit Game?",
JOptionPane.YES_NO_OPTION);
if(yesNo == JOptionPane.YES_OPTION){
dispose();
mainMenu menu = new mainMenu();
}
else{
}
}
}
}
This is a loaded question. I'll start by saying GridBagLayout is just fine for what you're trying to achieve. I think you should invest some time looking into: How to Use GridBagLayout.
You should also look into "Insets" for spacing options, and utilizing gridwidth, gridheight, and maybe even ipadx and ipady when dealing with GridBagConstraints.
You can also use a BoxLayout. (How to use BoxLayout ).
You would be able to position your components as desired and if you want to add space between components, you can add an empty border to your components or put invisible components between them.
You can see this discussion for more information.

I'm new to Java Swing, and coding in general and a code I wrote today is having an odd glitch involving the button.doClick() method.

If someone could review my code for me, give me some pointers etc, I would be very grateful!
So in this game in case you've never played Mastermind, basically three colours are hidden in a specific order and the user has to guess what they are out of four possible colours. The code appears to work fairly well, even though it is currently unfinished, however an odd glitch occurs once the user wins. When the player properly guesses the three hidden colours, they are prompted to press the "Play again" button, which is then supposed to reset the game, which it appears to do, however once the user inputs another colour into the JTextFields designated to do so, the words last entered in those fields are revealed. I have implemented a small line that displays the word "working" on a nearby JLabel to show that the doClick() methods are activating, but the reset button doesn't work as intended, even though the newGame button does. Its an odd glitch, if anyone has a fix or reason for this glitch or any other general improvements you would make my day!
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Summative2 extends JFrame {
static int guessNum;
static String colourGuess[] = new String[3];
static String colourArgument;
static int[] solution = new int[3];
public Summative2() {
for (int x=0;x<3;x++)
{
solution[x] = solution(); //Setting the solution for the first game
}
displayIntro(); //Activating the intro screen to start the program
}
public void displayIntro()
{
JPanel introPanel = new JPanel(new GridBagLayout());
this.getContentPane().add(introPanel);
GridBagConstraints c = new GridBagConstraints(); //The variable name being defined for the layout's constraints
introPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); //Setting the orientation of the Grid layout
c.insets = new Insets(2,2,2,2); //Basic spacing and anchoring
c.anchor = GridBagConstraints.CENTER;
JLabel welcome = new JLabel("Welcome to MASTERMIND");
c.ipady = 40;
c.gridx = 1; //Large welcome label, introducing the game
c.gridy = 0;
c.gridwidth = 3;
introPanel.add(welcome, c);
c.ipady = 0; //Resetting the characteristics of the components back to normal after the large intro message
c.gridwidth = 1;
JButton start = new JButton ("Start");
c.gridx = 1; //The start button
c.gridy = 1;
introPanel.add(start, c);
JLabel space = new JLabel(" ");
c.gridx = 2;
c.ipadx = 10; //Space between the Start and Rules buttons
c.gridy = 1;
introPanel.add(space, c);
c.ipadx= 0;
JButton rulesButton = new JButton("Rules");
c.gridx = 3; //Rules button
c.gridy = 1;
introPanel.add(rulesButton, c);
rulesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
introPanel.setVisible(false);
displayRules("intro"); //Makes the intro panel invisible and activates the rules panel, along with an argument that tells the displayRules method to return the user to the intro screen when they press back after reading the rules
}
});
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
introPanel.setVisible(false); //Makes the intro invisible and starts the main game.
displayGame(false);
}
});
}
public void displayRules(String previousScreen) {
JPanel rulesPanel = new JPanel(new GridBagLayout());
GridBagConstraints r = new GridBagConstraints();
rulesPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.getContentPane().add(rulesPanel);
JTextField rulesText = new JTextField("insert rules here");
rulesText.setEditable(false);
r.gridx = 0;
r.gridy = 0;
r.gridwidth = 3;
r.ipady=100; //Big rules text box` NOT YET FINISHED
r.ipadx = 100;
rulesPanel.add(rulesText, r);
r.gridwidth =1;
r.ipadx=1;
r.ipady=1;
JButton backFromRules = new JButton("Back");
r.gridx = 2; //back button
r.gridy=1;
rulesPanel.add(backFromRules, r);
backFromRules.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
rulesPanel.setVisible(false);
if (previousScreen.compareTo("intro")==0) //When the user presses the back button they are returned to the screen from which they activated the rules screen
{
displayIntro();
}
if (previousScreen.compareTo("game")==0)
displayGame(false);
}
});
}
public void displayGame(boolean restart)
{
JPanel gamePanel = new JPanel(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();
gamePanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.getContentPane().add(gamePanel);
g.anchor=GridBagConstraints.WEST;
g.weightx =1;
int coloursY = 0;
JButton redButton = new JButton("Red");
redButton.setBackground(Color.RED); //the red button, which is red
g.gridx= 0;
g.gridy=coloursY;
gamePanel.add(redButton, g);
JButton greenButton = new JButton("Green");
greenButton.setBackground(Color.GREEN);
g.gridx = 1; //The green button, which is green
g.gridy = coloursY;
gamePanel.add(greenButton, g);
JButton blueButton = new JButton("Blue");
blueButton.setBackground(Color.CYAN); //The blue button, which is cyan
g.gridx =2;
g.gridy=coloursY;
gamePanel.add(blueButton, g);
JButton yellowButton = new JButton("Yellow");
yellowButton.setBackground(Color.yellow); //The yellow button which is yellow
g.gridx=3;
g.gridy=coloursY;
gamePanel.add(yellowButton, g);
g.weightx=0;
g.weighty=0;
JLabel firstGuess = new JLabel("First Block Guess:");//The label for the first guess in each guessing sequence, followed by labels for the seconds and third
g.gridx = 0;
g.gridy=1;
g.gridwidth = 2;
gamePanel.add(firstGuess, g);
JLabel secondGuess = new JLabel("Second Block Guess:");
g.gridx = 0;
g.gridy=2;
gamePanel.add(secondGuess, g);
JLabel thirdGuess = new JLabel("Third Block Guess:");
g.gridx = 0;
g.gridy=3;
gamePanel.add(thirdGuess, g);
JTextField guessOne = new JTextField(""); //The text field where the user can enter thier guess for the first colour in a possible solution
guessOne.setPreferredSize(new Dimension(50,24));
g.gridx = 2;
g.gridy = 1;
guessOne.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
gamePanel.add(guessOne, g);
JTextField guessTwo = new JTextField(""); //Second colour
guessTwo.setPreferredSize(new Dimension(50,24));
g.gridx = 2;
g.gridy = 2;
gamePanel.add(guessTwo, g);
JTextField guessThree = new JTextField(""); //Third
guessThree.setPreferredSize(new Dimension(50,24));
g.gridx = 2;
g.gridy = 3;
gamePanel.add(guessThree, g);
JButton update = new JButton();//The update button, which doesn't exist but I used it as a type of repeatable method for whenever the user presses a colour button
JLabel GOneIndicator = new JLabel("<--"); //These arrows move when the user presses a colour button, letting them know where their next colour guess will be applied
g.gridx = 3;
g.gridy = 1;
gamePanel.add(GOneIndicator, g);
JLabel GTwoIndicator = new JLabel("<--");
g.gridx = 3;
g.gridy = 2;
gamePanel.add(GTwoIndicator, g);
GTwoIndicator.setVisible(false);
JLabel GThreeIndicator = new JLabel("<--");
g.gridx = 3;
g.gridy = 3;
gamePanel.add(GThreeIndicator, g);
GThreeIndicator.setVisible(false);
g.gridwidth = 2;
g.fill = GridBagConstraints.HORIZONTAL;
JButton submitButton = new JButton("SUBMIT"); //Submit guess
g.gridx = 0;
g.gridy = 4;
gamePanel.add(submitButton, g);
JButton resetButton = new JButton("Reset"); //Reset your guess JTextFields
g.gridx = 2;
g.gridy = 4;
gamePanel.add(resetButton, g);
JButton newGame = new JButton("New Game"); //Generates a new solution and presses the reset button
g.gridx = 0;
g.gridy = 5;
gamePanel.add(newGame, g);
JButton rulesButton = new JButton("Rules");
g.gridx = 2; //Displays the rules
g.gridy = 5;
gamePanel.add(rulesButton, g);
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String guess[] = new String[3];
boolean proper = true;
guess[0]= guessOne.getText();
guess[1] = guessTwo.getText();
guess[2] = guessThree.getText();
for (int y = 0;y<3;y++)
{
if ((guess[y].compareToIgnoreCase("blue")!=0) && (guess[y].compareToIgnoreCase("red")!=0) && (guess[y].compareToIgnoreCase("green")!=0) && (guess[y].compareToIgnoreCase("yellow")!=0))
{
proper = false; //If one of the text fields had a word that wasn't one of the colours available for guessing, the user will be told so.
}
}
if (proper)
check(guess);//If everything was in order, check the guess against the solution
else
errorWindow();//Otherwise, nope
}
});
resetButton.addActionListener(new ActionListener() {//Sets all of the textFields blank, the guessnumber to 1 and makes the fiirst arrow appear as if it were the first guess.
#Override
public void actionPerformed(ActionEvent e) {
guessOne.setText("");
guessTwo.setText("");
guessThree.setText("");
guessNum=1;
GOneIndicator.setVisible(true);
GTwoIndicator.setVisible(false);
GThreeIndicator.setVisible(false);
}
});
newGame.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {//Clicks the reset and generates a new solution set.
resetButton.doClick();
for(int d=0;d<3;d++)
solution[d]= solution();
}
});
if (restart)//If this screen was generated from the user pressing the play again button after winning, the game should be automatically reset and new solutions generated, this is bugging out somehow.
{
newGame.doClick();
GOneIndicator.setText("working");
resetButton.doClick();
restart=false;
}
rulesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//more rules display that isnt finished yet
gamePanel.setVisible(false);
displayRules("game");
}
});
update.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//When a colour button is pressed, the next guess Field is filled in order, depending on the last one that was filled
colourGuess[guessNum-1] = colourArgument;
if (guessNum ==1 ){
guessOne.setText(colourArgument);
GOneIndicator.setVisible(false);
GTwoIndicator.setVisible(true);
guessNum++;
}
else if (guessNum ==2){
guessTwo.setText(colourArgument);
GTwoIndicator.setVisible(false);
GThreeIndicator.setVisible(true);
guessNum++;
}
else if (guessNum==3){
guessThree.setText(colourArgument);
GThreeIndicator.setVisible(false);
GOneIndicator.setVisible(true);
guessNum = 1;
}
}
});
redButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) { //Red is put into the next guess slot0
colourArgument = "Red";
update.doClick();
}
});
blueButton.addActionListener(new ActionListener() {//Then blue
#Override
public void actionPerformed(ActionEvent arg0) {
colourArgument = "Blue";
update.doClick();
}
});
yellowButton.addActionListener(new ActionListener() {//Or yellow
#Override
public void actionPerformed(ActionEvent arg0) {
colourArgument = "Yellow";
update.doClick();
}
});
greenButton.addActionListener(new ActionListener() {//or green
#Override
public void actionPerformed(ActionEvent arg0) {
colourArgument = "Green";
update.doClick();
}
});
}
public void check(String guess[])
{
JFrame checkWindow = new JFrame();
checkWindow.setSize(300,100);
JPanel pane = new JPanel(new GridBagLayout());
checkWindow.getContentPane().add(pane); //This is all to set up the initial window generally, and activate the layouts and whatnot
GridBagConstraints c = new GridBagConstraints();
pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
checkWindow.setVisible(true);
c.insets = new Insets(2,2,2,2);
int numGuess[] = new int[3]; //
int colourCount=0;
int positionCount=0; //Converts the information in the textFields to numbers which can be more easily compared
for (int x =0;x<3;x++)
{
if (guess[x].compareToIgnoreCase("red")==0)
{
numGuess[x] = 1;
}
if (guess[x].compareToIgnoreCase("blue")==0)
{
numGuess[x] = 2;
}
if (guess[x].compareToIgnoreCase("green")==0)
{
numGuess[x] = 3;
}
if (guess[x].compareToIgnoreCase("yellow")==0)
{
numGuess[x] = 4;
}
}
for (int z=0;z<3;z++) //Runs through the inputs compared to the solution, finding out how many of the colours were correct, and any of those colours that were in the correct positions
{
boolean guessed = false;
for (int k=0;k<3;k++)
{
if (solution[z] == numGuess[k])
{
guessed = true;
}
}
if (solution[z] == numGuess[z])
positionCount++;
if (guessed)
colourCount++;
}
c.fill=GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
if (positionCount ==3) //If all three positions are correct the user wins
{
JLabel colours = new JLabel(guess[0] + ", " + guess[1] + ", " + guess[2] + " is correct!");
c.gridx=0;
c.gridy=0;
pane.add(colours, c);
JLabel winner = new JLabel("You WIN!");
c.gridx=0;
c.gridy=1;
pane.add(winner, c);
JButton playAgain = new JButton("Play Again");
c.gridx=0;
c.gridy=1;
pane.add(playAgain, c);
playAgain.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//Glitch causing button
for(int x=0;x<3;x++)
{
solution[x] = (int) (Math.random()*4)+1;
}
checkWindow.dispose();
displayGame(true);
}
});
}
else
{
JLabel labelOne = new JLabel(guess[0] + ", " + guess[1] + ", " +guess[2]);//If the user doesn't win, how many correct colours and positions they had are displayed
c.gridx = 0;
c.gridy = 0;
pane.add(labelOne, c);
JLabel colourMessage = new JLabel("You had " + colourCount + " correct colours.");
c.gridx=0;
c.gridy=1;
pane.add(colourMessage, c);
JLabel positionMessage = new JLabel("You had " + positionCount + " in the correct positions");
c.gridx=0;
c.gridy=2;
pane.add(positionMessage, c);
}
}
public void errorWindow()
{
JFrame checkWindow = new JFrame();
checkWindow.setSize(200,100);
JPanel pane = new JPanel(new GridBagLayout());//This window is displayed if the user inputs impossible values for their colour guesses
checkWindow.getContentPane().add(pane);
GridBagConstraints c = new GridBagConstraints();
pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
checkWindow.setVisible(true);
JLabel whoops = new JLabel("Try Again with valid colours.");
c.gridx=0;
c.gridy=0;
pane.add(whoops, c);
}
public static void main(String[] args) {
Summative2 frame = new Summative2(); //main method making the JFrame work properly
guessNum = 1;
frame.pack();
frame.setVisible(true);
frame.setSize(300, 225);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static int solution()
{
return (int) (Math.random()*4+1);//Solution method returning random numbers between 1 and 4 for solutions.
}
}
Every time you call the check() method, you're creating new ActionListener and registering it on the playAgain button.
This way, you get lots and lots of action listeners, and once the user finally clicks the playAgain button, they are all called, one by one.
You can see that yourself by setting a breakpoint inside the ActionListener code and debugging the application.
The solution would be to move that logic out of the check() method, to someplace where the form is initialized.

Vertical alignment of checkboxes

Could you help me understand how to set left vertical alignment to the checkboxes. I mean each checkbox on its own row.
Tried everything I could imagine and have come to the end of my wit.
public class DisplayFrame extends JFrame {
public DisplayFrame(ArrayList<String> contents){
DisplayPanel panel = new DisplayPanel(contents, whiteList);
add(panel);
}
private void displayAll(){
DisplayFrame frame = new DisplayFrame(contents, whiteList);
GridBagLayout gbl = new GridBagLayout();
frame.setLayout(gbl);
frame.setVisible(true);
...
}
public class DisplayPanel extends JPanel {
ArrayList<JCheckBox> cbArrayList = new ArrayList<JCheckBox>();
ArrayList<String> contents;
...
public DisplayPanel(ArrayList<String> contents){
...
createListOfCheckBoxes();
}
private void createListOfCheckBoxes() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = contents.size() + 1;
gbc.gridheight = contents.size() + 1;
for (int i = 0; i < contents.size(); i++){
gbc.gridx = 0;
gbc.gridy = i;
String configuration = contents.get(i);
JCheckBox currentCheckBox = new JCheckBox(configuration);
if (whiteList.contains(configuration)){
currentCheckBox.setSelected(true);
}
currentCheckBox.setVisible(true);
add(currentCheckBox, gbc);
}
}
"If I were able to proceed without GridBagLayout, that would suit me"
You can just use a BoxLayout. Box is a convenience class for BoxLayout. You can just do
Box box = Box.createVerticalBox();
for (int i = 0; i < contents.size(); i++){
String configuration = contents.get(i);
JCheckBox currentCheckBox = new JCheckBox(configuration);
if (whiteList.contains(configuration)){
currentCheckBox.setSelected(true);
}
box.add(currentCheckBox);
}
Since Box is a JComponent, you can just add the box to a container.
You can see more at How to Use BoxLayout
Simple Example
import javax.swing.*;
public class BoxDemo {
public static void main(String[] args) {
Box box = Box.createVerticalBox();
JCheckBox cbox1 = new JCheckBox("Check me once");
JCheckBox cbox2 = new JCheckBox("Check me twice");
JCheckBox cbox3 = new JCheckBox("Check me thrice");
box.add(cbox1);
box.add(cbox2);
box.add(cbox3);
JOptionPane.showMessageDialog(null, box);
}
}

simple GUI not showing up?

Ok so, when I run it, it works all fine but it just doesn't pop up with the answer.
What did I do wrong?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class AF implements ActionListener{
double length;
double width;
double answer;
JTextField twidth;
JTextField tlength;
void AFWindow() {
JFrame AFwindow = new JFrame();
JPanel pan2 = new JPanel(new GridBagLayout());
AFwindow.setVisible(true);
AFwindow.setSize(250, 150);
AFwindow.setResizable(false);
GridBagConstraints c = new GridBagConstraints();
AFwindow.add(pan2);
pan2.setBackground(Color.LIGHT_GRAY);
c.gridx = 0;
c.gridy = 5;
tlength = new JTextField();
tlength.setText(" Length ");
pan2.add(tlength, c);
c.gridx = 0;
c.gridy = 0;
twidth = new JTextField();
twidth.setText(" Width ");
pan2.add(twidth, c);
JButton Find = new JButton("Ok");
c.gridx = 0;
c.gridy = -5;
pan2.add(Find);
Find.addActionListener(this);
Find.setActionCommand("ok");
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("ok")){
try {
this.length = Double.parseDouble(tlength.getText());
this.width = Double.parseDouble(twidth.getText());
}
catch(NumberFormatException ex){
System.out.println("There was an issue!");
}
}
}
int area = (int) (length * width);
public void answer(){
JFrame answer = new JFrame();
answer.setVisible(true);
answer.setBackground(Color.yellow);
JPanel pan2 = new JPanel();
JLabel howanswer = new JLabel("Your answer is" + area + "We got this by multiplying the length and width");
pan2.add(howanswer);
}
}
That code has multiple issues. Forgot to document them, but look at this code for the beginnings of the fixes.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class AF implements ActionListener{
double length;
double width;
JTextField twidth;
JTextField tlength;
JFrame AFwindow;
void AFWindow() {
AFwindow = new JFrame();
JPanel pan2 = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
AFwindow.add(pan2);
pan2.setBackground(Color.LIGHT_GRAY);
pan2.setBorder(new EmptyBorder(100,100,100,100));
c.gridx = 0;
c.gridy = 5;
tlength = new JTextField();
tlength.setText(" Length ");
pan2.add(tlength, c);
c.gridx = 0;
c.gridy = 0;
twidth = new JTextField();
twidth.setText(" Width ");
pan2.add(twidth, c);
JButton Find = new JButton("Ok");
c.gridx = 0;
c.gridy = -5;
pan2.add(Find);
Find.addActionListener(this);
Find.setActionCommand("ok");
AFwindow.pack();
AFwindow.setLocationByPlatform(true);
AFwindow.setVisible(true);
}
int area;
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("ok")){
try {
this.length = Double.parseDouble(tlength.getText());
this.width = Double.parseDouble(twidth.getText());
area = (int) (length * width);
answer();
}
catch(NumberFormatException ex){
ex.printStackTrace();
// System.out.println("There was an issue!");
// Can you vague that up for me?!?!
JOptionPane.showMessageDialog(AFwindow, ex);
}
}
}
public void answer(){
JPanel pan2 = new JPanel();
JLabel howanswer = new JLabel("Your answer is " + area + " We got this by multiplying the length and width");
pan2.add(howanswer);
JOptionPane.showMessageDialog(AFwindow, pan2);
}
public static void main(String[] args) {
System.out.println("Hi!");
new AF().AFWindow();
}
}
Are you expecting the answer frame to pop up when you push the OK button? If so, you need to call the answer method:
if (e.getActionCommand().equalsIgnoreCase("ok")){
try {
this.length = Double.parseDouble(tlength.getText());
this.width = Double.parseDouble(twidth.getText());
answer(); // <--- This is missing
}
Also, some other things you need to do:
Generally, you should call JFrame.setVisible at the end of your GUI construction method, after you have added components to the frame. I have shown this in the example below, but you should move setVisible(..) to the bottom of the AFwindow() method as well.
When you do int area = (int) (length * width); outside of any method, this statement will be interpreted as an instance variable initialization and occur when you instantiate the AF object. And when the object is instantiated, you have not yet assigned any values to length and with. Hence, area will always be 0. Move that statement to the inside of the answer function instead.
You forgot to add the actual components to the frame in the answer method. Hence, when you set the frame to visible, only an empty frame will be displayed.
Here are examples of some suitable changes:
public void answer(){
int area = (int) (length * width); // <--- Move this inside answer method
JFrame answer = new JFrame();
answer.setBackground(Color.yellow);
JPanel pan2 = new JPanel();
JLabel howanswer = new JLabel("Your answer is" + area + "We got this by multiplying the length and width");
pan2.add(howanswer);
answer.add(pan2); // <--- Don't forget to add your components to the frame
answer.pack(); // <--- Resize the frame to a suitable size
answer.setVisible(true); // <--- Set the frame to visible AFTER you have added the components
}
This code works for me:
public class Test {
public static void main(String[] args){
JFrame test = new JFrame();
test.setVisible(true);
test.setSize(100,100);
test.setResizable(false);
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I assume that you can try to reduce your code and try to find problem point such way. You can put some logging to ensure setVisible(true) was called. Also I recomend to use setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); to terminate thread after exit GUI (if do not want to perform some post-exit actions).

Categories