带有安全管理器的 Swing 应用程序导致奇怪的 GUI 刷新问题

发布于 2024-10-02 14:14:29 字数 1404 浏览 7 评论 0原文

我有一个作为客户端的 Swing 应用程序(驻留在可执行的、签名的 jar 中)。该应用程序还连接到服务器。当满足某些条件时,我会刷新 GUI(更具体地说,删除 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);

分配而言,这可能不是一个破坏性的事情,但它确实困扰着我;我想弄清楚是什么原因造成的。

I have a Swing app (residing in an executable, signed jar) that is a client. The app also connects to a server. When certain conditions are met, I perform a refresh of the GUI (more specifically, delete all nodes of a JTree and then repopulate it). When I run this client as-is (i.e., without a security manager and without residing in an executable, signed JAR), the tree refreshes and updates without any issue.

However, when I package my client as a signed JAR (with the appropriate policy file), I get refresh issues. When the app starts up, I my JTree is not expanded. When I click it once, it looks like it has expanded, but the child nodes do not show. I have to click it twice after that for the nodes to show. Also, when I perform a refresh (deleting all nodes and then repopulating), the UI doesn't refresh appropriately. I (again) have to click the root-node twice to refresh the GUI.

I tried adding AWT permissions to the policy file, but that didn't help (I wasn't seeing any permission-violations in the first place, but I thought I'd try). I even tried giving the JAR all permissions. That didn't seem to help either. What could be causing this?

The code that performs the refresh is as follows:

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);
}

The code that populates the tree (showing just the relevant snippet):

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

This probably isn't a deal-breaker as far as the assignment is concerned, but it is really bothering me; I'd like to figure out what's causing it.

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

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

发布评论

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

评论(2

夜无邪 2024-10-09 14:14:29

正如初始线程中所述, Swing GUI 组件必须在事件调度线程上创建。根据经验,当从另一个线程进行操作时,JTree 特别容易失败。 SecurityManager 可能是偶然的;时间的任何改变,甚至改变平台,都可能暴露该缺陷。

As discussed in Initial Threads, Swing GUI components must be created on the event dispatch thread. Empirically, JTree is particularly susceptible to fail when manipulated from another thread. The SecurityManager is probably adventitious; any change in timing, even changing platforms, may expose the flaw.

吻泪 2024-10-09 14:14:29

好吧,您在 GUI 刷新周期中执行 IO,因此 GUI 线程很可能会被阻止/停止。
相反,请考虑使用 SwingWorker 并通过其 API 异步填充树。

Well you are doing IO in the GUI refresh cycle, so the GUI thread might well be blocked/stalled as a result.
Instead consider using a SwingWorker and asynchronous population of the Tree through its API.

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