Java - 如何防止单击第二个单元格时 JTable 中的水平自动滚动?
Java - How to prevent the horizontal auto-scrolling in a JTable when clicking the 2nd cell?
我有一个包含 2 列的 JTable。第二列的某些单元格中有长项,因此我使用水平滚动条,以便用户可以手动滚动它以查看那些长单元格中写的内容。
以下是 JTable 在单击其任何行之前的外观:
问题是,当我左键单击第二列中的任何单元格以突出显示该行时,table 会自动水平滚动,如下所示:
有没有办法防止这种自动滚动,但同时保持手动用户滚动(以防用户想水平滚动以查看单元格内的内容)?
也许您可以使用 Fixed Column Table 中的方法。
它允许您为滚动窗格创建一个"row header"。 header 行永远不会滚动,因此第一列将始终可见。但是,您仍然可以滚动浏览剩余的列。
您可以@Override
table 的scrollRectToVisible
方法。作为第一步,我会使用一个空的实现。当您确切地弄清楚什么时候需要 auto-scrolling 什么时候不需要时,相应地实施该方法。
如果你想完全禁用自动滚动,你可以使用
table.setAutoscroll(false)
但实际上,这不是很有用,因为键盘导航正在关闭。如果单元格完全隐藏在视图之外,我建议您仍然自动滚动。为此,我禁用了自动滚动并重写了 changeSelection
来处理隐藏单元格时的滚动。
public static class TestTable extends JTable {
static final int THRESHOLD = 10;
static String[] columns = {"name", "description", "other"};
static String[][] data = {
{"name1", "some description 1", "other value we don't care about"},
{"name2", "some description 2", "other value we don't care about"},
{"name3", "some description 3", "other value we don't care about"}
};
public TestTable() {
super(data, columns);
setAutoResizeMode(AUTO_RESIZE_OFF);
setAutoscrolls(false);
getColumnModel().getColumn(0).setPreferredWidth(300);
getColumnModel().getColumn(1).setPreferredWidth(300);
getColumnModel().getColumn(2).setPreferredWidth(300);
}
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
scrollColumnToVisible(rowIndex, columnIndex);
}
private void scrollColumnToVisible(int rowIndex, int columnIndex) {
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
int leftX = cellRect.x;
int rightX = cellRect.x + cellRect.width;
//assuming we're in scroll pane
int width = Math.min(getWidth(), getParent().getWidth());
int scrolledX = -getX();
int visibleLeft = scrolledX;
int visibleRight = visibleLeft + width;
//bonus, scroll if only a little of a column is visible
visibleLeft += THRESHOLD;
visibleRight -= THRESHOLD;
boolean isCellVisible = leftX < visibleRight // otherwise cell is hidden on the right
&& rightX > visibleLeft // otherwise cell is hidden on the left
;
if (!isCellVisible) {
scrollRectToVisible(cellRect);
}
}
}
作为奖励,我添加了 THRESHOLD 来考虑隐藏单元格,而实际上只有一小部分是可见的:)完整代码是 here.
JTable 的自动滚动行为在 changeSelection() 中实现。因此,防止水平自动滚动的最简单方法是始终将其绑定到第 0 列:
table = new JTable(new MyTableModel()) {
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
super.changeSelection(rowIndex, 0, toggle, extend);
}
};
如果你想禁用水平自动滚动,试试这个。
public class MyTable extends JTable {
@Override
public void scrollRectToVisible(Rectangle aRect) {
aRect.x = 0;
super.scrollRectToVisible(aRect);
}
}
我有一个包含 2 列的 JTable。第二列的某些单元格中有长项,因此我使用水平滚动条,以便用户可以手动滚动它以查看那些长单元格中写的内容。
以下是 JTable 在单击其任何行之前的外观:
问题是,当我左键单击第二列中的任何单元格以突出显示该行时,table 会自动水平滚动,如下所示:
有没有办法防止这种自动滚动,但同时保持手动用户滚动(以防用户想水平滚动以查看单元格内的内容)?
也许您可以使用 Fixed Column Table 中的方法。
它允许您为滚动窗格创建一个"row header"。 header 行永远不会滚动,因此第一列将始终可见。但是,您仍然可以滚动浏览剩余的列。
您可以@Override
table 的scrollRectToVisible
方法。作为第一步,我会使用一个空的实现。当您确切地弄清楚什么时候需要 auto-scrolling 什么时候不需要时,相应地实施该方法。
如果你想完全禁用自动滚动,你可以使用
table.setAutoscroll(false)
但实际上,这不是很有用,因为键盘导航正在关闭。如果单元格完全隐藏在视图之外,我建议您仍然自动滚动。为此,我禁用了自动滚动并重写了 changeSelection
来处理隐藏单元格时的滚动。
public static class TestTable extends JTable {
static final int THRESHOLD = 10;
static String[] columns = {"name", "description", "other"};
static String[][] data = {
{"name1", "some description 1", "other value we don't care about"},
{"name2", "some description 2", "other value we don't care about"},
{"name3", "some description 3", "other value we don't care about"}
};
public TestTable() {
super(data, columns);
setAutoResizeMode(AUTO_RESIZE_OFF);
setAutoscrolls(false);
getColumnModel().getColumn(0).setPreferredWidth(300);
getColumnModel().getColumn(1).setPreferredWidth(300);
getColumnModel().getColumn(2).setPreferredWidth(300);
}
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
scrollColumnToVisible(rowIndex, columnIndex);
}
private void scrollColumnToVisible(int rowIndex, int columnIndex) {
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
int leftX = cellRect.x;
int rightX = cellRect.x + cellRect.width;
//assuming we're in scroll pane
int width = Math.min(getWidth(), getParent().getWidth());
int scrolledX = -getX();
int visibleLeft = scrolledX;
int visibleRight = visibleLeft + width;
//bonus, scroll if only a little of a column is visible
visibleLeft += THRESHOLD;
visibleRight -= THRESHOLD;
boolean isCellVisible = leftX < visibleRight // otherwise cell is hidden on the right
&& rightX > visibleLeft // otherwise cell is hidden on the left
;
if (!isCellVisible) {
scrollRectToVisible(cellRect);
}
}
}
作为奖励,我添加了 THRESHOLD 来考虑隐藏单元格,而实际上只有一小部分是可见的:)完整代码是 here.
JTable 的自动滚动行为在 changeSelection() 中实现。因此,防止水平自动滚动的最简单方法是始终将其绑定到第 0 列:
table = new JTable(new MyTableModel()) {
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
super.changeSelection(rowIndex, 0, toggle, extend);
}
};
如果你想禁用水平自动滚动,试试这个。
public class MyTable extends JTable {
@Override
public void scrollRectToVisible(Rectangle aRect) {
aRect.x = 0;
super.scrollRectToVisible(aRect);
}
}