Search code examples
javaswinglistenerjform-designer

How to implement ListSelectionListener with JFormDesigner?


I'm trying to get a button to enable/disable itself depending on whether a JTable has any rows selected.

So I believe I need the button to be a ListSelectionListener, listening the JTable's SelectionModel, as described in this Oracle tutorial.

How should I do this with JFormDesigner 5?

Seems like I should be adding the following code to my JButton, but I don't know how to do so in JFormDesigner.

// Implementing this method to be a ListSelectionListener.
public void valueChanged(ListSelectionEvent e) {
    ListSelectionModel lsm = (ListSelectionModel)e.getSource();
    boolean anyRowsSelected = !(lsm.isSelectionEmpty());
    this.setEnabled( anyRowsSelected );
}

In my experience with JFormDesigner adding an actionPerformed handler, JFormDesigner created a method on the JFrame. But my understanding of Swing & OOP says the code for a ListSelectionListener should be inside the listening widget itself (the JButton in my case).

I'm using: JFormDesigner 5.0.0.1, IntelliJ 10.5, Java 1.6.0_24, Mac OS X 10.6.7.

--------SOLVED-----------

Thanks to "Hovercraft Full Of Eels" for answering my question.

Solution: I will add code to my JFrame to create a ListSelectionListener. That gets the job done without interfering with the JFormDesigner tool.

I enhanced example code given by "Hovercraft Full Of Eels", to make it more interactive. I added an ActionListener to the button to clear the user's selection. Now the user can see the button toggle between enabled and disabled.

My version shows a subtle bug: the selected cell turns black when the table's selection is cleared. I don't why. But that is out of scope for this StackOverflow question. Regardless of that bug, this code is a good demo for this question.

import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class TableAndButton extends JPanel {
   private static final String[] COLUMN_NAMES = {"Mon", "Tues", "Wed", "Thurs", "Fri"};
   private JButton button = new JButton("Clear user's selection");
   private DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 10);
   private JTable table = new JTable(model);

   public TableAndButton() {
      JPanel btnPanel = new JPanel();
      btnPanel.add(button);

      table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
            ListSelectionModel lsm = (ListSelectionModel)e.getSource();
            boolean anyRowSelected = !(lsm.isSelectionEmpty());
            button.setEnabled(anyRowSelected);
         }
      });

      button.addActionListener( new ActionListener() {
          public void actionPerformed(ActionEvent e) {
             table.getSelectionModel().clearSelection();
         }
      });

      button.setEnabled(false);

      setLayout(new BorderLayout());
      add(new JScrollPane(table), BorderLayout.CENTER);
      add(btnPanel, BorderLayout.PAGE_END);
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("TableAndButton");
      frame.getContentPane().add(new TableAndButton());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

Solution

  • No, the JButton itself shouldn't be a ListSelectionListener, but rather the JTable needs a separate ListSelectionListener added to it that enables/disables the JButton. Don't think about it as if the button is listening to the JTable because it isn't. Instead a separate entity is doing the listening and changes the state of the program depending on whether or not a row is selected.

    e.g.,

    import java.awt.BorderLayout;
    import javax.swing.*;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;
    import javax.swing.table.DefaultTableModel;
    
    public class TableAndButton extends JPanel {
       private static final String[] COLUMN_NAMES = {"Mon", "Tues", "Wed", "Thurs", "Fri"};
       private JButton button = new JButton("Button");
       private DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 10);
       private JTable table = new JTable(model);
    
       public TableAndButton() {
          JPanel btnPanel = new JPanel();
          btnPanel.add(button);
    
          table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
             public void valueChanged(ListSelectionEvent e) {
                ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                boolean anyRowSelected = !(lsm.isSelectionEmpty());
                button.setEnabled(anyRowSelected);
             }
          });
    
          button.setEnabled(false);
    
          setLayout(new BorderLayout());
          add(new JScrollPane(table), BorderLayout.CENTER);
          add(btnPanel, BorderLayout.PAGE_END);
       }
    
       private static void createAndShowUI() {
          JFrame frame = new JFrame("TableAndButton");
          frame.getContentPane().add(new TableAndButton());
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }