Search code examples
javaswinguser-interfacelistenerjscrollpane

How to bind different listener to different ScrollPane


I have a class that defines a graphical interface with two JList. For each JList I would like to associate a method public void valueChanged(ListSelectionEvent s) but I can't do it (obviously). So how can I fix it?

This is my code:

public class Inbox implements ListSelectionListener {

    public static void main(String[] args) {
        Inbox inbox = new Inbox();
    }

    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    JPanel titlePanel = new JPanel();
    JPanel centerPanel = new JPanel();
    JPanel listPanel = new JPanel();
    JPanel listRicPanel = new JPanel();
    JPanel listInvPanel = new JPanel();
    JPanel messPanel = new JPanel();
    JPanel buttonPanel = new JPanel();

    GridBagConstraints c;
    JButton indietro = new JButton("Indietro");
    JButton ok = new JButton("Ok");

    String ricevuti[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
    JList ricList = new JList(ricevuti);

    String inviati[] = {"A", "B", "C", "D", "E"};
    JList invList = new JList(inviati);

    Inbox() {
        frame.setTitle("Inbox"); //nome della finestra (frame)
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
       frame.setVisible(true);

        panel.setLayout(new BorderLayout());
        centerPanel.setLayout(new BorderLayout());
        listPanel.setLayout(new GridLayout(2, 0));

        panel.add(titlePanel, BorderLayout.NORTH);
        panel.add(buttonPanel, BorderLayout.SOUTH);
        panel.add(centerPanel, BorderLayout.CENTER);
        buttonPanel.add(indietro);
        buttonPanel.add(ok);

        centerPanel.add(listPanel, BorderLayout.WEST);
        centerPanel.add(messPanel, BorderLayout.CENTER);

        listPanel.add(listRicPanel);
        listPanel.add(listInvPanel);

        /** ScrollPane containing the first list **/
        ricList.setVisibleRowCount(10);
        ricList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listRicPanel.add(new JScrollPane(ricList));
        ricList.addListSelectionListener(this);

        /** ScrollPane containing the second list **/
        invList.setVisibleRowCount(10);
        invList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listInvPanel.add(new JScrollPane(invList));
        invList.addListSelectionListener(this);


        frame.pack();

    }


    /**
     * First listener.
     */
    public void valueChanged(ListSelectionEvent e) {
        String str = (String) ricList.getSelectedValue();
        if(str.equals("Alex"))
            System.out.println("Alex");
        else if(str.equals("John"))
            System.out.println("John");
        else
            System.out.println("Other name");
    }

    /**
     * Second listener.
     */
    public void valueChanged(ListSelectionEvent e) {
        String str = (String) invList.getSelectedValue();
        if(str.equals("Alex"))
            System.out.println("Alex");
        else if(str.equals("John"))
            System.out.println("John");
        else
            System.out.println("Other name");
    }

}

I wish the program would combine different listeners to different scroolPane, as I do that?

Thank you very much!


Solution

  • You Could

    Determine the source of the event and branch your logic based on the result...

    public void valueChanged(ListSelectionEvent e) {
        if (e.getSource() == ricList) {
            //...
        else if (e.getSource() == invList) {
            //...
        }
    }
    

    This assumes that you want to perform different logic for each source. This can become a little cumbersome if you have more than a few possible sources...

    Instead of "implementing" ListSelectionListener at the class level...

    You Could...

    Define a completely external class that does the specific job you want...

    public class MyListSelectionListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent s) {
            // Custom job here...
        }
    }
    

    This can be a good and bad thing depending on your needs...One problem with this is you may be required to provide additional context to the class in order for it to perform it's operations, as the event object may not provide enough context alone

    You Could

    Create inner classes that do a specific job, in particular for the class they've been defined within...

    public class Inbox {
        //...
        Inbox() {
            //...
            ricList.addListSelectionListener(new RicListSelectionListener());
            //...
            invList.addListSelectionListener(new InvListSelectionListener());
        }
        //...
        public class RicListSelectionListener implements ListSelectionListener {
            public void valueChanged(ListSelectionEvent s) {
                String str = (String) ricList.getSelectedValue();
                if(str.equals("Alex"))
                    System.out.println("Alex");
                else if(str.equals("John"))
                    System.out.println("John");
                else
                    System.out.println("Other name");            
            } 
        }
    
        public class InvListSelectionListener implements ListSelectionListener {
            public void valueChanged(ListSelectionEvent s) {
                String str = (String) invList.getSelectedValue();
                if(str.equals("Alex"))
                    System.out.println("Alex");
                else if(str.equals("John"))
                    System.out.println("John");
                else
                    System.out.println("Other name");            
            } 
        }
    }
    

    The nice thing about this is the classes have access to all the instance variables and methods within the parent class and are neat and tidy and easy to find when you need...

    Take a look at Inner Class Example for more details

    You Could...

    Use anonymous classes. These are a little like inner classes, except they are defined in line...

    public class Inbox {
        //...
        Inbox() {
            //...
            ricList.addListSelectionListener(new ListSelectionListener {
                public void valueChanged(ListSelectionEvent s) {
                    String str = (String) ricList.getSelectedValue();
                    if(str.equals("Alex"))
                        System.out.println("Alex");
                    else if(str.equals("John"))
                        System.out.println("John");
                    else
                        System.out.println("Other name");            
                } 
            });
            //...
            invList.addListSelectionListener(new ListSelectionListener() {
                public void valueChanged(ListSelectionEvent s) {
                    String str = (String) invList.getSelectedValue();
                    if(str.equals("Alex"))
                        System.out.println("Alex");
                    else if(str.equals("John"))
                        System.out.println("John");
                    else
                        System.out.println("Other name");            
                } 
            });
        }
    }
    

    These can clutter the code if they are too long and should be used sparingly for that reason, but are really good for plumbing together existing functionality.

    Take a look at Anonymous Classes for more details