Swing - JList内容在动态更新时随机消失

时间:2014-08-23 13:21:04

标签: java swing

自从我上次进行Swing编程以来已经有一段时间了,今天我又回到了它。我有一个简单的JList,由DefaultListModel支持。我还有JButton,会显示JFileChooser。选择目录时,JList应填充所选目录下的文件名。

我发现偶尔(实际上它经常随机发生),列表不会更新,直到我点击(看似空白)列表。我想通过使用DefaultListModel,我可以调用addElement()来触发fireIntervalAdded(它应该重新绘制列表,容器等)?另外,我相信在EDT中调用actionPerformed()方法,所以我应该能够更新DefaultListMode l。无论如何......我也尝试在列表,容器等上调用revalidate()repaint(),但也没有任何成功。

其次,当列表中已经有一些项目时,单击按钮(触发文件选择器显示)将清除JList条目(不在模型上调用clear())。

源代码位于:

https://github.com/alexwibowo/spider

这是代码的摘要(希望它已经足够了)

  package org.github.alexwibowo.spider.gui;

  import com.jgoodies.forms.factories.CC;
  import com.jgoodies.forms.layout.FormLayout;

   import javax.swing.*;

  public class MainPanel extends JPanel {
  public MainPanel() {
    initComponents();
  }

private void initComponents() {
    toolBar1 = new JToolBar();
    openFolderButton = new JButton();
    splitPane1 = new JSplitPane();
    scrollPane1 = new JScrollPane();
    fileList = new JList();

    //======== this ========
    setLayout(new FormLayout(
        "default:grow",
        "default, $lgap, fill:default:grow"));

    //======== toolBar1 ========
    {
        toolBar1.setFloatable(false);

        //---- openFolderButton ----
        openFolderButton.setIcon(UIManager.getIcon("Tree.openIcon"));
        openFolderButton.setBorder(new EmptyBorder(5, 5, 5, 5));
        toolBar1.add(openFolderButton);
    }
    add(toolBar1, CC.xy(1, 1));

        //======== splitPane1 ========
          {

            //======== scrollPane1 ========
            {

            //---- fileList ----
            fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            scrollPane1.setViewportView(fileList);
        }
        splitPane1.setLeftComponent(scrollPane1);
    }
    add(splitPane1, CC.xy(1, 3));
}

protected JToolBar toolBar1;
protected JButton openFolderButton;
protected JSplitPane splitPane1;
protected JScrollPane scrollPane1;
protected JList fileList;

  }

以及扩展上述内容的面板。这是处理向列表添加文件名的类:

  package org.github.alexwibowo.spider.gui

import javax.swing.*
import java.awt.event.ActionEvent
import java.awt.event.ActionListener

class BarcodeMainPanel extends MainPanel {
private DefaultListModel<String> listModel = new DefaultListModel<String>()

BarcodeMainPanel() {
    initModels()
    initEventHandling()
}

protected void initModels() {
    fileList.model = listModel
}

protected void initEventHandling() {
    openFolderButton.addActionListener(new ActionListener() {
        @Override
        void actionPerformed(ActionEvent e) {
                    JFileChooser chooser = new JFileChooser();
                    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                    chooser.setLocation(50, 50);
                    if (chooser.showOpenDialog(BarcodeSpiderMainFrame.instance()) == JFileChooser.APPROVE_OPTION) {
                        listModel.clear()
                        File selectedDirectory = chooser.getSelectedFile()
                        selectedDirectory.eachFile {
                            listModel.addElement(it.name)
                        }
                    } else {
                        System.out.println("No Selection ");
                    }
                }
    })
}
   }

包含面板的框架(仅为完整性):

package org.github.alexwibowo.spider.gui

import groovy.transform.Synchronized

import javax.swing.*
import java.awt.*

class BarcodeSpiderMainFrame extends JFrame{

    private static BarcodeSpiderMainFrame INSTANCE;

    BarcodeSpiderMainFrame(String title) throws HeadlessException {
        super(title)
    }

    @Synchronized
    public static BarcodeSpiderMainFrame instance() {
        if (INSTANCE == null) {
            INSTANCE = new BarcodeSpiderMainFrame("Spider")
            INSTANCE.minimumSize = new Dimension(800,600)
            INSTANCE.maximumSize = new Dimension(1024,768)
            INSTANCE.defaultCloseOperation = EXIT_ON_CLOSE
        }
        INSTANCE.initializeContent()
        INSTANCE.visible = true
        INSTANCE
    }

    private void initializeContent() {
        BarcodeMainPanel mainPanel = new BarcodeMainPanel()
        this.contentPane.add(mainPanel);
    }
}

最后是发射器(仅为完整性):

package org.github.alexwibowo.spider

import org.github.alexwibowo.spider.gui.BarcodeSpiderMainFrame

import javax.swing.*

@Singleton
class SpiderLauncher {
    BarcodeSpiderMainFrame barcodeSpiderMainFrame

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SpiderLauncher.instance.run(args);
            }
        });
    }

    void run(String[] args) {
        barcodeSpiderMainFrame = BarcodeSpiderMainFrame.instance()
        barcodeSpiderMainFrame.show()
    }
}

1 个答案:

答案 0 :(得分:1)

这就是修复它的原因。 在BarcodeSpiderMainFrame中,删除对setVisible的调用。所以它看起来像:

public static BarcodeSpiderMainFrame instance() {
    if (INSTANCE == null) {
        INSTANCE = new BarcodeSpiderMainFrame("Spider")
        INSTANCE.minimumSize = new Dimension(800,600)
        INSTANCE.preferredSize = new Dimension(1024,768)
        INSTANCE.maximumSize = new Dimension(1024,768)
        INSTANCE.defaultCloseOperation = EXIT_ON_CLOSE
    }

    INSTANCE.initializeContent()
     // INSTANCE.visible = true   // remove this line       
    INSTANCE
}

并在启动器中调用setVisible()

@Singleton
class SpiderLauncher {
    BarcodeSpiderMainFrame barcodeSpiderMainFrame

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SpiderLauncher.instance.run(args);
            }
        });
    }

    void run(String[] args) {
        barcodeSpiderMainFrame = BarcodeSpiderMainFrame.instance()
        barcodeSpiderMainFrame.pack()
        barcodeSpiderMainFrame.setVisible(true) // add this line
    }
}

我添加了对pack()的调用。但我不认为这真的很重要。以上是如何解决我的问题的?我不知道。如果有人能够解释实际发生的事情,那就太好了。