2

How do I display the information of a JTable row when selected?

I'll briefly explain what I am trying to do and then post the SSCCE that I created in case any of my explanation is confusing.

I'm wanting to be able to click any row in a table and display that information on a panel. I'm not sure what I need to make use of to get the job done.

I'm thinking I'll need to use:

  • table.getSelectedRow()
  • MouseListener()
  • ListSelectionListener()

I haven't used Listeners before, so I only know of those from reading articles/documentation while researching what I need to do to complete the job.

I'm also slightly confused as to how to display the info on my JPanel. The panel is created in the main class where as the table is created in its own class.

I appreciate any help and advice.

Example source :

import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class SwingTesting {

    private final JFrame frame;
    private final TablePane tablePane;
    private final JSplitPane splitPane;
    private final JPanel infoPanel;

    public SwingTesting() {
        tablePane = new TablePane();
        infoPanel = new JPanel();
        frame = new JFrame();

        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tablePane, infoPanel);

        frame.add(splitPane);
        frame.pack();
        frame.setVisible(true);
    }


    class TablePane extends JPanel {

        private final JTable table;
        private final TableModel tableModel;
        private final ListSelectionModel listSelectionModel;

    public TablePane() {
        table = new JTable();
        tableModel = createTableModel();
        table.setModel(tableModel);
        table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        table.add(table.getTableHeader(), BorderLayout.PAGE_START);
        table.setFillsViewportHeight(true); 

        listSelectionModel = table.getSelectionModel();
        table.setSelectionModel(listSelectionModel);
        listSelectionModel.addListSelectionListener(new SharedListSelectionHandler());
        table.setSelectionModel(listSelectionModel);

        this.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridheight = 1;
    gbc.gridwidth = 3;
    gbc.insets = new Insets(5, 5, 5, 5);
    gbc.ipadx = 2;
    gbc.ipady = 2;
    gbc.weightx = 1;
    gbc.weighty = 1;
        this.add(new JScrollPane(table), gbc);
    }

    private TableModel createTableModel() {
        DefaultTableModel model = new DefaultTableModel(
            new Object[] {"Car", "Color", "Year"}, 0 
        ){
            @Override 
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        addTableData(model);
        return model;
    }

    private void addTableData(DefaultTableModel model) {
        model.addRow(new Object[] {"Nissan", "Black", "2007"});
        model.addRow(new Object[] {"Toyota", "Blue", "2012"});
        model.addRow(new Object[] {"Chevrolet", "Red", "2009"});
        model.addRow(new Object[] {"Scion", "Silver", "2005"});
        model.addRow(new Object[] {"Cadilac", "Grey", "2001"});
    }


    class SharedListSelectionHandler implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
            String contents = "";

            if(lsm.isSelectionEmpty()) {
                System.out.println("<none>");
            } else {
                int minIndex = lsm.getMinSelectionIndex();
                int maxIndex = lsm.getMaxSelectionIndex();
                for(int i = minIndex; i <= maxIndex; i++) {
                    if(lsm.isSelectedIndex(i)) {
                        for(int j = 0; j < table.getColumnCount(); j++) {
                            contents += table.getValueAt(i, j) + " ";
                        }
                    }
                }
                System.out.println(contents);
            }
        }

    }
}

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SwingTesting();
            }
        });
    }
}

This doesn't quite perform like I want it. It prints out double the information.

So instead of Chevrolet Red 2009 it prints out Chevrolet Red 2009 Chevrolet Red 2009. Ultimately I'm wanting to put the text in a JLabel and put it on the panel. Keeping in mind that the panel containing the JLabel is in a different class than the table.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
WilliamShatner
  • 926
  • 2
  • 12
  • 25
  • 1
    +1 for posting an SSCCE, nice and good question – mKorbel May 15 '12 at 18:22
  • *"Here is the SSCCE:"* An SSCCE would be one source file with imports. Demote `TablePane` to default access, add it to the end of the `SwingTesting` source and add imports & you'll have one SSCCE. Alternately, copy/paste the main into `TablePane` (add imports) and it will be an SSCCE. – Andrew Thompson May 15 '12 at 18:31
  • @AndrewThompson Ah, sorry I wasn't aware of that. I had split it up for two reasons. Readability and because the way I'd be doing it outside of the SSCCE is also split. If you'd like, I can add the imports and push it all into one source file. – WilliamShatner May 15 '12 at 18:39
  • I prefer to see SSCCEs (not surprising given I was the one that started the trend). OTOH don't make the mistake of thinking an SSCCE is 'compulsory'. Many questions are solved without them. I would ask though, that you don't apply the term 'SSCCE' to any old code example. It is ***very*** specific in its meaning. – Andrew Thompson May 15 '12 at 18:46
  • @AndrewThompson Understood, I'll keep that in mind. I started using SSCCE (or what I thought it to be) because I'm not always able to clarify in words what I'm wanting to do. So code helps. However, I'll be sure to make the proper adjustments you mentioned in the future ones. – WilliamShatner May 15 '12 at 18:55
  • @mKorbel I'm not sure where your answer went, but I was wanting to upvote it as it gave me advice on what to fix and gave me advice regarding ListSelectionListener. (will apply the upvote to one of your other answers) – WilliamShatner May 15 '12 at 20:05
  • @WilliamShatner your edit demonstrating wrong way – mKorbel May 15 '12 at 20:23
  • @WilliamShatner please see my (undeleted) answer here – mKorbel May 15 '12 at 20:31

3 Answers3

3
table.getModel().addTableModelListener(tableModelListener);

See TableModel.addTableModelListener(TableModelListener) for details.


Based on the SSCCE.

GUI with details on selection

import javax.swing.*;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class SwingTesting {

    private final JFrame frame;
    private final TablePane tablePane;
    private final JSplitPane splitPane;
    private final JPanel infoPanel;

    JTextField make = new JTextField(9);;
    JTextField color = new JTextField(7);;
    JTextField year = new JTextField(4);

    public SwingTesting() {
        tablePane = new TablePane();
        infoPanel = new JPanel(new FlowLayout(5));

        infoPanel.add(new JLabel("Make"));
        infoPanel.add(make);
        infoPanel.add(new JLabel("Color"));
        infoPanel.add(color);
        infoPanel.add(new JLabel("Year"));
        infoPanel.add(year);

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tablePane, infoPanel);

        frame.add(splitPane);
        frame.pack();
        frame.setVisible(true);
    }

    class TablePane extends JPanel {

        private final JTable table;
        private final TableModel tableModel;
        private final ListSelectionModel listSelectionModel;

    private void setFields(int index) {
        make.setText(table.getValueAt(index, 0).toString());
        color.setText(table.getValueAt(index, 1).toString());
        year.setText(table.getValueAt(index, 2).toString());
    }

    private void clearFields() {
        make.setText("");
        color.setText("");
        year.setText("");
    }

    public TablePane() {
        table = new JTable();
        tableModel = createTableModel();
        table.setModel(tableModel);
        table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        table.add(table.getTableHeader(), BorderLayout.PAGE_START);
        table.setFillsViewportHeight(true);

        listSelectionModel = table.getSelectionModel();
        table.setSelectionModel(listSelectionModel);
        listSelectionModel.addListSelectionListener(new SharedListSelectionHandler());
        table.setSelectionModel(listSelectionModel);

        this.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridheight = 1;
    gbc.gridwidth = 3;
    gbc.insets = new Insets(5, 5, 5, 5);
    gbc.ipadx = 2;
    gbc.ipady = 2;
    gbc.weightx = 1;
    gbc.weighty = 1;
        this.add(new JScrollPane(table), gbc);
    }

    private TableModel createTableModel() {
        DefaultTableModel model = new DefaultTableModel(
            new Object[] {"Car", "Color", "Year"}, 0
        ){
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        addTableData(model);
        return model;
    }

    private void addTableData(DefaultTableModel model) {
        model.addRow(new Object[] {"Nissan", "Black", "2007"});
        model.addRow(new Object[] {"Toyota", "Blue", "2012"});
        model.addRow(new Object[] {"Chevrolet", "Red", "2009"});
        model.addRow(new Object[] {"Scion", "Silver", "2005"});
        model.addRow(new Object[] {"Cadilac", "Grey", "2001"});
    }


    class SharedListSelectionHandler implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
            String contents = "";

            if(lsm.isSelectionEmpty()) {
                System.out.println("<none>");
            } else {
                int minIndex = lsm.getMinSelectionIndex();
                int maxIndex = lsm.getMaxSelectionIndex();
                if (minIndex==maxIndex) {
                    setFields(minIndex);
                } else {
                    clearFields();
                    for(int i = minIndex; i <= maxIndex; i++) {
                        if(lsm.isSelectedIndex(i)) {
                            for(int j = 0; j < table.getColumnCount(); j++) {
                                contents += table.getValueAt(i, j) + " ";
                            }
                        }
                    }
                    System.out.println(contents);
                }
            }
        }

    }
}

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SwingTesting();
            }
        });
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • I did not check the code, but from the question I would think a selection listener is needed, added to the `ListSelectionModel` of the `JTable` and not a model listener on the `TableModel` – Robin May 15 '12 at 18:47
  • @AndrewThompson Reading up on the `tableModelListener` as well. Thanks for the link. – WilliamShatner May 15 '12 at 18:52
  • @AndrewThompson After reading a bit into `TableModelListener` I saw that it only had a few methods to offer information. I updated my question with the route I took, can you offer advice as to whether I'm going in the wrong direction? – WilliamShatner May 15 '12 at 20:06
  • @AndrewThompson Added SSCCEE, at least as close to SSCCE as I understand :) (some of the indentation appears off though) – WilliamShatner May 16 '12 at 16:50
  • Yep. That is a (poorly indented) SSCCE all right. See the update to my answer. – Andrew Thompson May 16 '12 at 21:18
  • @AndrewThompson How would I call `setFields()` if the classes were separated? Would I need to create an instance of SwingTesting in TablePane? – WilliamShatner May 17 '12 at 16:04
  • Seems like the question *"How do I display the information of a jtable row when selected?"* is answered, no? Maybe time to ask another question or questions. – Andrew Thompson May 17 '12 at 23:14
2

I'd be use

  • table.getSelectedRow() could be safe until/without implemented RowSorter or RowFilter, otherwise you have to convertViewToModel

  • MouseListener for JToolTip

  • ListSelectionListener() is direct way how to do it, but

a) setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);

b) to test if row > -1, otherwise there any row(s) isn't selected

c) then there no reason thinking or reduce I would prefer to have double/multi click disabled.

  • frame.getContentPane().add(splitPane); not required using of ContentPane from Java5

  • new SwingTesting(); please to read Initial Thread

EDIT:

how to use ListSelectionListener here, here, or top of examples is here

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I've started working on the ListSelectionListener but will have to complete it tomorrow. Will post back tomorrow. Also, can you explain why I should avoid using the `mouseListener` the way I did? – WilliamShatner May 15 '12 at 20:59
  • because you have to convertMouseToPoint, this Point returns Row, Column from JTable, no reason why, as I mentioned I'd be use that for JToolTip, and again this is retuning the same row with effort as from implemented and the simple method in the ListSelectionListener – mKorbel May 15 '12 at 21:03
  • Is that more like what I should be doing? (in my newest edit) – WilliamShatner May 16 '12 at 16:50
  • @WilliamShatner very good, but I'd be testing `int > -1` rather than `lsm.isSelectionEmpty()` == my view, and diff betweens `SINGLE_INTERVAL_SELECTION` and `MULTIPLE_INTERVAL_SELECTION`, second option allowing non_continous selection by using `CRTL` + `Mouse` – mKorbel May 16 '12 at 17:19
  • Thank you very much for all the help. I didn't even think about non_continuous selection. I'm glad you offered all the advice you have. I've upvoted you here and on a few other answers that were helpful. – WilliamShatner May 17 '12 at 16:06
1

Well I think using a custom MouseListener is not as feasible as using a special ButtonColumn that can render JButton on a seperate column with each row, you just have to define a common ActionListener for the JButton.

More information can be found here: Table Button Column

Asif
  • 4,980
  • 8
  • 38
  • 53
  • While that is an interesting idea and perhaps worth looking into, I would like to avoid adding buttons to the GUI if possible. (I'm able removing a button that did this for me and hoping to replace it with a simple click.). Thanks for the info about a table button column, I'll look into it. I just don't think it's right for this project at the moment. – WilliamShatner May 15 '12 at 18:26
  • Why avoiding Buttons in a _GUI_ ?? also if you are on `JDK 7`, then you have a method `setContentAreaFilled(Boolean filled)`, pass a `false` in this method and your `JButton` will look like a _link_ rather than button. – Asif May 15 '12 at 18:31
  • I'm attempting to clean up a GUI that is cluttered with buttons. I'm currently on `JDK 6`, but may be updating to `JDK 7` in the near future. – WilliamShatner May 15 '12 at 18:40
  • I gave you what I know and use, now its all your choice.. All the best :) – Asif May 15 '12 at 18:43
  • Thank you for the suggestion :) it is appreciated. Rest assured I'll be back to upvote once I've tested out all the suggestions to see what works best for me! – WilliamShatner May 15 '12 at 18:44