Question

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!

Was it helpful?

Solution 2

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

OTHER TIPS

It must be one method but you can use e.getSource() method to get JList instance which fires the event. Then you can use it like this

public void valueChanged(ListSelectionEvent e) {
    String str = (String) ((JList)e.getSource()).getSelectedValue();
    if(str.equals("Alex"))
        System.out.println("Alex");
    else if(str.equals("John"))
        System.out.println("John");
    else
        System.out.println("Other name");
}

Of course the listener must be added to both list instances

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top