如果我理解正确,您需要显示某种正在进行的进度,直到按钮完成其工作。
如果是这样,您可以将 aCardLayout
与 indeterminate 一起使用JProgressBar
。
CardLayout
是一个LayoutManager
(例如BorderLayout
,FlowLayout
等...),它可以让您定义卡片。每张卡片都是一个Component
(比如aContainer
和其他Component
s,比如a JPanel
)。任何时候都只能看到一张卡片。每张卡片都与一个字符串相关联,以识别它并能够将其选择为在其他卡片上可见。您可以CardLayout
在相应的 Java 教程中了解更多信息。
AJProgressBar
是一个进度条,即JComponent
显示正在进行的任务的进度。有两种模式:确定和不确定。在确定模式下,您可以指定问题的大小并通过代码自己推进进度条。在不确定模式下,指示旋钮不断旋转(这让用户知道有一个正在进行的任务正在进行中,并且程序不知道需要多长时间)。JProgressBar
可以用作用户的简单视觉指示器。您可以JProgressBar
在相应的 Java 教程中了解更多信息。
因此,在您的情况下,您可以将 aCardLayout
与两张卡一起使用,其中一张卡包含“帮助”按钮,另一张卡是不确定的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
。在其中,我们添加了两张卡。一个带有按钮,一个带有进度条。