1

我有一个作为客户端的 Swing 应用程序(驻留在可执行的签名 jar 中)。该应用程序还连接到服务器。当满足某些条件时,我会刷新 GUI(更具体地说,删除 a 的所有节点,JTree然后重新填充它)。当我按原样运行此客户端时(即,没有安全管理器,也没有驻留在可执行的签名 JAR 中),树刷新和更新没有任何问题。

但是,当我将客户端打包为已签名的 JAR(使用适当的策略文件)时,我会遇到刷新问题。当应用程序启动时,我JTree的没有展开。当我单击它一次时,它看起来已经展开,但子节点不显示。之后我必须单击它两次才能显示节点。此外,当我执行刷新(删除所有节点然后重新填充)时,UI 不会正确刷新。我(再次)必须单击根节点两次以刷新 GUI。

我尝试将 AWT 权限添加到策略文件,但这没有帮助(我一开始没有看到任何权限违规,但我想我会尝试)。我什至尝试为 JAR 授予所有权限。这似乎也没有帮助。这可能是什么原因造成的?

执行刷新的代码如下:

private void buildTree() throws IOException, ClassNotFoundException {
    setVisible(false);
    tree.removeTreeWillExpandListener(this);
    tree.removeTreeSelectionListener(this);

    DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
    DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
    root.removeAllChildren();

    root.setUserObject(base);

    Book[] bookArray = remoteLibraryService.getAllBooks();
    TreeBuilderService.buildTree(root, bookArray);
    treeModel.reload();

    for(int i = 0; i < tree.getRowCount(); i++) {
        tree.expandRow(i);
    }

    tree.addTreeSelectionListener(this);
    tree.addTreeWillExpandListener(this);
    setVisible(true);
}

填充树的代码(仅显示相关代码段):

categoryNode = new DefaultMutableTreeNode(book.getGenre());
root.add(categoryNode);

就任务而言,这可能不会破坏交易,但这确实让我感到困扰;我想弄清楚是什么原因造成的。

4

2 回答 2

2

好吧,您在 GUI 刷新周期中执行 IO,因此 GUI 线程很可能因此被阻塞/停止。而是考虑通过其 API 使用 SwingWorker 和 Tree 的异步填充。

于 2010-11-12T07:31:57.157 回答
2

正如在Initial Threads中所讨论的,Swing GUI 组件必须在事件分派线程上创建。根据经验,JTree从另一个线程操作时特别容易失败。SecurityManager可能是偶然的;时间的任何变化,甚至是平台的变化,都可能暴露出这个缺陷。

于 2010-11-12T08:55:15.623 回答