我有JFrame
。 JFrame
中包含JDesktopPane
,JComboBox
,多个JLabel
和JProgressBar
。我面临两个挑战:
我想通过点击JLabel
上的JFrame
来更新/更改JButton
中某个JInternalFrame
中的文字(按钮做了一些计算)。
点击另一个JButton
上的JInternalFrame
(该按钮执行一项小任务),我想使用JProgressBar
(进度栏位于JFrame
})显示完成工作的进度。
我使用SwingUtilities.invokelater()
来执行按钮完成的任务。
我使用NetBeans作为我的IDE。
答案 0 :(得分:1)
很难知道没有代码会发生什么,但可能是事件调度线程(EDT)被阻止(或终止?),例如通过invokeLater
调用代码。 EDT用于更新GUI,不应用于(慢)非GUI相关的计算。有关更多详细信息,请参阅教程事件调度线程及后续内容。
示例(不阻止):
import java.awt.*;
import java.awt.event.ActionEvent;
import java.time.LocalTime;
import javax.swing.*;
public class LabelProgress {
public static void main(String[] args) {
LabelProgress main = new LabelProgress();
SwingUtilities.invokeLater(() -> main.showInternal1());
SwingUtilities.invokeLater(() -> main.showInternal2());
}
private JFrame frame;
private JLabel label;
private JDesktopPane desktop;
private JProgressBar bar;
private int progress = 0;
private LabelProgress() {
label = new JLabel("Label: ");
desktop = new JDesktopPane();
bar = new JProgressBar(0, 100);
bar.setStringPainted(true);
frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(label, BorderLayout.BEFORE_FIRST_LINE);
frame.add(desktop, BorderLayout.CENTER);
frame.add(bar, BorderLayout.AFTER_LAST_LINE);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(600, 400);
frame.validate();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void showInternal1() {
JButton change = new JButton("Change");
change.addActionListener(this::doChange);
JInternalFrame internal = new JInternalFrame("Change Label");
internal.setLayout(new FlowLayout());
internal.add(change);
internal.setBounds(20, 20, 200, 150);
internal.setVisible(true);
desktop.add(internal);
}
private void showInternal2() {
JButton task = new JButton("Task");
task.addActionListener(this::doTask);
JInternalFrame internal = new JInternalFrame("Small Task");
internal.setLayout(new FlowLayout());
internal.add(task);
internal.setBounds(150, 100, 200, 150);
internal.setVisible(true);
desktop.add(internal);
}
private void doChange(ActionEvent ev) {
// using a SwingWorker:
// for demonstration I used an anonymous class, maybe a own class is better
SwingWorker<LocalTime , Void> worker = new SwingWorker<LocalTime , Void>() {
@Override
protected LocalTime doInBackground() throws Exception {
// not executed on the EDT - just get the current time
LocalTime someCalculation = LocalTime.now();
return someCalculation;
}
@Override
protected void done() {
// executed on EDT
try {
LocalTime resultOfSomeCalculation = get();
label.setText("Label: " + resultOfSomeCalculation.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
worker.execute();
}
private void doTask(ActionEvent ev) {
// no need to use SwingWorker
Thread thread = new Thread(this::slowTask);
thread.start();
}
private void slowTask() {
// not really that slow, just for demonstration
progress += 10;
if (progress > 100) progress = 100;
// and now switching to the EDT
SwingUtilities.invokeLater(() -> bar.setValue(progress));
}
}