У меня есть JTree
, с CustomTreeCellRenderer
, где я меняю представление узлов JCheckBoxes. Все работает до сих пор.
Теперь, в моем CustomTreeCellRenderer
, когда я определяю JCheckBox
, который должен быть возвращен, я устанавливаю ActionListener
для каждого из них.
В ActionListener
я печатаю только имя JCheckBox
, просто чтобы посмотреть, запущено событие или нет.
Моя проблема заключается в следующем: когда я нажимаю на флажок, чтобы изменить состояние, событие ActionListener
никогда не запускается, поэтому имя JCheckBox
нажата никогда не отображается. Я думаю, что я не делаю ничего странного здесь, поэтому я не способен понять, почему ActionListener
не срабатывает. Это может быть потому, что флажки находятся внутри JTree
, и мне нужно сделать что-то еще, чтобы это работало? Раньше я использовал слушателей в флажках, но не внутри деревьев, и мне не нужно было делать ничего особенного ...
Также я видел, что с использованием ItemListener
и ChangeListener
вместо ActionListener
для моих флажков событие запускается много раз, и это не то поведение, которое я хочу. Я искал об этом множественных пожарах событий при использовании этих двух слушателей, и я нашел это:
Несколько событий ITEM_STATE_CHANGED из jcheckbox в jtree
Я просто хочу бросить событие один раз, используя ActionListener
, я думаю, что это из-за JTree
, но я не могу найти причину, по которой оно не запускается.
Если это можно сделать, используя ItemListener
или ChangeListener
, но выбрасывая событие только один раз, это может быть полезно и для меня.
Вот код (я пытался максимально упростить это):
Основной класс:
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MainItemListener {
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JTree tree = new JTree();
//Define the root node
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Node", true);
//Define the child nodes and add it to the root node
for (int i = 0; i < 3; i++){
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode("Child " + i, false);
root.add(childNode);
}
//Set the tree model
DefaultTreeModel treeModel = new DefaultTreeModel(root);
tree.setModel(treeModel);
//Set my custom tree cell renderer
tree.setCellRenderer(new CustomTreeCellRenderer());
//Set the frame
frame.setSize(800,600);
frame.setVisible(true);
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); // Close the application when closing the window
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent aEvent) {
System.exit(0); //Close Application
}
});
panel.add(tree, BorderLayout.CENTER);
frame.add(panel);
}
}
CustomTreeCellRenderer
import javax.swing.*;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;
public class CustomTreeCellRenderer 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);
//Convert each node to a JCheckBox and return the JCheckBox
JCheckBox checkBox = new JCheckBox();
checkBox.setOpaque(true);
checkBox.setSelected(sel);
checkBox.setText(value.toString());
//Set the ActionListener to each JCheckBox
checkBox.addActionListener(new ActionListenerSample());
return checkBox;
}
}
ActionListenerExample
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ActionListenerSample implements ActionListener {
//Just print the name of the JCheckBox to see how this event is fired
@Override
public void actionPerformed(ActionEvent e) {
JCheckBox component = (JCheckBox) e.getSource();
System.out.println(component.getText());
}
}