Если я правильно понял, нужно отображать какой-то текущий прогресс, пока кнопка не закончит свою работу.
Если это так, вы можете использовать CardLayout
с неопределенным JProgressBar
.
CardLayout
– это LayoutManager
(например, BorderLayout
, FlowLayout
и т. д.), с помощью которого можно определить карточки. Каждая карта представляет собой Component
(например, Container
с другими Component
, например JPanel
). В каждый момент времени может быть видна только одна карточка. Каждая карта связана со строкой, чтобы идентифицировать ее и иметь возможность выбрать ее как видимую над другими. Вы можете узнать больше о CardLayout
в соответствующем руководстве по Java.
JProgressBar
— это индикатор выполнения, т. е. 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
. В него мы добавляем две карты. Один с кнопкой и один с индикатором выполнения.
person
gthanop
schedule
17.01.2020
JOptionPane
поверхJFrame
и удалять его по завершении определенного действия? - person c0der   schedule 17.01.2020Glass Pane
. См.: stackoverflow.com/questions/27822671 / для реализации с простым API. - person camickr   schedule 17.01.2020