这是我第一次使用 Java Swing,很抱歉错过了很多上下文。这是使用 Netbeans 7.0.x——商业理性。代码是使用 Netbeans 中的“设计”功能生成的。生成了大部分 gui 代码,如果不是全部的话。
我已经尝试了几个调用
setEnabled
的区域来禁用upload
按钮,直到文件传输完成。出于测试目的,我添加了一个双重 for 循环来执行一些浮点运算;我在 for 循环之前和之后都有弹出消息来反映一些“文件上传繁忙的工作”。我在感兴趣的按钮上调用 setEnabled
函数的任何地方都没有给出“变灰”或“禁用”按钮的预期结果——直到 guiController.submitUpload()
调用在 swingworker.doInBackground()
的主体内完成。现在我注释掉了done()
函数。
期望的结果:单击
buttonX
时,按钮变灰或禁用它——也就是说,我不应该再次单击它——看到 submitUpload()
中的第一个弹出窗口,然后看到第二个弹出窗口向上。 submitUpload()
函数运行它的业务逻辑,并完成。完成后,buttonX
应该重新启用或禁用它。理想情况下,我想禁用此按钮并将其变灰,buttonX
.
我已经在 SO 中尝试了很多结果,并且已经阅读了文档:
https://docs.oracle.com/javase/tutorial/uiswing/components/button.html
https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
有人可以帮我解决我遗漏的问题吗?
=========================
panelFile.java
//private variable
SwingWorker sw = ...;
buttonX.addActionListener(new java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent evt) {
//tried disabling here
//buttonX.setEnabled(false);
buttonXActionPerformed(evt);
//renable
}
}
.
.
.
private void bottonXActionPerformed(java.awt.event.ActionEvent evt) {
//also tried disabling here
sw = new SwingWorker<void, void> () {
@Override
public void doInBackground
{
try
{
if (guiController != null)
{
guiController.submitUpload();
}
}
catch (Exception e)
{
logger.log(Level.SEVERE, e.toString(), e);
}
sw = null;
return null;
}
/*
@Override
public void done()
{
buttonX.setEnabled(true);
}
*/
};
sw.execute();
}
=========================
guiController.java
public void submitUpload(){
//do stuff
//for testing I have pop-ups
// I should only see this popup once, until the "upload completes"
JOptionPane.showMessageDialog(getFrame(),
"BEFORE",
"test disable",
JOptionPane.INFORMATION_MESSAGE);
//busy loop here
JOptionPane.showMessageDialog(getFrame(),
"AFTER",
"test disable",
JOptionPane.INFORMATION_MESSAGE);
}
所以是的,在执行 SwingWorker 之前,在您调用它的地方调用
JButton#setEnabled(false)
,然后在工作人员完成后重新启用它。这 will 工作。如果它对您不起作用,那么您在未显示的代码中遇到了 Swing 线程问题。
这是我的概念验证示例MRE:
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class FooPanel01 extends JPanel {
private JButton longActionButton = new JButton("Start Long Action");
private JTextArea output = new JTextArea(15, 40);
public FooPanel01() {
longActionButton.addActionListener(e -> longActionPerformed());
JPanel buttoPanel = new JPanel();
buttoPanel.add(longActionButton);
JScrollPane scrollPane = new JScrollPane(output);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setLayout(new BorderLayout());
add(buttoPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
}
private void longActionPerformed() {
longActionButton.setEnabled(false);
output.append("Long Action started..." + System.lineSeparator());
new MyWorker().execute();
}
private class MyWorker extends SwingWorker<Void, String> {
@Override
protected Void doInBackground() throws Exception {
// Do some long running task
// here emulated with Thread.sleep
for (int i = 0; i < 6; i++) {
Thread.sleep((long) (Math.random() * 1000));
publish("Processing step " + i);
}
return null;
}
@Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
output.append(chunk + System.lineSeparator());
}
}
@Override
protected void done() {
longActionButton.setEnabled(true);
output.append("Long Action finished..." + System.lineSeparator());
try {
// always call this in the done() method to trap exceptions
get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FooPanel01());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}