当从一个动作监听器调用fireTableRowsInserted()时,JTable不会立即更新。

时间:2022-04-16 21:06:57

I have a JTable that I'm inserting rows into using data found on the internet. When I run the code that fills the list directly from the main function, I can see each row being inserted at the same time 'fireTableRowsInserted' is called - which is the behavior I want. However, when I run that same code from a JButton's ActionListener (during 'ActionPreformed()', the table does not update until the thread/event has finished. I think the problem has something to do with threads, but I am not very familiar with how thread work and am not sure where to start. Here is an example of the problem:

我有一个JTable,我在使用在internet上找到的数据插入行。当我运行从主函数直接填充列表的代码时,我可以看到在同一时间插入的每一行都被称为“fireTableRowsInserted”,这就是我想要的行为。但是,当我从JButton的ActionListener中运行相同的代码时(在“ActionPreformed()”中,这个表直到线程/事件完成之后才会更新。我认为这个问题与线程有关,但是我不太熟悉线程的工作方式,也不知道从哪里开始。下面是一个问题的例子:

public class Main { 
    static TestModel myTestModel = new TestModel(); 

    public static void main(String[] args) {
        JFrame  testFrame   = new JFrame();
        JTable  table       = new JTable(myTestModel);
        JButton button      = new JButton("Load");

        testFrame.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        testFrame.getContentPane().add(button, BorderLayout.PAGE_END);
        testFrame.pack();
        testFrame.setVisible(true);
        testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button.addActionListener(new ActionListener(){
            @Override public void actionPerformed(ActionEvent e) {
                //When openURLStr is called here, the table in the JFrame doesn't add rows until
                // the function has exited.
                openURLStr("http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Component.html", true);               
            }           
        });

        //When openURLStr is called here, the table in the JFrame adds rows at the same time the 
        // list in the table-model adds a row. (the desired behavoir)
        openURLStr("http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Component.html", true);
        myTestModel.myArrayList.clear();
        myTestModel.fireTableDataChanged();
    }

    static class TestModel extends AbstractTableModel {
        ArrayList<String> myArrayList = new ArrayList<String>();

        @Override public int    getColumnCount()    { return(3);                    }
        @Override public int    getRowCount()       { return(myArrayList.size());   }
        @Override public Object getValueAt(int row, int col) {
            char c = '*';
            String rowStr = myArrayList.get(row);
            if ( rowStr.length() > col ) c = rowStr.charAt(col);
            return(c);
        }

        public boolean add(String line) {
            int row = myArrayList.size();
            if ( row < 100 ) {
                myArrayList.add(line);
                this.fireTableRowsInserted(row, row);               
                return(true);
            }
            else {
                return(false);
            }
        }       
    }

    private static void openURLStr(String urlStr, boolean lookForLinks) {
        try {
            URL                 url         = new URL(urlStr);
            InputStreamReader   isr         = new InputStreamReader(url.openConnection().getInputStream());
            BufferedReader      br          = new BufferedReader(isr);
            ArrayList<String>   linksFound  = new ArrayList<String>();

            if ( br != null ) {
                String strLine = br.readLine();
                //row added to table-model here: 
                boolean continueParse = myTestModel.add(strLine);

                //this code is mainly to induce more time between each addition of a line.
                while ( strLine != null && continueParse ) {
                    if ( lookForLinks && strLine != null ) {
                        String ahrefStr = "a href=\"";
                        int start_i = strLine.indexOf(ahrefStr) + ahrefStr.length();
                        if ( start_i > -1 ) {
                            int end_i = strLine.indexOf("\"", start_i+1);
                            if ( end_i > -1 && end_i > start_i ) {
                                linksFound.add(strLine.substring(start_i, end_i));
                            }
                        }
                    }
                    strLine = br.readLine();
                }
                br.close();
            }

            for ( String link : linksFound ) {
                openURLStr(link, false);
            }

        } catch (IOException e) {
        }
    }
}

1 个解决方案

#1


5  

The ActionListener's actionPerformed is executed on the event dispatch thread and this will be blocked by your code inside. Thus the GUI freezes for this time and no updates will be shown at all.

ActionListener的actionPerformed在事件分派线程上执行,这将被内部代码阻塞。因此,GUI冻结了这个时间,并且不会显示任何更新。

Try to separate the "long running" URL call e.g. in a SwingWorker.

试着将“长时间运行”的URL调用分开,例如在一个SwingWorker中。

#1


5  

The ActionListener's actionPerformed is executed on the event dispatch thread and this will be blocked by your code inside. Thus the GUI freezes for this time and no updates will be shown at all.

ActionListener的actionPerformed在事件分派线程上执行,这将被内部代码阻塞。因此,GUI冻结了这个时间,并且不会显示任何更新。

Try to separate the "long running" URL call e.g. in a SwingWorker.

试着将“长时间运行”的URL调用分开,例如在一个SwingWorker中。