带有安全管理器的 Swing 应用程序导致奇怪的 GUI 刷新问题
我有一个作为客户端的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如初始线程中所述, 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. TheSecurityManager
is probably adventitious; any change in timing, even changing platforms, may expose the flaw.好吧,您在 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.