gpt4 book ai didi

java - 如何卡住滚动 Pane 内的 JTable 行选择

转载 作者:行者123 更新时间:2023-11-29 07:14:55 24 4
gpt4 key购买 nike

我有一个经常更新的 JTable。它位于滚动 Pane 内。

有时我们会看到一条消息,我们想深入研究一下。不幸的是,由于更新的数量,消息将在我们完成查看之前滚出可见屏幕。

我希望能够在检查消息时卡住视口(viewport)/滚动,但仍允许表格模型使用新消息进行更新。

我可以使用这段代码让选定的行转到顶部:

        int firstSelectedRow = table.getSelectedRow();
Rectangle rowLocation = table.getCellRect(firstSelectedRow, 0, false);
scroll.getVerticalScrollBar().setValue(rowLocation.y);
freezeScrolling.setText("Resume Updates");

但这只会在按下按钮时发生,然后它会迅速滚开。

有没有办法告诉视口(viewport)/滚动 Pane 卡住所选内容并关闭它,以便滚动 Pane 按照您的预期进行更新?

最佳答案

好吧,这个很逗我,所以我花了一些时间来找到解决这个问题的方法。我找到了两个选项:

  1. 我更喜欢一个,因为我发现它更简单:阻止表模型的新条目并将它们存储在缓冲区中。每当我们解冻时,我们都会将缓冲区刷新到表模型。
  2. 第二个选项包括定位当前顶部可见行。如果用户滚动,我们会捕获最上面的可见行。随着模型的更新,我们在表中找到捕获的行并将视口(viewport)位置设置为该行。

这是一个说明这两种机制的 SSCCE(不要介意代码设计的愚蠢,我测试了一堆东西——扩展 JScrollPane 实际上不是一个好主意,它都可以在外部完成)。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

public class Tables {

private static class JScrollPaneExtension extends JScrollPane implements TableModelListener, AdjustmentListener {
private boolean frozen = false;
private Vector<String> rowData;
private final JTable table;
private final MyTableModel tableModel;

private JScrollPaneExtension(JTable table, MyTableModel tableModel) {
super(table);
this.table = table;
this.tableModel = tableModel;
tableModel.addTableModelListener(this);
getVerticalScrollBar().addAdjustmentListener(this);
}

public boolean isFrozen() {
return frozen;
}

public void setFrozen(boolean frozen) {
if (frozen != this.frozen) {
this.frozen = frozen;
if (frozen) {
captureCurrentTopRowData();
} else {
rowData = null;
}
}
}

private void captureCurrentTopRowData() {
int row = table.rowAtPoint(getViewport().getViewPosition());
if (row > -1) {
rowData = (Vector<String>) tableModel.getDataVector().get(row);
}
}

@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
if (frozen) {
captureCurrentTopRowData();
scrollToRowData();
}
}

@Override
public void tableChanged(TableModelEvent e) {
scrollToRowData();
}

private void scrollToRowData() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (frozen) {
int index = tableModel.getDataVector().indexOf(rowData);
getViewport().setViewPosition(table.getCellRect(index, 0, true).getLocation());
}
}
});
}

}

public static class MyTableModel extends DefaultTableModel {
private int count;

private boolean frozen = false;

private List<Vector<String>> buffer = new ArrayList<Vector<String>>();

public MyTableModel() {
addColumn("Test");
}

public void insertNewRow() {
Vector<String> rowData = createNewRowData();
if (isFrozen()) {
buffer.add(rowData);
} else {
insertRow(0, rowData);
}
}

private Vector<String> createNewRowData() {
Vector<String> data = new Vector<String>(1);
data.add("Hello-" + (count++));
return data;
}

public boolean isFrozen() {
return frozen;
}

public void setFrozen(boolean frozen) {
if (frozen == this.frozen) {
return;
}
this.frozen = frozen;
if (!frozen) {
flushBuffer();
}
}

private void flushBuffer() {
for (Vector<String> rowData : buffer) {
insertRow(0, rowData);
}
}
}

public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

final MyTableModel model = new MyTableModel();
JTable table = new JTable(model);
final JScrollPaneExtension scroll = new JScrollPaneExtension(table, model);
JPanel panel = new JPanel();
final JButton freeze = new JButton("Freeze");
freeze.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
if (model.isFrozen()) {
freeze.setText("Freeze model");
} else {
freeze.setText("Continue");
}
model.setFrozen(!model.isFrozen());
}
});
final JButton freeze2 = new JButton("Freeze scroll");
freeze2.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
if (scroll.isFrozen()) {
freeze2.setText("Freeze scroll");
} else {
freeze2.setText("Resume scroll");
}
scroll.setFrozen(!scroll.isFrozen());
}
});
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.add(scroll);
panel.add(freeze);
panel.add(freeze2);
frame.getContentPane().add(panel, BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {

@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
model.insertNewRow();
}
});
}
}, new Date(), 300);
}
}

关于java - 如何卡住滚动 Pane 内的 JTable 行选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10451008/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com