1

I have a button which runs a function in another class.The button click event handling goes like this:

    JPanel ne=new JPanel();
    JButton startButton=new JButton("START"); 
    public void actionPerformed(ActionEvent e)
    {

        System.out.println("Welcome to Guess the number Game");
        System.out.println("You have 3 chances to guess a number between 0 and 10 excluding 10");

        ne.remove(startButton);
        gamer2 game=new gamer2();
        game.generatenum();

    }

The JButton startButton is added to a JPanel ne.Once the button is clicked,actionPerformed(ActionEvent e) runs and the button is supposed to be removed from the JPanel.But the button remains there until the whole program finishes running.Can someone help me with this?

Complete code for the JFrame:

package test;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.Border;

public class test3 implements ActionListener {

    JButton p=new JButton("START"); 
    JPanel ne=new JPanel();

    public void create()
    {
        Dimension s=new Dimension(400,400);
        JFrame l=new JFrame();

        l.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        l.setSize(s);
        l.setResizable(true);
        Dimension s1=new Dimension(400,200);
        Dimension s2=new Dimension(400,100);

        JPanel me=new JPanel(); 


        JLabel kingsman=new JLabel ("GUESS THE KING'S NUMBER!");
        kingsman.setFont(new Font("Serif", Font.BOLD, 45));

        JPanel commonPane=new JPanel();
        BoxLayout n1=new BoxLayout(commonPane,1);
        commonPane.setLayout(n1);


        p.setFont(new Font("Serif", Font.BOLD, 40));
        p.setPreferredSize(s1);
        JTextField tf=new JTextField();
        tf.setFont(new Font("Serif", Font.BOLD, 45));
        Border border = BorderFactory.createLineBorder(Color.YELLOW, 5);
        tf.setBorder(border);
        tf.setPreferredSize(s2);
        JPanel cn=new JPanel();
        cn.add(tf);
        //l.add(p);
        me.add(kingsman);
        ne.add(p);

        commonPane.add(me);
        commonPane.add(ne);
        commonPane.add(cn);
        l.add(commonPane);

        l.setVisible(true);
        p.addActionListener(this); 

    }

    public void actionPerformed(ActionEvent e)
    {
        System.out.println("Welcome to Guess the number Game");
        System.out.println("You have 3 chances to guess a number between 0 and 10 excluding 10");

        ne.remove(p);

        ne.updateUI();
        gamer2 game=new gamer2();
        game.generatenum();

    }

    public static void main(String args[])
    {
        test3 ob=new test3();
        ob.create();

    }

}
Mitch Talmadge
  • 4,638
  • 3
  • 26
  • 44
Mathews Mathai
  • 1,707
  • 13
  • 31

4 Answers4

2

Under normal circumstances, something like...

ne.remove(startButton);
ne.revalidate();
ne.repaint();

should work. If this doesn't work, that would suggest that you're doing something else wrong in your code which you're not showing us and you should consider providing a runnable example which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses

So having look at the source code, I updated the actionPeformed method to look like...

public void actionPerformed(ActionEvent e) {
    System.out.println("Welcome to Guess the number Game");
    System.out.println("You have 3 chances to guess a number between 0 and 10 excluding 10");

    ne.remove(p);
    ne.revalidate();
    ne.repaint();

    //ne.updateUI();
    //gamer2 game = new gamer2();
    //game.generatenum();

}

And that worked fine for me.

I would, however, encourage you to have a look at How to Use CardLayout for a better alternative

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Do you want me to post the entire program? – Mathews Mathai Dec 28 '15 at 07:06
  • As I said, we want a runnable "example" which demonstrates you problem, which is NOT a code dump. Have a look at [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) for more details about what we're looking for – MadProgrammer Dec 28 '15 at 07:08
  • @MathewsMathai Updated your code and it runs fine for me, see updates – MadProgrammer Dec 28 '15 at 07:23
  • Yes..I did that too.By commenting off those lines,the program completes execution which yet again proves the fact that the JFrame can be modified if the program completes running. – Mathews Mathai Dec 28 '15 at 07:25
  • But the use of my button is to run the `generatenum()` function in class `gamer2`.If I remove those 2 lines,the button is useless. – Mathews Mathai Dec 28 '15 at 07:26
  • Yes, but I don't have the source code for `gamer2`, so I couldn't run your example with it, so I took it out, my attention was focused on fixing it so that the button would disappear from the window. If the button is still visible when you re-enable those two lines (ignore `updateUI`, you should never use it), then you have a bigger problem which is not demonstrated with the code you've provided – MadProgrammer Dec 28 '15 at 07:28
  • May I provide you a link to an earlier question I asked which has the entire code for the program??...http://stackoverflow.com/questions/34479318/jframe-losing-its-structure-and-looks-on-resizing-after-button-click/34479425#34479425 – Mathews Mathai Dec 28 '15 at 07:30
  • Okay, so based on your previous code, you're accepting user input from the console from within a GUI, this is a recipe for disaster, which you've discovered. GUI's a event driven frameworks, that is, something happens and you respond to it, they are NOT linear in nature. Console programs are linear. The way you appear to have your code setup, suggests that while you're waiting for user input, the GUI thread (AKA The Event Dispatching Thread) is been blocked, meaning it can't respond to new events, including repaint events, so your UI won't update – MadProgrammer Dec 28 '15 at 08:07
  • Is there a solution to this?..>How can I achieve this requirement? And is this EDT thing mentioned in java API? – Mathews Mathai Dec 28 '15 at 08:09
  • The EDT is the thread in which the GUI runs (events are dispatched to components), if you block this thread for any reason, no more events get dispatched, including paint events. See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details. The solution is not to get user input from the console in this way, but instead, use the GUI to get the input you need. See [Creating a GUI With JFC/Swing](http://docs.oracle.com/javase/tutorial/uiswing/) for more options – MadProgrammer Dec 28 '15 at 08:11
  • Okay.Thanks a lot.Got it. – Mathews Mathai Dec 28 '15 at 08:14
2

All the updates on the GUI (initiated by ne.remove(p); and ne.updateUI();) will be done after the actionPerformed(..) method finishes. Therefore game.generatenum(); should only bring up the new GUI and return as fast as possible.

Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34
  • Now that makes sense.But why isn't executed when the line is encountered?? – Mathews Mathai Dec 28 '15 at 08:02
  • First the changes should be made and then `game.generatenum()` should be executed..right??...According to the flow of lines? – Mathews Mathai Dec 28 '15 at 08:03
  • That is the way swing has been designed. The `updateUI` method schedules a repaint event on the event queue. This event will be handled after the current event (button click -> `actionPerformed(..)`) has been handled. – Thomas Kläger Dec 28 '15 at 08:05
  • Thanks a lot.So How do I make changes to the frame before `game.generatenum()` is executed? – Mathews Mathai Dec 28 '15 at 08:06
  • As others have pointed out it is a horrible idea to mix a Swing GUI with Console input. The proper way to go would be to implement gamer2 / gamer3 with Swing too. An "easy" way out could be to run `game.generatenum();` in a new thread. Easy in quotes because it further complicates your design. – Thomas Kläger Dec 28 '15 at 08:22
  • Okay.Basically,clicking the button again restarts the program so I wanted the button to be removed till one session is complete.I'll probably convert everything to GUI. – Mathews Mathai Dec 28 '15 at 09:30
  • What does `creating a new thread` mean?...Can you throw some light on that? – Mathews Mathai Dec 28 '15 at 09:31
  • @MathewsMathai You could code it like this (on one line since there is no better formatting in a comment): `new Thread(new Runnable() { public void run() { gamer2 game=new gamer2(); game.generatenum(); }}).start();`. But - this road leads to the next problem: how to reenable the button once your console part finishes... – Thomas Kläger Dec 28 '15 at 10:00
  • Okay.That means I need to go through the complete GUI topic and the related topics.Thanks a lot. – Mathews Mathai Dec 28 '15 at 10:07
1

After removing the button, revalidate the UI, then repaint it.

ne.revalidate();
ne.repaint();

This should invalidate the UI and request that it be redrawn.

Mitch Talmadge
  • 4,638
  • 3
  • 26
  • 44
0

You can call the UI update method,

en.updateUI();

This will update all the UI inside this JPanel.

Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68