在编写JTABEL的一个程序时,参考了suN公司的主页,上面有个这样的提示,请帮忙解释下什么意思
Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
完整代码如下:
/*
 * SimpleTableDemo.java is a 1.4 application that requires no other files.
 */import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class SimpleTableDemo extends JPanel {
    private boolean DEBUG = false;    public SimpleTableDemo() {
        super(new GridLayout(1,0));        String[] columnNames = {"First Name",
                                "Last Name",
                                "Sport",
                                "# of Years",
                                "Vegetarian"};        Object[][] data = {
            {"Mary", "Campione",
             "Snowboarding", new Integer(5), new Boolean(false)},
            {"Alison", "Huml",
             "Rowing", new Integer(3), new Boolean(true)},
            {"Kathy", "Walrath",
             "Knitting", new Integer(2), new Boolean(false)},
            {"Sharon", "Zakhour",
             "Speed reading", new Integer(20), new Boolean(true)},
            {"Philip", "Milne",
             "Pool", new Integer(10), new Boolean(false)}
        };        final JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));        if (DEBUG) {
            table.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    printDebugData(table);
                }
            });
        }        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(table);        //Add the scroll pane to this panel.
        add(scrollPane);
    }    private void printDebugData(JTable table) {
        int numRows = table.getRowCount();
        int numCols = table.getColumnCount();
        javax.swing.table.TableModel model = table.getModel();        System.out.println("Value of data: ");
        for (int i=0; i < numRows; i++) {
            System.out.print("    row " + i + ":");
            for (int j=0; j < numCols; j++) {
                System.out.print("  " + model.getValueAt(i, j));
            }
            System.out.println();
        }
        System.out.println("--------------------------");
    }    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);        //Create and set up the window.
        JFrame frame = new JFrame("SimpleTableDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        //Create and set up the content pane.
        SimpleTableDemo newContentPane = new SimpleTableDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

解决方案 »

  1.   

    如果需要线程安全,这个方法需要从event-dispatching thread调用。 普通应用不需要考虑这个。
      

  2.   

    《The Java Tutorial》- Dorothy's Birthday Release, 15 April 2005
        Trail: Creating a GUI with JFC/Swing 
        Lesson: Using Other Swing Features 
          How to Use Threads 
    中有你的这个例子,并对这个问题有详细的介绍API Specification中是这样介绍SwingUtilities.invokeLater的:
    Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI. 我看了一下,大致意思是说,Swing使用一个单独的线程来专门执行painting和相关的事件处理,保证事件的处理顺序执行,并且painting不会被事件打断。这个单一的线程就叫做event-dispatch线程。比如,你在执行一个按钮的actionPerformed时,代码执行时间长,你就会发现按钮保持不动,直到代码执行完毕。这就是因为事件的处理代码和painting使用event-dispatch线程的缘故。这种情况并不是真正值得担心的。根据Tutorial中的介绍,如果在一个paint的准备工作没有完成的时候,就去执行一个对该部件界面的修改,就会导致死锁,从而程序无法执行下去。所以,Swing希望所有的部件及其model(Swing的大多部件使用MVC模式)在创建、修改部件或者要求部件作响应的处理都在event-dispatch线程里执行。当然,出现这种情况的次数很少,我记得在Tutorial中的另一篇文章里介绍说,在main中,只要按照
    new JFrame
    ..
    fr.pack();
    fr.setVisible(true);
    这个顺序,并且setVisible(true)之后不再有任何小修改部件界面的代码,程序就不会出问题。
    感觉对这部分的介绍有些模糊,做到真正了解可能需要看invokeLater的代码。不过幸好出问题的概率不大,并且使用invokeLater也不是很麻烦。