JList 重新填充非常慢

发布于 2024-09-16 13:23:08 字数 1315 浏览 5 评论 0原文

我有一个 JList 组件,应该清空并重新填充它。以下代码(基于我的原始代码)显示了一个带有 JList 和 JButton 的简单窗口:

import java.awt.BorderLayout;
import javax.swing.*;

public class JListTest extends javax.swing.JFrame{
    JList jList;
    JButton button;
    DefaultListModel model;

    public JListTest() {
        jList = new JList();
        model = new DefaultListModel();
        jList.setModel( model );
        button = new JButton();

        getContentPane().add(jList, java.awt.BorderLayout.CENTER);

        button.setText("add 10000 items");
        button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                model.clear();
                for( int i=0; i<10000; ++i ) {
                    model.addElement( "aaaa");
                }
            }
        });
        getContentPane().add(button, BorderLayout.PAGE_START);        
        pack();        
    }

    public static void main(String args[]) {
        JListTest jlt =new JListTest();
        jlt.setSize(300, 300);
        jlt.setVisible( true );
    }
}

如果我按下按钮,插入(10000 个项目)会非常快。如果我一次又一次地按下它,它仍然很快。

如果我选择第三项并按下按钮,结果是相同的,插入速度非常快。

如果我选择第一项并按下按钮,程序会变得非常慢(实际上我必须停止它)。

为什么选择第一项会减慢执行速度?

我已经使用 JDK 1.5 和 1.6 对其进行了测试。

I have a JList component which should be emptied and repopulated. The following code (based on my original code) shows a simple window with a JList and a JButton:

import java.awt.BorderLayout;
import javax.swing.*;

public class JListTest extends javax.swing.JFrame{
    JList jList;
    JButton button;
    DefaultListModel model;

    public JListTest() {
        jList = new JList();
        model = new DefaultListModel();
        jList.setModel( model );
        button = new JButton();

        getContentPane().add(jList, java.awt.BorderLayout.CENTER);

        button.setText("add 10000 items");
        button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                model.clear();
                for( int i=0; i<10000; ++i ) {
                    model.addElement( "aaaa");
                }
            }
        });
        getContentPane().add(button, BorderLayout.PAGE_START);        
        pack();        
    }

    public static void main(String args[]) {
        JListTest jlt =new JListTest();
        jlt.setSize(300, 300);
        jlt.setVisible( true );
    }
}

If I press the button the insertion (10000 items) is very fast. If I press it again and again it is still very fast.

If I select the third item and press the button, the result is the same, the insertion is very fast.

If I select the first item and press the button, the program becomes very slow (actually I have to stop it).

Why the selection of the first item slows down the execution?

I've tested it using JDK 1.5 and 1.6.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

优雅的叶子 2024-09-23 13:23:09

我建议编写您自己的模型,它允许一次添加一堆值。我想这不是对模型的添加,而是由此触发的 GUI 东西导致了性能的下降。

I'd suggest to write your own model which allows to add a bunch of values at once. I guess it's not the addition to the model but the GUI things triggered by this that kill the performance.

我爱人 2024-09-23 13:23:09

我不确定为什么选择一个项目会导致性能问题。但是每次添加一个项目时,都会触发一个事件,告诉列表重新绘制它自己。因此,选择某个项目可能会导致额外的重新绘制。

无论如何,更好的方法是创建一个新模型,然后将其添加到列表中:

    button.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            DefaultListModel dlm = new DefaultListModel();
            for( int i=0; i<10000; ++i ) {
                dlm.addElement( "aaaa");
            }
            jList.setModel(dlm);
        }
    });

这样,添加每个新项目时都不会触发事件。

I'm not sure why selecting an item causes the performance problem. But everytime you add an item an event is fired which tells the list to repaint itslef. So maybe the fact that an item is selected causes extra repainting.

Anyway a better way to do this would be to create a new model and then just add it to the list:

    button.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            DefaultListModel dlm = new DefaultListModel();
            for( int i=0; i<10000; ++i ) {
                dlm.addElement( "aaaa");
            }
            jList.setModel(dlm);
        }
    });

This way events are not fired as every new item is added.

只有影子陪我不离不弃 2024-09-23 13:23:09

您不应该在这样的事件循环中向模型中添加大量元素。更好的方法是让您的操作侦听器生成一个线程来添加项目,并让该线程调用 SwingUtilities.invokeLater() 来向列表触发更改事件。

请注意,根据下面的注释,您需要创建一个 AbstractListModel(或其子类)并使其成为模型,然后在 invokeLater 中对其调用 fireContentsChanged

You should not be adding lots of elements into the model in a the event loop like that. Far better would be to have your action listener spawn off a thread to add the items, and have that thread invoke a SwingUtilities.invokeLater() to fire the change event to the list.

Note that as per the comment below, you need to make an AbstractListModel (or a subclass of it) and make it the model, and call fireContentsChanged on it in the invokeLater.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文