2016-12-04 2 views
1

Pour un projet sur lequel j'ai travaillé, j'ai dû créer un JTree avec un JToggleButton sur chaque ligne, et deux sur chaque ligne en fait. Donc pour faire ce travail, comme vous le verrez dans le MCVE, j'ai écrit un DefaultTreeCellRenderer personnalisé et un AbstractCellEditor personnalisé.Sauvegarde de la sélection dans JToggleButton

Cependant, il y a un problème avec l'édition si le JToggleBox est sélectionné ou non. Initialement, lorsque vous sélectionnez la première valeur à modifier, cela fonctionne correctement. Et si vous restez sur cette ligne du JTree et ne cliquez pas ailleurs mais sur le JToggleButton cela fonctionne très bien. Si vous cliquez ailleurs, les valeurs que vous définissez sont perdues.

Comment les valeurs de consigne du JToggleButton peuvent-elles être conservées lorsqu'un autre emplacement est cliqué?

MCVE

import java.awt.Color; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.event.ItemEvent; 
import java.awt.event.ItemListener; 
import java.awt.event.MouseEvent; 
import java.util.EventObject; 

import javax.swing.AbstractCellEditor; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JToggleButton; 
import javax.swing.JTree; 
import javax.swing.event.ChangeEvent; 
import javax.swing.plaf.metal.MetalToggleButtonUI; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeCellRenderer; 
import javax.swing.tree.TreeCellEditor; 
import javax.swing.tree.TreePath; 

@SuppressWarnings("serial") 
public class DirectoryExplorer extends JFrame { 
    private DirectoryExplorer() { 
     super("Directory Explorer"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLayout(new GridLayout(1, 1)); 
     createPanel(); 
     setSize(800,600); 
     setVisible(true); 
    } 

    private void createPanel() { 
     DefaultMutableTreeNode colors = new DefaultMutableTreeNode("Colours"); 
     colors.add(new DefaultMutableTreeNode("Red")); 
     colors.add(new DefaultMutableTreeNode("Green")); 
     colors.add(new DefaultMutableTreeNode("Blue")); 

     DefaultMutableTreeNode falvors = new DefaultMutableTreeNode("Flavours"); 
     falvors.add(new DefaultMutableTreeNode("Toffee")); 
     falvors.add(new DefaultMutableTreeNode("Fudge")); 
     falvors.add(new DefaultMutableTreeNode("Chocolate")); 

     DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); 
     root.add(colors); 
     root.add(falvors); 
     root.add(new DefaultMutableTreeNode("Leafy")); 

     JPanel panel = new JPanel(new GridLayout(1, 1)); 
     JTree tree = new JTree(root); 

     FileNameRenderer fileRender = new FileNameRenderer(); 
     tree.setCellRenderer(fileRender); 

     tree.setCellEditor(new CheckBoxNodeEditor(tree)); 
     tree.setEditable(true); 

     tree.setShowsRootHandles(true); 

     panel.add(new JScrollPane(tree)); 
     getContentPane().add(panel); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> new DirectoryExplorer()); 
    } 

    private class FileNameRenderer extends DefaultTreeCellRenderer { 
     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
      JComponent c = (JComponent) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 

      return new Holder((JLabel) c); 
     } 
    } 

    private class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor { 
     FileNameRenderer renderer = new FileNameRenderer(); 
     ChangeEvent changeEvent = null; 
     JTree t; 
     TreePath path; 

     public CheckBoxNodeEditor(JTree tree) { 
      t = tree; 
     } 

     public Object getCellEditorValue() { 
      Holder checkBoxNode = new Holder(new JLabel((((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject().toString()))); 
      return checkBoxNode; 
     } 

     public boolean isCellEditable(EventObject event) { 
      if(event instanceof MouseEvent) { 
       MouseEvent mouseEvent = (MouseEvent) event; 
       path = t.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()); 
       if (path != null) { 
        Object node = path.getLastPathComponent(); 
        if ((node != null) && (node instanceof DefaultMutableTreeNode)) { 
         DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node; 
         Object userObject = treeNode.getUserObject(); 
         return (userObject instanceof String); 
        } 
       } 
      } 
      return false; 
     } 

     public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) { 
      Component editor = renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true); 
      ItemListener itemListener = new ItemListener() { 
       public void itemStateChanged(ItemEvent itemEvent) { 
        if (stopCellEditing()) 
         fireEditingStopped(); 
       } 
      }; 

      if (editor instanceof JToggleButton) { 
       ((JToggleButton) editor).addItemListener(itemListener); 
      } 

      return editor; 
     } 
    } 

    private class Holder extends JPanel { 
     public Holder(Component c) { 
      setLayout(new GridBagLayout()); 
      setBackground(Color.BLACK); 
      setOpaque(false); 
      addComponents(c); 
     } 

     private void addComponents(Component c) { 
      GridBagConstraints gBC = new GridBagConstraints(); 

      gBC.insets = new Insets(0, 0, 0, 5); 
      add(c, gBC); 

      gBC.insets = new Insets(0, 0, 0, 0); 
      add(new DefaultChkBx(), gBC); 
      add(new FavouriteChkBx(), gBC); 
     } 
    } 

    private class DefaultChkBx extends JToggleButton { 
     public DefaultChkBx() { 
      setUI(new MetalToggleButtonUI() { 
       @Override 
       protected Color getSelectColor() { 
        return new Color(242, 0, 255); 
       } 
      }); 
      setBorder(null); 
      setForeground(Color.GRAY); 
      setText("Default"); 
      setFocusPainted(false); 
     } 
    } 

    private class FavouriteChkBx extends JToggleButton { 
     public FavouriteChkBx() { 
      setUI(new MetalToggleButtonUI() { 
       @Override 
       protected Color getSelectColor() { 
        return Color.RED; 
       } 
      }); 
      setBorder(null); 
      setForeground(Color.GRAY); 
      setText("Favourite"); 
      setFocusPainted(false); 
     } 
    } 
} 

Répondre

3

Il me semble que votre problème est avec votre « modèle »: Vous utilisez des objets DefaultMutableTreeNode vanille plaine pour vos nœuds, une classe qui ne peut pas enregistrer le plus important données - l'état de vos boutons.

plutôt envisager

  1. en utilisant une classe qui va de DefaultMutableTreeNode, qui a deux booléens, les valeurs qui seront utilisées par les équarrisseurs pour dire aux boutons quel état à afficher.
  2. Ou utilisez votre DefaultMutableTreeNode comme un "wrapper" en passant dans votre DefaultMutableTreeNode un objet qui contient du texte ainsi que deux champs booléens, les champs que les JToggleButtons utilisent pour afficher leur état.
+0

Merci pour la réponse, j'ai pris la première approche que vous avez énumérée afin de le faire fonctionner – Dan