Если я правильно понял, вам нужно отображать какой-то текущий прогресс, пока кнопка не закончит свою работу.
Если это так, вы можете использовать CardLayout
с неопределенным JProgressBar
.
CardLayout
- это LayoutManager
(например, BorderLayout
, FlowLayout
, et c ...), который позволяет определять карты . Каждая карта представляет собой Component
(например, Container
с другими Component
s, например, JPanel
). Только одна карта может быть видна в любое время. Каждая карта связана со строкой, чтобы идентифицировать ее и иметь возможность выбрать ее как видимую поверх других. Вы можете прочитать больше о CardLayout
в соответствующем учебнике Java .
A JProgressBar
- это индикатор выполнения, ie a JComponent
, который показывает прогресс постоянная задача. Есть два режима: детерминированный и неопределенный. В детерминированном режиме вы указываете размер проблемы и сами продвигаете индикатор выполнения с помощью кода. В неопределенном режиме постоянно вращается ручка индикатора (которая позволяет пользователю знать, что выполняется текущая задача и что программа не знает, сколько времени это займет). JProgressBar
можно использовать как простой визуальный индикатор для пользователя. Вы можете прочитать больше о JProgressBar
в соответствующем учебном пособии Java .
Таким образом, в вашем случае вы можете использовать CardLayout
с двумя картами, где одна карта содержит Кнопка «Помощь», а другая неопределенная JProgressBar
. Когда пользователь нажимает кнопку «Справка», вы отображаете карточку индикатора выполнения, а когда прогресс завершается, вы переключаетесь обратно на карточку кнопки «Справка».
Теперь, если вы выполняете процесс внутри ActionListener
кнопки «Справка», которая будет запускаться в потоке рассылки событий (или EDT для краткости). Таким образом, ваши карты не смогут переключаться, потому что переключение выполняется также в EDT. В этом случае мы собираемся создать отдельный SwingWorker
для обработки прогресса. Поэтому единственное, что сделает ActionListener
, - это создаст и запустит такой SwingWorker
. Таким образом, ActionListener
закончится до окончания процесса, поэтому карты будут переключены.
Рассмотрим следующий пример кода:
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();
}
});
}
}
Здесь вы можете увидеть создание и инициализация MyPanel
, который является контейнером с CardLayout
. В него мы добавляем две карты. Один с кнопкой и один с индикатором.