有趣的是,就在最近我遇到過類似的問題,所以爲了克服這個我用SwingUtilities.invokeAndWait(Runnable runnable),這就是取得了SSCCE我創建工作不如預期,但如果我改變所有調用invokeAndWait()與invokeLater(),可以清楚地看到兩者之間的區別。
從Java文件引述說:
Causes doRun.run() to be executed synchronously on the AWT event dispatching thread.
This call blocks until all pending AWT events have been processed and
(then) doRun.run() returns. This method should be used when an application thread
needs to update the GUI.
這是我作爲一個SSCCE代表一個冒泡排序動畫做了一個小程序:
import javax.swing.*;
public class BubbleSortFrame extends JFrame
{
private BubbleSortView contentPane;
private void displayGUI()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new BubbleSortView();
setContentPane(contentPane);
pack();
setLocationByPlatform(true);
setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new BubbleSortFrame().displayGUI();
}
});
}
}
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
public class BubbleSortView extends JPanel
{
private JLabel sizeLabel;
private JTextField sizeField;
private JTextField[] vField;
private JLabel[] vLabel;
private JButton startButton, createButton;
private int size;
private JPanel createPanel, animationPanel;
private BubbleSort bubbleSort;
public BubbleSortView()
{
size = 5;
displayAndCreateGUI();
}
private void displayAndCreateGUI()
{
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setOpaque(true);
setBackground(Color.WHITE);
JPanel basePanel = new JPanel();
basePanel.setLayout(new GridLayout(2, 1, 5, 5));
basePanel.setOpaque(true);
basePanel.setBackground(Color.WHITE);
JPanel topPanel = new JPanel();
topPanel.setOpaque(true);
topPanel.setBackground(Color.WHITE);
topPanel.setBorder(
BorderFactory.createTitledBorder("Input : "));
topPanel.setLayout(new GridLayout(2, 1, 5, 5));
/*
* This will act as the area
* for taking the input for
* number of elements in an Array.
*/
JPanel sizePanel = new JPanel();
sizePanel.setOpaque(true);
sizePanel.setBackground(Color.WHITE);
sizeLabel = new JLabel("Enter Number of Elements : ");
sizeField = new JTextField(10);
createButton = new JButton("CREATE");
/*
* This will act as the area
* where we will specify the values
* for each index in an Array.
*/
createPanel = new JPanel();
createPanel.setOpaque(true);
createPanel.setBackground(Color.WHITE);
createPanel.setBorder(
BorderFactory.createTitledBorder("Please Enter values for an Array : "));
createPanel.setVisible(false);
animationPanel = new JPanel();
animationPanel.setOpaque(true);
animationPanel.setBackground(Color.WHITE);
animationPanel.setBorder(
BorderFactory.createTitledBorder("Animation : "));
animationPanel.setVisible(false);
createButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent ae)
{
if (sizeField.getDocument().getLength() > 0)
{
size = Integer.parseInt(sizeField.getText());
vField = new JTextField[size];
createPanel.setVisible(true);
for (int i = 0; i < size; i++)
{
vField[i] = new JTextField(5);
/*
* Adding the Listener to the
* last JTextField on the Right
* Side.
*/
if (i == (size - 1))
{
vField[i].addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent ae)
{
animationPanel.setLayout(
new GridLayout(1, size, 2, 2));
animationPanel.setVisible(true);
vLabel = new JLabel[size];
for (int i = 0; i < size; i++)
{
vLabel[i] = new JLabel(
vField[i].getText(), JLabel.CENTER);
vLabel[i].setOpaque(true);
vLabel[i].setBackground(Color.YELLOW);
vLabel[i].setForeground(Color.RED);
animationPanel.add(vLabel[i]);
}
animationPanel.revalidate();
animationPanel.repaint();
bubbleSort = new BubbleSort(vLabel, size);
Thread t = new Thread(bubbleSort);
t.start();
}
});
}
createPanel.add(vField[i]);
}
createPanel.revalidate();
createPanel.repaint();
createButton.setEnabled(false);
}
else
size = 5;
}
});
sizePanel.add(sizeLabel);
sizePanel.add(sizeField);
sizePanel.add(createButton);
/*
* Initializing JTextField Array
* so that it can be first presented
* to the USER to take input for
* 5 values.
*/
//for (int i = 0; i < size; i++)
// vField[i] = new JTextField(5);
topPanel.add(sizePanel);
topPanel.add(createPanel);
basePanel.add(topPanel);
basePanel.add(animationPanel);
add(basePanel);
}
private class BubbleSort implements Runnable
{
private int[] arr;
private JLabel[] vLabel;
private int size;
private int pass;
public BubbleSort(JLabel[] label, int size)
{
vLabel = label;
this.size = size;
pass = 1;
for (int i = 0; i < size; i++)
System.out.print("" + vLabel[i].getText() + "\t");
System.out.println("");
}
@Override
public void run()
{
try
{
bubbleSorting();
}
catch (InvocationTargetException ite)
{
ite.printStackTrace();
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
private void bubbleSorting()
throws InterruptedException, InvocationTargetException
{
while (pass < size)
{
for (int i = 0; i < (size - pass); i++)
{
final int j = i;
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
vLabel[j].setBackground(Color.RED);
vLabel[j].setForeground(Color.WHITE);
vLabel[j + 1].setBackground(Color.RED);
vLabel[j + 1].setForeground(Color.WHITE);
}
});
try
{
Thread.sleep(1500);
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
int left = Integer.parseInt(vLabel[i].getText());
int right = Integer.parseInt(vLabel[i + 1].getText());
if (left > right)
{
String temp = vLabel[i].getText();
vLabel[i].setText(vLabel[i + 1].getText());
vLabel[i + 1].setText(temp);
}
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
vLabel[j].setBackground(Color.YELLOW);
vLabel[j].setForeground(Color.RED);
vLabel[j + 1].setBackground(Color.YELLOW);
vLabel[j + 1].setForeground(Color.RED);
}
});
}
System.out.println("Pass : " + pass + "\tSize : " + size);
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
vLabel[size - pass].setBackground(Color.GREEN);
vLabel[size - pass].setForeground(Color.BLUE);
}
});
pass++;
}
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
vLabel[0].setBackground(Color.GREEN);
vLabel[0].setForeground(Color.BLUE);
}
});
}
}
}
究竟不管用? 'invokeLater'在[Event Dispatch Thread]上執行runnable(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)。作爲替代方案,您可以查看[SwingWorker](http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html),該工具專爲長時間運行的任務而設計,可爲用戶界面提供更新在EDT上。 – tenorsax
當我的意思不工作時,我的意思是Textfield沒有更新。不過我會看看SwingWorker。 – Narabhut