jtable自动滚动式intellij控制台

fslejnso  于 2021-07-03  发布在  Java
关注(0)|答案(0)|浏览(340)

我想在最多50行的jtable中添加一个scroll to end(autoscroll)函数。autoscroll函数应该像intellij scroll to end一样工作。
最初有0行。在几毫秒(比如说100毫秒)内,一些项目(1-5个项目)被添加到表的末尾。如果表行数达到最大值(50),则在下一次插入之前将删除第一行。
当用户用鼠标拖动或滚轮滚动到最后时,选中滚动到最后复选框,功能将被启用。从那时起,滚动窗格应滚动到表的底部,如:

scrollRectToVisible(getCellRect(getRowCount() - 1, 0, true));

当用户通过拖动或鼠标滚轮更改滚动条位置而不是视口底部时,将取消选中“滚动到结尾”复选框,并禁用该功能。
如果未选中“滚动到结尾”复选框,则表格将对通过拖动或鼠标滚轮进行的滚动条移动做出React。但是视口应该显示相同的数据。
如果由于删除随后的第一行而无法在视口中显示相同的数据,则视口中可见的第一行数据将转到上一行。
这正是intellij控制台日志屏幕的行为。我写了scroll以结束启用功能(90%工作)。我不能写滚动结束禁用功能,我不知道保存当前视口如上所述。
谢谢你的帮助。

package org.example.table;

import com.bsbls.home.gui.test.GuiTester;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

public class MyTable extends JTable {

    JScrollPane scrollPane;
    boolean autoScroll;
    private Consumer<Boolean> scrollToEndListener;
    private Object lastValue;
    private ScheduledFuture<?> future;

    public MyTable(int max) {
        this.setFillsViewportHeight(true);
        this.setRowHeight(24);
        this.setModel(new MyTableModel(max));
        this.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                if (autoScroll) {
                    scrollToEnd();
                }
            }
        });

    }

    public MyTableModel getTableModel() {

        return (MyTableModel) getModel();
    }

    private void scrollToEnd() {
        scrollRectToVisible(getCellRect(getRowCount() - 1, 0, true));
    }

    public void setScrollToEnd(boolean autoScroll) {
        this.autoScroll = autoScroll;
        if (autoScroll) {
            scrollToEnd();
        }
        if (scrollToEndListener != null) {
            scrollToEndListener.accept(autoScroll);
        }
    }

    public void setScrollToEndListener(Consumer<Boolean> scrollToEndListener) {
        this.scrollToEndListener = scrollToEndListener;
    }

    public JScrollPane wrap() {
        if (scrollPane == null) {
            scrollPane = new JScrollPane(this);
            scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
            JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
            scrollBar.addAdjustmentListener(e -> {

                if (e.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum()) {
                    setScrollToEnd(true);
                } else {
                    setScrollToEnd(false);
                }

            });

            ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

            scrollPane.addMouseWheelListener(new MouseWheelListener() {
                @Override
                public void mouseWheelMoved(MouseWheelEvent e) {
                    if (future != null) {
                        future.cancel(false);
                    }
                    future = scheduler.schedule(() -> {
                        EventQueue.invokeLater(() -> {
                            System.out.println("Yes");
                            JViewport viewport = scrollPane.getViewport();
                            Point p = viewport.getViewPosition();
                            Dimension extentSize = viewport.getExtentSize();
                            //p.translate(extentSize.width, extentSize.height);
                            int rowIndex = rowAtPoint(p);
                            if (rowIndex >= 0) {
                                lastValue = getValueAt(rowIndex, 0);
                            }
                        });
                    }, 500, TimeUnit.MILLISECONDS);

                }
            });

            scrollBar.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    //System.out.println(e);
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    //System.out.println(e);
                    lastValue = null;
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    //System.out.println(e);
                    JViewport viewport = scrollPane.getViewport();
                    Point p = viewport.getViewPosition();
                    Dimension extentSize = viewport.getExtentSize();
                    //p.translate(extentSize.width, extentSize.height);
                    int rowIndex = rowAtPoint(p);
                    if (rowIndex >= 0) {
                        lastValue = getValueAt(rowIndex, 0);
                    }
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    //System.out.println(e);
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    //System.out.println(e);
                }

                @Override
                public void mouseWheelMoved(MouseWheelEvent e) {
                    //System.out.println(e);
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    // System.out.println(e);
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    //System.out.println(e);
                }
            });

            getTableModel().addTableModelListener(new TableModelListener() {
                @Override
                public void tableChanged(TableModelEvent e) {

                    if (lastValue != null && !autoScroll) {
                        int rowCount = getRowCount();
                        int newIndex = -1;
                        for (int i = 0; i < rowCount; i++) {
                            Object indexValue = getValueAt(i, 0);
                            if (indexValue == lastValue) {
                                newIndex = i;
                                break;
                            }
                        }

                        System.out.println(lastValue + " " + newIndex);
                        if (newIndex > 1) {
                            scrollRectToVisible(getCellRect(newIndex - 1, 0, true));
                        } else {
                            lastValue = null;
                        }

                    }

                }
            });

        }
        return scrollPane;
    }

    static int counter;

    public static void main(String[] args) {
        GuiTester.test(f -> {
            JPanel panel = new JPanel(new BorderLayout());
            MyTable table = new MyTable(50);

            MyTableModel model = table.getTableModel();

            Random random = new Random();
            Timer timer = new Timer(100, e -> {
                Data data = new Data();
                data.setName(++counter + "");
                data.setX(random.nextInt());
                data.setY(random.nextInt());
                data.setZ(random.nextInt());
                data.setFlag(random.nextBoolean());
                model.addRow(data.toObjectArray());
            });
            timer.start();

            DataPanel dataPanel = new DataPanel();
            table.getSelectionModel().addListSelectionListener(e -> {
                int index = e.getFirstIndex();
                if (index >= 0) {
                    Data data = (Data) table.getValueAt(index, 5);
                    dataPanel.setData(data);

                }

            });

            JCheckBox checkBox = new JCheckBox("Scroll To End");
            table.setScrollToEndListener(flag -> {
                checkBox.setSelected(flag);
            });

            checkBox.addItemListener(e -> {
                table.setScrollToEnd(checkBox.isSelected());
            });

            panel.add(checkBox, BorderLayout.NORTH);
            panel.add(table.wrap(), BorderLayout.CENTER);
            panel.add(dataPanel.getPanel(), BorderLayout.EAST);
            return panel;
        });
    }
}

表模型

package org.example.table;

import javax.swing.table.DefaultTableModel;

public class MyTableModel extends DefaultTableModel {

    private int max = -1;

    public MyTableModel() {
        this(-1);

    }

    public MyTableModel(int max) {
        super(new Object[]{
                "Name", "Flag", "X", "Y", "Z", "Data"
        }, 0);
        this.max = max;
    }

    @Override
    public void addRow(Object[] rowData) {
        if (getRowCount() == max) {
            super.removeRow(0);
        }
        super.addRow(rowData);
    }
}

虚拟数据

package org.example.table;

public class Data {

    private String name;
    private boolean flag;
    private int x;
    private int y;
    private int z;

    public Object[] toObjectArray() {
        Object[] array = new Object[6];
        array[0] = name;
        array[1] = flag;
        array[2] = x;
        array[3] = y;
        array[4] = z;
        array[5] = this;
        return array;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getZ() {
        return z;
    }

    public void setZ(int z) {
        this.z = z;
    }
}

datpanel是一个虚拟intellij窗体:

package org.example.table;

import javax.swing.*;

public class DataPanel {
    private JTextField fieldName;
    private JCheckBox flagCheckBox;
    private JTextField fieldX;
    private JTextField fieldY;
    private JTextField fieldZ;
    private JPanel panel;

    public JPanel getPanel() {
        return panel;
    }

    public void setData(Data data) {
        fieldName.setText(data.getName());
        fieldX.setText(data.getX() + "");
        fieldY.setText(data.getY() + "");
        fieldZ.setText(data.getZ() + " ");
        flagCheckBox.setSelected(data.isFlag());
    }
}

编辑:
我已经添加了鼠标和鼠标滚轮侦听器,并找到了第一个可见的行。并将滚动模式更改为simple或backingstore。

scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);

那样的话,我有更好的功能。我仍然对更好的方法持开放态度。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题