我有窗口显示表中的日志事件。 例如,用户正在读取某行表格中的文本。当新日志到来时,它们会添加到表的开头,而用户正在读取的行向下移动。我需要在表的开头添加新行时阻止JScrollPane滚动。我尝试了不同的东西,但没有任何帮助。有人可以建议我如何实现这个? 提前谢谢!
答案 0 :(得分:1)
棘手的任务:-)移出是因为默认情况下滚动位置不以任何方式调整:在上面添加行只是保持垂直滚动位置,然后指向不同的行,如前所述
需要什么:
这很棘手,因为我们需要听取模型的变化。该侦听器是由表在内部注册的modelListener的邻居,该表在更改时自行更新。因此,我们需要确保在内部更改完成后行动,同时在内部更新之前使用信息。
一个肮脏的解决方案 - 取决于最后添加的第一次通知的摇摆侦听器通知的常规顺序(当心:生产代码中的 DONT !在更改LAF时它会轻易破坏,fi ) - 是在收到通知后收集前状态并调整包含在invokeLater中的滚动位置:
final DefaultTableModel model = new DefaultTableModel(20, 2);
for (int i = 0; i < model.getRowCount(); i++) {
model.setValueAt(i, i, 0);
}
final JTable table = new JTable(model);
Action action = new AbstractAction("add row at 0") {
@Override
public void actionPerformed(ActionEvent e) {
model.insertRow(0, new Object[] {});
}
};
JXFrame frame = wrapWithScrollingInFrame(table, "modify scroll");
TableModelListener l = new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (!TableUtilities.isInsert(e)) return;
final Rectangle r = table.getVisibleRect();
final int lastRow = table.rowAtPoint(
new Point(0, r.y + r.height - 5));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// assuming
// a) the insert was exactly 1 row
// b) was _before_ the old last row in view-coordinates
Rectangle cell = table.getCellRect(lastRow + 1, 0, true);
cell.translate(0, -r.height + cell.height);
cell.height = r.height;
table.scrollRectToVisible(cell);
}
});
}
};
model.addTableModelListener(l);
适当地获取前状态的方式取决于您的确切背景。您可以在表的生命周期内跟踪第一行/最后一行,在(一个或所有)
中更新它们