调整列大小时使 JTable 在 JScrollPane 中保持静止
Keep JTable Stationary in JScrollPane When Resizing Columns
我在 JScrollPane
里面有一个 JTable
。用户向右滚动。然后,我将用户正在查看的位置左侧的一列放大 x
像素。这会导致 table 向左滚动。如何调整 JScrollPane
、JScrollBar
或 JViewport
以保持 table 静止?换句话说,如何在屏幕上保持 table 的相同可见部分?
我尝试将水平 JScrollBar
的值调整 x
。我还尝试通过 x
调整 JViewport
的视图位置。问题是 table 最终向右滚动。
这是显示问题的代码,我没有尝试保持 table 静止。
package oracle.psr.ndr.guiclient.util.table;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public final class StableColumnResizing extends JFrame
{
private static final long serialVersionUID = 738732002168497075L;
private final TableColumnModel m_model;
private final JScrollBar m_bar;
private int m_colIndex;
public static void main(String args[])
{
SwingUtilities.invokeLater(StableColumnResizing::create);
}
private static void create()
{
StableColumnResizing frame;
Timer timer;
frame = new StableColumnResizing();
frame.setVisible(true);
SwingUtilities.invokeLater(frame::moveRight);
timer = new Timer(1000, frame::adjust);
timer.start();
}
private StableColumnResizing()
{
JScrollPane pane;
JTable table;
Object rowData[][], columnNames[];
columnNames = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
rowData = new Object[][]{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}};
table = new JTable(rowData, columnNames);
m_model = table.getColumnModel();
pane = new JScrollPane();
m_bar = pane.getHorizontalScrollBar();
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
pane.setViewportView(table);
add(pane, BorderLayout.CENTER);
setSize(1024, 768);
setLocationByPlatform(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void moveRight()
{
m_bar.setValue(m_bar.getMaximum() / 3);
}
private void adjust(@SuppressWarnings("unused") ActionEvent event)
{
TableColumn column;
int count;
count = m_model.getColumnCount();
if (m_colIndex >= count)
return;
column = m_model.getColumn(m_colIndex);
column.setPreferredWidth(200);
m_colIndex++;
}
}
应他人的要求,我创建了一些简单的代码来说明问题。使用这个简单的代码,创建解决方案变得很容易。
该解决方案添加了一个新方法 getX()
并向 adjust()
添加了更多代码。 getX()
在进行任何列大小更改之前计算列的最左侧位置。此值存储在局部变量 x
.
中
该解决方案还会在更改任何列大小之前捕获 JScrollBar.getValue()
。此值存储在局部变量 value
.
中
改变列大小后,再比较x
< value
。如果列的最左侧位置不在视图的左侧,则为真。如果为真,则将列宽的差异添加到 value
并调用 JScrollBar.setValue()
。因此,离开视图左侧的列将导致滚动条移动到足以使可见列保持在视图中。右边的列将被简单地调整。
小心TableColumn.getMaxWidth()
。设置列宽时,列宽将遵循这一点。处理 getMaxWidth()
的代码在下面,即使它对 UI 没有影响,因为原始 post 什么都不做,不调用 TableColumn.setMaxWidth()
.
private void adjust(@SuppressWarnings("unused") ActionEvent event)
{
TableColumn column;
int count, old, next, value, x, max;
count = m_model.getColumnCount();
if (m_colIndex >= count)
return;
x = getX(m_colIndex);
value = m_bar.getValue();
column = m_model.getColumn(m_colIndex);
old = column.getPreferredWidth();
max = column.getMaxWidth();
next = 200;
column.setPreferredWidth(next);
m_colIndex++;
if (x < value)
m_bar.setValue(value + Math.min(next, max) - old);
}
private int getX(int colIndex)
{
TableColumn column;
int result;
result = 0;
while (--colIndex >= 0)
{
column = m_model.getColumn(colIndex);
result += column.getPreferredWidth();
}
return(result);
}
我在 JScrollPane
里面有一个 JTable
。用户向右滚动。然后,我将用户正在查看的位置左侧的一列放大 x
像素。这会导致 table 向左滚动。如何调整 JScrollPane
、JScrollBar
或 JViewport
以保持 table 静止?换句话说,如何在屏幕上保持 table 的相同可见部分?
我尝试将水平 JScrollBar
的值调整 x
。我还尝试通过 x
调整 JViewport
的视图位置。问题是 table 最终向右滚动。
这是显示问题的代码,我没有尝试保持 table 静止。
package oracle.psr.ndr.guiclient.util.table;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public final class StableColumnResizing extends JFrame
{
private static final long serialVersionUID = 738732002168497075L;
private final TableColumnModel m_model;
private final JScrollBar m_bar;
private int m_colIndex;
public static void main(String args[])
{
SwingUtilities.invokeLater(StableColumnResizing::create);
}
private static void create()
{
StableColumnResizing frame;
Timer timer;
frame = new StableColumnResizing();
frame.setVisible(true);
SwingUtilities.invokeLater(frame::moveRight);
timer = new Timer(1000, frame::adjust);
timer.start();
}
private StableColumnResizing()
{
JScrollPane pane;
JTable table;
Object rowData[][], columnNames[];
columnNames = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
rowData = new Object[][]{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}};
table = new JTable(rowData, columnNames);
m_model = table.getColumnModel();
pane = new JScrollPane();
m_bar = pane.getHorizontalScrollBar();
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
pane.setViewportView(table);
add(pane, BorderLayout.CENTER);
setSize(1024, 768);
setLocationByPlatform(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void moveRight()
{
m_bar.setValue(m_bar.getMaximum() / 3);
}
private void adjust(@SuppressWarnings("unused") ActionEvent event)
{
TableColumn column;
int count;
count = m_model.getColumnCount();
if (m_colIndex >= count)
return;
column = m_model.getColumn(m_colIndex);
column.setPreferredWidth(200);
m_colIndex++;
}
}
应他人的要求,我创建了一些简单的代码来说明问题。使用这个简单的代码,创建解决方案变得很容易。
该解决方案添加了一个新方法 getX()
并向 adjust()
添加了更多代码。 getX()
在进行任何列大小更改之前计算列的最左侧位置。此值存储在局部变量 x
.
该解决方案还会在更改任何列大小之前捕获 JScrollBar.getValue()
。此值存储在局部变量 value
.
改变列大小后,再比较x
< value
。如果列的最左侧位置不在视图的左侧,则为真。如果为真,则将列宽的差异添加到 value
并调用 JScrollBar.setValue()
。因此,离开视图左侧的列将导致滚动条移动到足以使可见列保持在视图中。右边的列将被简单地调整。
小心TableColumn.getMaxWidth()
。设置列宽时,列宽将遵循这一点。处理 getMaxWidth()
的代码在下面,即使它对 UI 没有影响,因为原始 post 什么都不做,不调用 TableColumn.setMaxWidth()
.
private void adjust(@SuppressWarnings("unused") ActionEvent event)
{
TableColumn column;
int count, old, next, value, x, max;
count = m_model.getColumnCount();
if (m_colIndex >= count)
return;
x = getX(m_colIndex);
value = m_bar.getValue();
column = m_model.getColumn(m_colIndex);
old = column.getPreferredWidth();
max = column.getMaxWidth();
next = 200;
column.setPreferredWidth(next);
m_colIndex++;
if (x < value)
m_bar.setValue(value + Math.min(next, max) - old);
}
private int getX(int colIndex)
{
TableColumn column;
int result;
result = 0;
while (--colIndex >= 0)
{
column = m_model.getColumn(colIndex);
result += column.getPreferredWidth();
}
return(result);
}