简体   繁体   中英

Displaying a row selector (cursor / pointer) in a JTable

["

I'm migrating an MS-Access app to Java.<\/i>

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

/*
 *    Use a JTable as a renderer for row numbers of a given main table.
 *  This table must be added to the row header of the scrollpane that
 *  contains the main table.
 */
public class RowNumberTable extends JTable
    implements ChangeListener, PropertyChangeListener, TableModelListener
{
    private JTable main;

    public static void main(String[] args) {
        JTable mainTable = new JTable(new MyTableModel());
        mainTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane scrollPane = new JScrollPane(mainTable);
        RowNumberTable rowTable = new RowNumberTable(mainTable);
        rowTable.getSelectionModel()
            .addListSelectionListener(rowTable.new RowListener());
        scrollPane.setRowHeaderView(rowTable);
        scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowTable.getTableHeader());

        // Create a panel to hold all other components
        JPanel topPanel = new JPanel();
        topPanel.setLayout( new BorderLayout() );
        topPanel.add( scrollPane, BorderLayout.CENTER );

        // Set the frame characteristics
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle( "Selector" );
        frame.setBackground( Color.gray );
        frame.getContentPane().add( topPanel );
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public RowNumberTable(JTable table)
    {
        main = table;
        main.addPropertyChangeListener( this );
        main.getModel().addTableModelListener( this );

        setFocusable( false );
        setAutoCreateColumnsFromModel( false );
        setSelectionModel( main.getSelectionModel() );

        TableColumn column = new TableColumn();
        column.setHeaderValue(" ");
        addColumn( column );
        column.setCellRenderer(new RowNumberRenderer());

        getColumnModel().getColumn(0).setPreferredWidth(22);
        setPreferredScrollableViewportSize(getPreferredSize());
    }

    @Override
    public void addNotify()
    {
        super.addNotify();

        Component c = getParent();

        //  Keep scrolling of the row table in sync with the main table.

        if (c instanceof JViewport)
        {
            JViewport viewport = (JViewport)c;
            viewport.addChangeListener( this );
        }
    }

    /*
     *  Delegate method to main table
     */
    @Override
    public int getRowCount()
    {
        return main.getRowCount();
    }

    @Override
    public int getRowHeight(int row)
    {
        int rowHeight = main.getRowHeight(row);

        if (rowHeight != super.getRowHeight(row))
        {
            super.setRowHeight(row, rowHeight);
        }

        return rowHeight;
    }

    /*
     *  No model is being used for this table so just use the row number
     *  as the value of the cell.
     */
    @Override
    public Object getValueAt(int row, int column)
    {
        //return Integer.toString(row + 1);
        if (main.isRowSelected(row))
            return "\u25BA"; // Unicode Black Right-pointing Pointer
        else
            return " ";
    }

    /*
     *  Don't edit data in the main TableModel by mistake
     */
    @Override
    public boolean isCellEditable(int row, int column)
    {
        return false;
    }

    /*
     *  Do nothing since the table ignores the model
     */
    @Override
    public void setValueAt(Object value, int row, int column) {}

    //
    //  Implement the ChangeListener
    //
    public void stateChanged(ChangeEvent e)
    {
        //  Keep the scrolling of the row table in sync with main table

        JViewport viewport = (JViewport) e.getSource();
        JScrollPane scrollPane = (JScrollPane)viewport.getParent();
        scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
    }

    //
    //  Implement the PropertyChangeListener
    //
    public void propertyChange(PropertyChangeEvent e)
    {
        //  Keep the row table in sync with the main table

        if ("selectionModel".equals(e.getPropertyName()))
        {
            setSelectionModel( main.getSelectionModel() );
        }

        if ("rowHeight".equals(e.getPropertyName()))
        {
            repaint();
        }

        if ("model".equals(e.getPropertyName()))
        {
            main.getModel().addTableModelListener( this );
            revalidate();
        }
    }

    //
    //  Implement the TableModelListener
    //
    @Override
    public void tableChanged(TableModelEvent e)
    {
        revalidate();
    }

    /*
     *  Attempt to mimic the table header renderer
     */
    private static class RowNumberRenderer extends DefaultTableCellRenderer
    {
        public RowNumberRenderer()
        {
            setHorizontalAlignment(JLabel.CENTER);
        }

        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column)
        {
            if (table != null)
            {
                JTableHeader header = table.getTableHeader();

                if (header != null)
                {
                    setForeground(header.getForeground());
                    setBackground(header.getBackground());
                    setFont(header.getFont());
                }
            }

            setText((value == null) ? "" : value.toString());
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));

            return this;
        }
    }

    private class RowListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent event) {
            if (event.getValueIsAdjusting()) {
                return;
            }
            int row =  main.getSelectedRow();
            System.out.println("selected row : "  +
                main.getSelectionModel().getLeadSelectionIndex() + " - " +
                main.getModel().getValueAt(row, 0) ); 
        }
    }
}

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = {"First Name",
        "Last Name",
        "Sport",
        "# of Years",
        "Vegetarian"};
    private Object[][] data = {
        {"Kathy", "Smith",
            "Snowboarding", new Integer(5), new Boolean(false)},
        {"John", "Doe",
            "Rowing", new Integer(3), new Boolean(true)},
        {"Sue", "Black",
            "Knitting", new Integer(2), new Boolean(false)},
        {"Jane", "White",
            "Speed reading", new Integer(20), new Boolean(true)},
        {"Joe", "Brown",
            "Pool", new Integer(10), new Boolean(false)}
        };

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return data.length;
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }
}
["

You would need to add a "row header" to the scroll pane.<\/i>

@Override
public Object getValueAt(int row, int column)
{
    //return Integer.toString(row + 1);
    if (main.isRowSelected(row))
        return "\u25BA";
    else
        return " ";
}

I Used your RowNumberTable and found out that if you play around with the fonts and table sizes the rownumbertable buggs out (gets partially empty/invisible when scrolling).

My solution to that was:

@Override
public int getRowHeight(int row) {
    setRowHeight(main.getRowHeight(row));
    return main.getRowHeight(row);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM