When I add a file object into a DefaultListModel, which is used to create a JList, with model.addElement(file), the displayed text in the JList is the path to the file. But I only want the file name to be displayed. I cannot do model.addElement(file.getName()), however, because I need access to the file object, not just a string, later on.
How can I add a file object to a list/model while displaying only the file name? Thank you!
You would do this by creating a custom renderer:
class FileRenderer extends DefaultListCellRenderer
{
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
File file = (File)value;
setText( file.getName() );
return this;
}
}
Then you set the renderer for the JList using:
list.setCellRenderer( new FileRenderer() );
For more information and working examples see the section from the Swing tutorial on Writing a Custom Cell Renderer
Related
So I have a class called Note and I need to put every Note inside a JComboBox.
Each Note has a String id and a String title. The title is being shown to the user, and the id is being used in the backend.
I've written a custom renderer to make this work, but I am getting compiler error: error: Note cannot be converted to String
Here is the code:
//Inside of the GUI class
cmbNotes.setRenderer(new NoteListCellRenderer());
//Populate combo box with the title of each note
NoteManager.notes.forEach((id, note) -> { //For-each loop
if (!note.isOpen()) {
cmbNotes.addItem(note); //ERROR: Note cannot be converted to String
}
});
Here is my custom renderer:
//In the same file as GUI, but outside of the GUI class
class NoteListCellRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (value instanceof Note) {
value = ((Note) value).getTitle();
}
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
return this;
}
}
Thank you Riann Nel for helping me to solve this problem.
I had created the JComboBox through the design, not through code.
The design by default sets the Type Parameters to String so I went in the design and clicked on the code section on the right then changed the Type Parameters to <Note>.
I also had to add a default constructor in my Note class.
I am writing a simple text based chat application using applets in java, which consists of few components & one of them is my Jlist which provides list of online users at that particular point of time.
What i want is that i need to set a small picture besides online user name in Jlist.
Does anyone have any idea based on this. Please feel free to ask if you have any questions.
Thanks,
Puneet
The JList documentation has an example that loads icons into the JList. You should be able to use this to insert your small pictures into the JList.
http://docs.oracle.com/javase/6/docs/api/javax/swing/JList.html
Here is the relevant code from that link:
// Display an icon and a string for each object in the list.
class MyCellRenderer extends JLabel implements ListCellRenderer {
final static ImageIcon longIcon = new ImageIcon("long.gif");
final static ImageIcon shortIcon = new ImageIcon("short.gif");
// This is the only method defined by ListCellRenderer.
// We just reconfigure the JLabel each time we're called.
public Component getListCellRendererComponent(
JList list, // the list
Object value, // value to display
int index, // cell index
boolean isSelected, // is the cell selected
boolean cellHasFocus) // does the cell have focus
{
String s = value.toString();
setText(s);
setIcon((s.length() > 10) ? longIcon : shortIcon);
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setEnabled(list.isEnabled());
setFont(list.getFont());
setOpaque(true);
return this;
}
}
myList.setCellRenderer(new MyCellRenderer());
Assuming your JList contains usernames, you could put your usernames in a HashMap
setIcon(userHashMap.get(s));
If your JLIst is actually store other parts than just the username (dynamic components such as status, group name, etc.) you may need to parse out the username from the String passed into the value object.
I have two JTree in two panels in a JFrame. I want to change the style(color and font) of nodes on drag and drop from one tree to the other.Please provide me a way to change the color of a JTree node permanently.
To start, you will need to have a data object that can handle style and color. You could subclass DefaultMutableTreeNode and add these data items with getts and setters
Then you'd need to create a custom TreeCellRenderer. I recommend extending DefaultTreeCellRenderer, and in the overridden handler, checking for your custom class, and modifying the JLabel output to use the Font and Color if these values are set
Create your own CellRenderer. To give the appropriate behaviour to your MyTreeCellRenderer, you will have to extend DefaultTreeCellRenderer and override the getTreeCellRendererComponent method.
public class MyTreeCellRenderer extends DefaultTreeCellRenderer {
#Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, exp, leaf, row, hasFocus);
// Assuming you have a tree of Strings
String node = (String) ((DefaultMutableTreeNode) value).getUserObject();
// If the node is a leaf and ends with "xxx"
if (leaf && node.endsWith("xxx")) {
// Paint the node in blue
setForeground(new Color(13, 57 ,115));
}
return this;
}
}
Finally, say your tree is called myTree, set your CellRenderer to it:
myTree.setCellRenderer(new MyTreeCellRenderer());
It is weird that I set my JTable cell renderer like this:
setDefaultRenderer(Object.class, new MyTableRenderer());
My table renderer works like this:
class MyTableRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Component comp = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
Font font = comp.getFont();
if (table.getModel().getValueAt(row, 0).equals(BUY)) {
comp.setFont(font.deriveFont(Font.BOLD));
comp.setForeground(BUY_COLOR);
}
else {
comp.setFont(font.deriveFont(Font.BOLD));
comp.setForeground(SELL_COLOR);
}
return comp;
}
}
But it turns out, it didin't apply those columns that have type "BigDecimal", Other String fields are all working fine.
And then, I add one more line:
setDefaultRenderer(BigDecimal.class, new MyTableRenderer());
Then everything just work fine.
Why it is like this?
JTable by default installs a renderer for type Number. BigDecimal is-a Number so the default renderer is used instead of your custom renderer.
BTW: your custom renderer is buggy in that it doesn't take potentially sorted/filtered rows into account (the row/column index params of the method are view coordinates).
#eugener: your answer is wrong - it's not the storage that's important but the lookup ;-)
Cheers
Jeanette
Take look at the source code of the JTable:
public void setDefaultRenderer(Class<?> columnClass, TableCellRenderer renderer) {
if (renderer != null) {
defaultRenderersByColumnClass.put(columnClass, renderer);
} else {
defaultRenderersByColumnClass.remove(columnClass);
}
}
It uses a map where column class is a key and means that class comparison is literal. This should explain the reason for behavior you're experiencing. This is by design.
I have a JComboBox and have 10 string items added in it.
I want to assign different colors to each item.
How i can achive this?
Please help.
The example in Chandru's answer looks like a lot of code so I can understand why you're asking for an easier solution. However, if you subclass DefaultListCellRenderer a lot of the work is done for you, as this renderer is a subclass of JLabel.
JList list = ... // Create JList
// Install custom renderer.
list.setCellRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// Request superclass to render the JLabel.
Component ret = super.getListCellRenderer(list, value, index, isSelected, cellHasFocus);
// Now conditionally override background if cell isn't selected.
if (!isSelected) {
String s = String.valueOf(value);
if (s.equals("Foo")) {
ret.setBackground(Color.RED);
} else {
ret.setBackground(Color.GREEN);
}
}
return ret;
}
});
You must use a custom list cell renderer. Look into this how-to for an example.
You must implement a new ListCellRenderer ,which will be used by your combobox, through setRenderer, to render properly your objects.
You can extend BasicComboBoxRenderer to avoid reconding everything.