JTable自动滚动方法是一行太高

时间:2013-08-21 00:16:45

标签: java swing jtable jscrollpane

以下是我一直使用的示例表:

JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane);

table = new JTable();
DefaultTableModel tableModel = new DefaultTableModel(new Object[]{"Row 1","Row 2"},0);
table.setModel(tableModel);
scrollPane.setViewportView(table);

我尝试使用以下自动滚动方法,结果相同。

// Method 1
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());

// Method 2
table.scrollRectToVisible(table.getCellRect(table.getRowCount(), 0, true));

两个示例都转到表格的近底部,直到用户必须向下滚动才能看到的最后一个(底部)行,只有在添加另一行时再次发生。


编辑:复制问题的示例代码

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

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;

public class ScrollTableEx extends JFrame {

    private static final long serialVersionUID = 1L;
    public int i = 100;
    public JScrollPane scrollPane;
    public JPanel contentPane;
    public JTable table;
    public JButton add;
    public DefaultTableModel model = new DefaultTableModel(new Object[] { "Int (+)", "Int (-)" }, 0);

    public static void main(String[] args) {
        ScrollTableEx frame = new ScrollTableEx();
        frame.setVisible(true);
    }

    public ScrollTableEx() {
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        setSize(500,400);

        scrollPane = new JScrollPane();

        table = new JTable();
        table.setCellSelectionEnabled(true);
        table.setModel(model);
        scrollPane.setViewportView(table);

        for (int i = 0; i < 100; i++) {
            model.addRow(new Object[] { i, i * -1 });
            Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
            table.scrollRectToVisible(goodRect);
        }

        JButton add = new JButton("Add");
        add.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
                table.scrollRectToVisible(goodRect);
                model.addRow(new Object[] { i, i * -1 });
                i++;
            }
        });

        add(add, BorderLayout.NORTH);
        add(scrollPane, BorderLayout.CENTER);
    }
}

1 个答案:

答案 0 :(得分:4)

问题是,JTableTableModel都被0编入索引。也就是说,最后一个值实际上是rowCount - 1

因此,当您使用table.getCellRect(table.getRowCount(), 0, true)时,它实际上会返回Rectangle的正确位置,只有0高度,因为该行实际上并不存在。

相反,您想要使用table.getCellRect(table.getRowCount() - 1, 0, true)

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class ScrollTable {

    public static void main(String[] args) {
        new ScrollTable();
    }

    public ScrollTable() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                final DefaultTableModel model = new DefaultTableModel(new Object[]{"Test"}, 0);
                for (int index = 0; index < 100; index++) {
                    model.addRow(new Object[]{index});
                }

                final JTable table = new JTable(model);

                JButton add = new JButton("Add");
                add.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        model.addRow(new Object[]{model.getRowCount()});
                        Rectangle badRect = table.getCellRect(model.getRowCount(), 0, true);
                        Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);

                        System.out.println("bad = " + badRect);
                        System.out.println("goodRect = " + goodRect);

                        table.scrollRectToVisible(goodRect);
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.add(add, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

我会尽可能避免使用.setBounds。它没有考虑到不同计算机和操作系统之间存在的各种差异,虽然它在开发时可能看起来非常好,但当你将它移动到另一个系统时,它可能会产生不可测量的结果 - 恕我直言