让我解释一下我需要什么以及我来得多远:
我有一个JTree
带有自定义模型和一些漂亮的图标,一切正常,但是,树的默认颜色(白色)不适合我试图设计的GUI我希望能够改变它的背景颜色。
这已被证明是一件苦差事!
我已经在网络上看到了很多这方面的解释,它们似乎围绕扩展DefaultTreeCellRenderer
或BasicTreeUI
,但有一些暗示这些都是黑客,应该避免,虽然没有解释为什么他们是黑客或应该做什么。
在任何情况下,建议的方法似乎都不能很好地工作,因为我总是最终得到两种情况之一:
颜色在树中设置,但树标签的末尾和树的右侧之间,标签和它们的图标之间以及用于展开树的正/负小部件之间存在令人讨厌的间隙。在这种情况下,建议实施完整的行选择。
另一个场景已经实现了完整的行选择,并且节点正确着色并且完整行选择有效,但是图标要么完全丢失,要么加/减小部件,或者两者都有一个令人讨厌的白色边框。 / p>
我自己的尝试失败了,我现在留下了以下代码,它为树和节点着色,但仍然在树标签的末尾和所有图标之间留下令人讨厌的白色边框。
final Color MainBg = new Color(213,220,228);
KTree.setCellRenderer(new DefaultTreeCellRenderer()
{
@Override
public Component getTreeCellRendererComponent(JTree pTree, Object pValue, boolean pIsSelected, boolean pIsExpanded, boolean pIsLeaf, int pRow, boolean pHasFocus)
{
super.getTreeCellRendererComponent(pTree, pValue, pIsSelected, pIsExpanded, pIsLeaf, pRow, pHasFocus);
setBackgroundNonSelectionColor(MainBg);
setBackgroundSelectionColor(MainBg);
setTextNonSelectionColor(Color.BLACK);
setTextSelectionColor(Color.BLACK);
ImageIcon tDoc = createImageIcon("images" + File.separator + "document.gif","document");
ImageIcon tOpen = createImageIcon("images" + File.separator + "book_open.gif","book open");
ImageIcon tClosed = createImageIcon("images" + File.separator + "bookclosed.png","book closed");
setClosedIcon(tClosed);
setOpenIcon(tOpen);
setLeafIcon(tDoc);
putClientProperty("Tree.collapsedIcon", tDoc);
putClientProperty("tree.expandedIcon", tOpen);
return (this);
}
});
我的问题:
1)当然,我很感激帮助获得JTree
上的颜色设置,我很乐意接受建议,但如果您打算发布链接,我很有可能已经在那里在过去的几天里,还有......
2)我很欣赏对该过程所涉及的确切解释。我阅读了很多关于JTree
的教程,但没有关注完全着色树的问题(如果有的话),这就是我正在寻找的,似乎有一些关于究竟是什么的讨论必需的,例如是否完整行选择,是否继承子类等等。
我还想了解为什么某些事情被认为是' hacks'什么是替代品。
我正在添加这一部分,以显示我在整理过程中取得的进展,并且可能让其他人在一个相当繁琐的过程中先行一点。我花了好几天试图让这个系统与L& F系统正常工作,我已经圈了几次。毫无疑问,这很大程度上取决于缺乏经验,所以如果这样可以节省其他人一些头发拉动会话,那就更好了!
顺便说一句:如果我做了一些被认为是黑客的事情,我会非常高兴听到批评,但请提供一个(工作)替代方案和一些明确的推理背后的标签。好吧,让我们开始吧:我想设置系统L& F因为我不喜欢其他选项,因为我喜欢用户看到一个与他们习惯的东西相匹配的程序。在我做其他事情之前,我将L& F设置为这样:
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) { return; }
这会将JTree
设置为您正在使用的操作系统的标准。这似乎包括设置树本身的背景,以及节点选择的背景等。如果你想要的只是标准的JTree
,你就可以开始了,但是当我想看到基于系统的滚动条等时,我也希望看到背景以外的颜色而不是白色。
我将背景设置为一个漂亮的蓝色(请注意,颜色会在一瞬间再次使用,因此final
声明):
final Color MainBg = new Color(213,220,228);
KTree.setBackground(MainBg);
我现在拥有的是具有漂亮蓝色背景的JTree
,其仅覆盖不包含节点的树的那些区域,其根据L& F的设置保持白色。我现在需要为节点本身设置一些颜色,为此我需要使用以下代码覆盖getTreeCellRendererComponent
的{{1}}:
DefaultTreeCellRenderer
以上是 createImageIcon 。这直接来自一个教程,但请注意,这是在我完成之前编辑的(所以不要复制并粘贴此代码!):
final Color SellBg = new Color(232,235,237);
final Color HiliBg = new Color(150,196,246);
KTree.setCellRenderer(new DefaultTreeCellRenderer()
{
@Override
public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
{
super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus);
setBackgroundNonSelectionColor(MainBg);
setBackgroundSelectionColor(SellBg);
setTextNonSelectionColor(Color.BLACK);
setTextSelectionColor(Color.BLACK);
ImageIcon tDoc = createImageIcon("images" + File.separator + "document.gif","document");
ImageIcon tOpen = createImageIcon("images" + File.separator + "book_open.gif","open");
ImageIcon tClosed = createImageIcon("images" + File.separator + "bookclosed.png","closed");
setClosedIcon(tClosed);
setOpenIcon(tOpen);
setLeafIcon(tDoc);
setBorderSelectionColor(HiliBg);
return this;
}
});
如果您正在关注代码,那么在此阶段您将看到我为树节点设置了各种颜色,并为它们添加了一些图标。所有这一切都很好,但是现在节点文本的末端和protected ImageIcon createImageIcon(String path, String description)
{
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null)
{
return new ImageIcon(imgURL, description);
}
else
{
System.err.println("Couldn't find file: " + path);
return null;
}
}
本身的边缘之间以及节点文本和图标之间以及树的正/负小部件之间存在令人讨厌的白色块。 。这些白色块在扩展时也会穿过树。
这就是我进来的地方,头发拉开了。感谢Jacob'建议和MadProgrammer'提示(谢谢你们)我在正确的轨道上,但这是事情变得奇怪的地方,很可能是因为我已经在忙着用JTree
来试图让事情发挥作用。将代码回滚到以前的版本并再次启动此部分有助于使工作正常运行。
快速注意:如果我以错误的方式做这件事,请告诉我!
似乎要更改JTree
的白色部分,我需要覆盖JTree
,我这样做了:
BasicTreeUI
我必须声明这不是我的代码 - 我在众多教程网站中的一个上找到了它,它按照建议工作,我的KTree.setUI(new javax.swing.plaf.basic.BasicTreeUI()
{
@Override
public Rectangle getPathBounds(JTree tree, TreePath path)
{
if(tree != null && treeState != null)
{
return getPathBounds(path, tree.getInsets(), new Rectangle());
}
return null;
}
private Rectangle getPathBounds(TreePath path, Insets insets, Rectangle bounds)
{
bounds = treeState.getBounds(path, bounds);
if(bounds != null)
{
bounds.width = tree.getWidth();
bounds.y += insets.top;
}
return bounds;
}
});
现在有正确的背景,但是,加/减小部件有disapeared!
很可能有一种简单的方法可以在上面的代码中设置这些小部件,但是我注意到雅各布关于弄乱JTree
的警告,所以我直接放置了以下代码 之后我设置了L& F:
BasicTreeUI
这会将加/减小部件图标设置为我自己的一些,并在树中的元素之间设置我想要的画线类型。请注意,此时我收到错误,因为无法访问之前的非静态 createImageIcon 。我必须编辑这样的代码以允许同时调用此方法:
ImageIcon clapsed = createImageIcon("images" + File.separator + "plus.gif","closed");
ImageIcon clopen = createImageIcon("images" + File.separator + "minus.gif","open");
UIManager.getLookAndFeelDefaults().put("Tree.collapsedIcon",clapsed);
UIManager.getLookAndFeelDefaults().put("Tree.expandedIcon",clopen);
UIManager.getLookAndFeelDefaults().put("Tree.paintLines", true);
UIManager.getLookAndFeelDefaults().put("Tree.leftChildIndent",7);
UIManager.getLookAndFeelDefaults().put("Tree.lineTypeDashed",true)
我现在(终于!)有一个protected static ImageIcon createImageIcon(String path, String description)
{
Class<?> cl=new Object(){}.getClass().getEnclosingClass();
java.net.URL imgURL = cl.getResource(path);
if (imgURL != null)
{
return new ImageIcon(imgURL, description);
}
else
{
System.err.println("Couldn't find file: " + path);
return null;
}
}
,系统L&amp; F设置,并为树的所有元素设置颜色。
仍有未解决的问题:
我(还)没有完全理解JTree
代码 - 这给了我我需要的颜色,但似乎也给了我全行选择。但是我无法让选择颜色跨越整个距离。我打算稍后再玩这个,但是我要谨慎,感谢Jacob&#39;警告 - 如果有人对此有任何严格的规定,我会非常乐意听到这些规则。
我还故意设置L&amp; F,以便用户可以看到他们熟悉的东西,尽管颜色不同。但是,我被迫将自己的图标添加到加/减树小部件,这不是一个真正的问题,而是一个小小的问题。这可能会在以后清理。
我的另一个问题是,当使用BasicTreeUI()
设置值时,我只能设置某些键,其他键显然会被忽略。 MadProgrammer确实指出使用Nimbus可能会使这些键混乱一点,所以也许使用L&amp; F系统有它自己的怪癖。
无论如何,这是我努力的结果。我为这篇文章的篇幅道歉,但我希望这可以帮助别人,如果我以错误的方式做了某些事情,那么有人可以向我指出正确的方法。< / p>
此致
MVK
答案 0 :(得分:3)
如果您已经覆盖getTreeCellRendererComponent
以便树项具有您想要的颜色,则可以使用
UIManager.getLookAndFeelDefaults().put("Tree.background", new ColorUIResource(aColor);
更改树中“未占用”空间的颜色。请注意,这将影响所有未来树。组件UI类使用此属性,许多人在绘制组件时都喜欢它。要找出存在哪些键,您可以执行以下操作:
for (Entry<Object, Object> entry : UIManager.getLookAndFeelDefaults().entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
至于你的其他问题,我永远不会考虑将getTreeCellRendererComponent
覆盖为黑客,但不小心延伸BasicTreeUI
可能会导致某些外观出现意外行为。
答案 1 :(得分:0)
如果您正在寻找的是一种在JTree中同时拥有系统L&amp; F和彩色背景+文本的方法,那么这就是您需要的所有代码:
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
UIManager.getLookAndFeelDefaults().put("Tree.background", new ColorUIResource(Util.BACKGROUND));
UIManager.getLookAndFeelDefaults().put("Tree.textBackground", new ColorUIResource(Util.BACKGROUND));
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}