I have some custom JTree. That tree has nodes with custom icons. I also have a class that extends DefaultTreeCellRenderer with method getTreeCellRendererComponent as simple as this:
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
MyTreeNode node = ((MyTreeNode) value);
Icon icon = node.getIcon();
setIcon(icon);
return this;
It works. My tree nodes will be rendered with custom icons in ICON TEXT format. BUT! Is there a way to put TWO icons in my node! I would like to have a node that looks like this: ICON TEXT ANOTHER_JLABEL_WITH_IMAGE.
How to do it?
You should create your own TreeCellRenderer that extends from something like a JPanel.
This way, you can define your own layout requirements and add your own components to support your requirements
You can also create an Icon which combines two (or more) other icons. See for example http://tips4java.wordpress.com/2009/03/29/compound-icon/
The default component used to render a Tree node is a JLabel. Thus you have access to the setIcon method.
But if you want to set two icons to a node you need to create a JPanel with two labels in it.
(J)Component / JLabel (returned by Renderer) haven't implemented any LayoutManager in the API
right JLabel has constructor for Text and Icon, there is not place for another Icon
basically every JComponents are containers too, part of Containers have got implemented LayoutManager in the API (JFrame, JPanel), you can to put any JComponent to the another
for example
great workarounds by camickr, especially Compound Icon
Related
I need to show multiple icons in a single column in JTable. I am using an modified Icon implementation.
Class IconCollection implements Icon {
Icon[] icons
}
Since it implements Icon interface , I am able to show multiple icons in single column. However I need to assign separate tooltips for each icon. Since JComponent has single setToolTipText() method, it is not possible.
Any suggestions?
Since the JTable has a decent implementation of getTooltipText which delegates to the component of the renderer, you can completely solve this in the renderer.
In the getTableCellRendererComponent method you can return any JComponent. If you would opt for a JPanel containing multiple icon instances with each a correct tooltip (instead of your big icon).
You could create a component to contain your icons and override getToolTipText(MouseEvent), basing the text returned on the relative position of the mouse.
I have a JList and inside that list, I want to change the color of the font of the following words.
Someone said that I have to use CellRenderer but I'm not yet familiar with that.
Now, my problem is how can I setup this renderer to change the color of the Font?
Any idea about this matter?
Thanks...
Check out the JavaDoc, it might just have what you need (the example at the top). Basically you just return a component (like a JLabel) with a configured font color.
Edit: since you want to have the words in a different color than their definitions, here two possibilities how that can be done with the list cell renderer:
Return a JPanel that contains 2 JLabels, one with the word and one with the definitions. Both labels can have different foreground colors.
JLabel supports HTML (like other Swing components do), so you might just set the text of the label as <html><font color=red>your word</font> - your definitions</html>. Note that the default foreground color should then be the one for the definitions, alternatively you can wrap the definitions with a <font> tag as well. Have a look at this Tutorial.
For JLabel components try:
new DefaultListCellRenderer(){
#Override
public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus ) {
JLabel label = (JLabel)super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
label.setForeground( Color.RED );
return label;
}
};
consider ...., that would be better using a JTable with one TableColumn and without TableHeader as the JList, demonstrated here, here, by using prepareRenderer, because JList has lots of restriction/missed methods as JTable
Is it possible to assign different icons to different nodes in a JTree using DefaultTreeCellRenderer.setOpenIcon()? Thanks.
The same cell renderer instance is used to render all the cells of the tree. The open icon is the little + symbol, or triangle symbol at the left of every tree node which allows to expand it (i.e. see its child nodes). I doubt this is the icon you want to change. It would be rather strange not to use the same one for all the nodes.
If you want to display a custom icon for a specific node, create a subclass of DefaultTreeCellRenderer, override the getTreeCellRendererComponent method, decide which icon to display based on the value passed to the method, and call setIcon.
See http://download.oracle.com/javase/tutorial/uiswing/components/tree.html#display for a similar example (which customized the tooltip, and not the icon, but the idea is the same).
What I'm trying to do is create a JTree with each cell containing normal text but also containing a right-aligned text for each cell (right-aligned to the edge of the tree, regardless of the hierarchy level).
I've tried creating my own TreeCellRenderer, but the cells' sizes are not being updated. I also tried this idea with a custom tree UI but am experiencing similar issues.
I also have tried creating a custom component with a JPanel "glued" to the right of the tree. This has been the most successful, but I have been unable to have the tree cells extend to the right and touch this extra panel:
alt text http://img718.imageshack.us/img718/3676/problem.png
You could try to use a JXTreeTable, from the SwingX package.
jxtreetable example http://blogs.sun.com/geertjan/resource/outline-tim-browser.png
You would define then such an object with two columns (one for the tree, to other for the right aligned text), and it should work out fine.
To prevent it from looking like a table, though, I would recommend you to deactivate the header (setTableHeader(null)), and use their "packing" methods, to have the columns on optimal size.
I am working on a GUI where the JComponents are "stamped" on the screen. In other words, the actual components aren't displayed, but images of the components. This is a graph, where the nodes of the graph are custom Swing components - or rather stamped images of Swing components.
Now I want to display tooltips for specific components within my nodes.
To do this, I create a JComponent that is identical to the one displayed and using the mouse x and y values, I ask findComponentAt() for the proper component. This doesn't work very well. If I reuse JComponents for the nodes, it gets confused if I try to get a tooltip for a node that is a different size than the last one painted. If I create a new JComponent for each node and a new one when calculating the tooltip, the initial size of the new one is 0,0. I can set the size using the getPreferredSize() calculation, but that still doesn't work. The root JComponent (a JPanel) has the right size, but none of it's children have any size yet.
A sample of the tooltip calculation code:
// Get a component that matches the stamped component
JComponent nodeComponent = getNodeComponent();
// These next two lines get the size right
nodeComponent.setSize(nodeComponent.getPreferredSize());
nodeComponent.revalidate();
Component componentTop = nodeComponent.findComponentAt(relativeX, relativeY);
componentTop comes back as the root JComponent no matter what x and y values it is passed.
So is it possible to get Swing to properly calculate the size and locations of the JComponents without actually painting them?
You have images of your components in the graph they have to have their sizes to be able to paint correctly.
To find your "stamp" you should walk backwards (in z-order) in your graph and find the first image your mouse position fall into.
Preferred sizes will not work, you should rely on size of "stamps" i think.
I found the answer myself. The key problem is that Swing doesn't want to layout a component unless that component has a proper parent. So, I changed my code to this:
parentComponent.add(nodeComponent);
// Set the node's size and validate it so it's laid out properly
nodeComponent.setBounds((int)realizer.getX(), (int)realizer.getY(), (int)realizer.getWidth(), (int)realizer.getHeight());
nodeComponent.validate();
// Now we can properly find the child component under our mouse
Component componentTop = nodeComponent.findComponentAt(relativeX, relativeY);
// Now remove it from the view
parentComponent.remove(nodeComponent);
And that works like a charm. You should be able to use a similar process to find child components in JLists or JTables (which also use this Renderer pattern).