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

标签 java swing

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

我发现有时(实际上经常随机发生),列表不会更新,直到我单击(看似空白的)列表。我认为通过使用 DefaultListModel,我可以调用 addElement() 这将触发 fireIntervalAdded (它应该重新绘制列表、容器等)?另外,我相信 actionPerformed() 方法是在 EDT 内部调用的,所以我应该能够更新 DefaultListModel。不管怎样......我也尝试过在列表、容器等上调用 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()
    }
}

最佳答案

这就是修复它的方法。 在 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() 的调用。但我认为这并不重要。上述如何解决我的问题?我不知道。如果有人能解释到底发生了什么,那就太好了。

关于java - Swing - JList 内容在动态更新时随机消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25462376/

相关文章:

java - 我可以使用 EntityManager 生成 .sql 文件而不是写入数据库吗?

java - 在已经检测过的文件上从 gradle 运行 jacoco

java - 使用绝对定位将组件添加到框架

java - 为什么 SwingWorker 不向 EDT 返回对象?

Java String.replaceAll() 引用最新找到的组

java - 将原始 XmlElement 从 WCF 传递到 Apache CXF 客户端 (basicHttpBinding)

java在另一个类中编辑文本字段

java - 制作幻灯片程序

java - 执行键盘操作时遇到问题

java - 使用带有 GridBagConstraints 的 GridBagLayout 进行 Swing