If I understood correctly, you need to display some sort of ongoing progress until the button finishes its work.
If so, you can use a CardLayout
with an indeterminate JProgressBar
.
CardLayout
is a LayoutManager
(such as BorderLayout
, FlowLayout
, etc...) which lets you define cards. Each card is a Component
(such as a Container
with other Component
s, such as a JPanel
for example). Only one card can be visible at any time. Each card is associated with a String to identify it and being able to select it as visible over the others. You can read more about CardLayout
in the corresponding Java tutorial.
A JProgressBar
is a progress bar, ie a JComponent
which shows you the progress of an ongoing task. There are two modes: determinate and indeterminate. In determinate mode you specify the size of the problem and you advance the progress bar yourself via code. In indeterminate mode, there is constantly an indicator knob spinning (which lets the user know that there is an ongoing task in progress and that the program does not know how long will it take). JProgressBar
can be used as just a simple visual indicator for the user. You can read more about JProgressBar
in the corresponding Java tutorial.
So, in your case, you can use a CardLayout
with two cards, where one card contains the "Help" button, and the other an indeterminate JProgressBar
. When the user clicks on "Help", you show the progress bar card, and when the progress is done you switch back to the "Help" button card.
Now if you do the progress inside the ActionListener
of the button "Help", that will run on the Event Dispatch Thread (or EDT for short). So your cards will not be able to be switched because the switching is done also inside the EDT. In this case we are going to create a separate SwingWorker
to handle the progress. So the only thing the ActionListener
will do, is to create and start such a SwingWorker
. So that will let the ActionListener
end before the end of the progress, so the cards will be switched.
Consider the following sample code:
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
public class MyPanel extends JPanel {
private static final Dimension PANEL_SIZE = new Dimension(500, 500);
public MyPanel() {
//Always prefer a layout instead of setting it to null.
super(new CardLayout()); //Set the layout of the main panel to CardLayout, so we can add the cards...
//Obtain the CardLayout we just created for this panel:
final CardLayout cardLayout = (CardLayout) super.getLayout();
//String names of each card:
final String nameForCardWithButton = "BUTTON",
nameForCardWithProgress = "PROGRESS";
//Creating first card...
final JPanel cardWithButton = new JPanel(new GridBagLayout());
/*Using a GridBagLayout in a panel which contains a single component (such as the
cardWithButton panel, containing a single JButton) will layout the component in
the center of the panel.*/
final JButton btnH = new JButton("HELP");
cardWithButton.add(btnH);
// Action listener to listen to button click and display pop-up when received.
btnH.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
cardLayout.show(MyPanel.this, nameForCardWithProgress); //Switch to progress bar card...
//Create and start worker Thread:
new SwingWorker() {
@Override
protected Object doInBackground() throws Exception {
/*Simulate a long ongoing process without blocking the EDT...
Well, actually, the JOptionPane will block the EDT I think, so I will leave
it here for demonstration puprposes only.*/
JOptionPane.showMessageDialog(null, "Helpful info...", "info", JOptionPane.INFORMATION_MESSAGE);
return null; //Not sure if returning null here is a good practice or not.
}
@Override
protected void done() {
cardLayout.show(MyPanel.this, nameForCardWithButton); //Switch back to button card, when the job has finished.
}
}.execute();
}
});
//Creating second card...
final JPanel cardWithProgress = new JPanel(new FlowLayout());
final JProgressBar bar = new JProgressBar();
bar.setIndeterminate(true); //Here we initialize the progress bar to indeterminate mode...
cardWithProgress.add(bar);
super.add(cardWithButton, nameForCardWithButton);
super.add(cardWithProgress, nameForCardWithProgress);
super.setPreferredSize(PANEL_SIZE);
}
private static void createAndDisplay() {
JFrame frame = new JFrame("Frame");
frame.getContentPane().add(new MyPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndDisplay();
}
});
}
}
You can see here the creation and initialization of MyPanel
which is the container with CardLayout
. In it, we add the two cards. One with the button and one with the progress bar.