How to set tooltip in TreeCellRenderer? - java

I am stuck with setting a tooltip to one of my JPanel added to the node in a JTree. This question could be similar to JTree node's changable tooltip but not entirely.
I am also using JTree populated with some (custom) nodes. Each node contains a checkbox, a color box (JPanel) and node path. I am implementing TreeCellRenderer. I have not posted below code for what is being added to node as I think it is not necessary.
Below is part of my code:
public class CheckTreeCellRenderer extends JPanel implements TreeCellRenderer {
private static final long serialVersionUID = 4025435851260573240L;
CheckTreeSelectionModel selectionModel;
private TreeCellRenderer delegate;
TristateCheckBox checkBox = new TristateCheckBox();
JPanel panel = new JPanel();
public CheckTreeCellRenderer(TreeCellRenderer delegate, CheckTreeSelectionModel selectionModel){
this.delegate = delegate;
this.selectionModel = selectionModel;
setLayout(new BorderLayout());
setOpaque(false);
checkBox.setOpaque(false);
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus){
Component renderer = delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
panel.setToolTipText("Hello");
removeAll();
add(checkBox, BorderLayout.WEST);
add(panel, BorderLayout.CENTER);
add(renderer, BorderLayout.EAST);
return this;
}
}
How to set a tooltip for JPanel added to a node?

Have a look at the docs of JTree.getToolTipText:
NOTE: For JTree to properly display tooltips of its renderers, JTree must be a registered component with the ToolTipManager. This can be done by invoking ToolTipManager.sharedInstance().registerComponent(tree). This is not done automatically!
This will fix it.

Related

Adding JPanel to JList

I want to add a custom objects that extend JPanel into a JList. Everything is fine, but I can not interact with them. For example, I can not type in the JTextField which is added on panel. I Use DefaultListModel<ListItem = new DefaultListModel<ListItem>(); Plase help.
This is custom Object
public class ListItem extends JPanel{
private static final long serialVersionUID = 1L;
private JTextField textField;
public ListItem() {
setLayout(new MigLayout("", "[grow][grow]", "[30px:n:30px][30px:n:30px][30px:n:30px]"));
JLabel lblNewLabel = new JLabel("New label");
add(lblNewLabel, "cell 0 0,alignx trailing");
textField = new JTextField();
add(textField, "cell 1 0,growx");
}
This is the renderer
public class ListItemRenderer implements ListCellRenderer<Object>{
#Override
public Component getListCellRendererComponent(JList<? extends Object> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
Component component = (Component) value;
if(isSelected)
component.setBackground(Color.RED);
return component;
}
This is how I create List
list = new JList<ListItem>(addedItems);
And
ListItem temp = new ListItem();
addedItems.addElement(temp);
list.setCellRenderer(new ListItemRenderer());
I want to add a custom objects that extend JPanel into a JList. Everything is fine, but I can not interact with them. For example, I can not type in the JTextField which is added on panel.
That is because a Jlist does not hold or show components but rather only rendering of components. If you want a list like object that holds components that can be edited, that the user can interact with, then either create your own -- using a JPanel that uses GridLayout and holds a grid of your components, or use a JTable that has at least two columns, one (the "label") that's not editable, and the other (the "text field") that is.

How to refresh JTree UI

I have a JTree that shows files and folders of a directory. Also there is a button that disables some of the nodes in the JTree (using DefaultTreeCellRenderer).
The item gets disabled when I press the button, but JTree does not show it as a disabled item. Until I click somewhere, or in on if the items of the tree, then it also shows the disabled look of the item.
I know there is a reload() method for DefaultTreeModel. But I use a customised model. So this method doesnt work. Here is the model that I use to list files and folders: FileSystemModel
And this is my code:
public class FileViewer {
JFrame frame;
JPanel panel;
JTree tree;
File root;
public ArrayList<String> disabledNodes = new ArrayList<String>();
public FileViewer(){
frame = new JFrame("File Viewer");
panel = new JPanel(new BorderLayout());
root = new File("D:\\Documents\\A X");
FileSystemModel model = new FileSystemModel(root);
tree = new JTree();
tree.setModel(model);
panel.add(tree, BorderLayout.CENTER);
JButton press = new JButton("Press");
panel.add(press, BorderLayout.SOUTH);
press.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
disabledNodes.add("folder1");
}
});
tree.setCellRenderer(new CustomDefaultTreeCellRenderer());
frame.add(panel);
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new FileViewer();
}
class CustomDefaultTreeCellRenderer extends 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);
File node = (File)value;
String name = node.getName();
for(String element : disabledNodes){
if(name.equals(element)){
this.setEnabled(false);
}
}
return this;
}
}
}
However, in the ActionListener of the button, I added tree.updateUI(); and it perfectly worked. But somehow I have heard updating UI is a bad practice since it will make other problems later. So is using updateUI correct here? or there is a better way to make the UI updated with clicks and user interactions?
Note, I will not add or remove any file from the tree, I just have to enable/disable nodes.
UPDATE: I just notice there is a repaint() option that does similar function for me. But still, Is it the right way of refreshing the JTree?
repaint() is the correct API to use in this situation.

ListCellRendererComponent() method updates all the objects(elements) of JList similar to last added element

hi there i implemented a JList which contains JLabels as elements. My aim is implementing a contact list for server/client chat application. So, when a client connects to a server, JList will build to show his/her contact list.I selected to use JLabels cause they can have icons and text as well. However, i'm getting some trouble about overridden cellrenderer method. Whenever, a client gets online/offline JList updates its state and set all the items similar to the last added item. It's something like this,
this is the first time adding an offline state client into the friend list of a person;
afterwards, this is the second time adding a different client
and finally third time...
Furthermore, i remember that in tutorial it mention about JList overrides pain method and draw whole elements again and again when there is a change in the list. Well actually i'm a newbie about this rendering subject and this thing gets very annoying. Here you can see my renderer class;
RendererSample
and add an element into the model like this way in my main class
labelSetText = tempon.getNickName();
onlineStatus = tempon.isIsOnline();
model.addElement(createPanel());
and also createPanel() returns a JLabel which is like;
public static JLabel createPanel() {
JLabel panel = new JLabel();
return panel;
}
i hope that i have been clear about my problem. I have to achieve that when a contact changes his/her state or when a contact is added this action shouldn't affect the other elements. I will be very appreciate for every answers (and also if you can add brief explanation that what and why you did i will be grateful.) well thanks anyway
You should not put components such as JLabel into JList. Instead, use a model to hold the data and add a renderer to customize the presentation. See How to Use Lists for some examples.
Here is a very basic example of a renderer that adds icon:
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.*;
public class TestUserList {
public static class UserRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean hasFocus) {
if (value instanceof UserEntry) {
UserEntry user = (UserEntry) value;
JLabel label = (JLabel) super.getListCellRendererComponent(
list, user.getName(), index, isSelected, hasFocus);
if (user.isOnline())
label.setIcon(UIManager
.getIcon("OptionPane.informationIcon"));
else
label.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
return label;
}
return super.getListCellRendererComponent(list, value, index,
isSelected, hasFocus);
}
}
public TestUserList() {
JFrame frame = new JFrame("User List");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JList list = new JList();
JScrollPane scrollPane = new JScrollPane(list);
JPanel content = new JPanel(new BorderLayout());
content.add(scrollPane, BorderLayout.CENTER);
final DefaultListModel model = new DefaultListModel();
model.addElement(new UserEntry("John", true));
model.addElement(new UserEntry("Jesse", false));
list.setModel(model);
list.setCellRenderer(new UserRenderer());
frame.add(content);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public class UserEntry {
private String name;
private boolean online;
public UserEntry(String name, boolean online) {
super();
this.name = name;
this.online = online;
}
public String getName() {
return name;
}
public Boolean isOnline() {
return online;
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestUserList();
}
});
}
}

How do I insert a JPanel inside a JLabel?

I am writing a custom jlist cell renderer for some kind of filechooser. My problem is that when I read my ImageIcon, it seems it has the dimension (-1,-1), so I can't resize it properly. The picture is a simple texture (wood, metal, etc.).
Then I thought that if I added a JPanel instead of an image, and then adding the image to the panel, I wouldnt even have to resize the picture.
I have 2 possibilities:
Read the ImageIcon from the hard drive so that they dont have dimension -1,-1
Insert a JPanel inside the JLabel.
Here is a preview of my list cells.
Here is my custom renderer, which adds icons to the cells.
class IconListRenderer extends DefaultListCellRenderer {
private Map<Object, Icon> icons = null;
public IconListRenderer(Map<Object, Icon> icons) {
this.icons = icons;
}
#Override
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
// Get the renderer component from parent class
JLabel label =
(JLabel) super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
ImageIcon icon = (ImageIcon)icons.get(value);
// Set icon to display for value
label.setIcon(icon);
label.setText(value.toString());
return label;
}
}
Just replace the label with the panel.
You can use a JPanel as the rendercomponent instead of the JLabel.

JTable - compound editor focus

I have a custom editor composed of several components. Something like:
class MyCellEditor extends AbstractCellEditor implements TableCellEditor {
JTextArea textArea;
JButton button;
JPanel panel;
MyCellEditor() {
textArea = new JTextArea();
button = new JButton();
panel = new JPanel(new BorderLayout());
panel.add(textArea, BorderLayout.CENTER);
panel.add(button, BorderLayout.EAST);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
textArea.setText((String) value);
return panel;
}
public Object getCellEditorValue() {
return textArea.getText();
}
}
I want the inner textArea to grab focus when editing starts. It works just fine when I click the cell, but not when I navigate the table with keyboard and start typing in this cell.
How can I fix this?
I had the same problem some time ago and took me ages to find a solution. Tried a lot with focuslistener and stuff, but nothing really seemed to work the way I wanted it to until I found this useful article by Santhosh Kumar.
Its well written and should fix your problem.

Categories