Java Swing scrollpane在滚动超过某一点时发出通知

Java Swing scrollpane在滚动超过某一点时发出通知,java,swing,pagination,swingworker,Java,Swing,Pagination,Swingworker,伙计们。我需要关于如何最好地实施某事的建议。我的节目: 我有一个swing程序,它读取一个包含多条不同类型记录的文件。我将这些记录读入java对象,用它们的标题和内容制作JTable(因此每个表只有标题和1条记录),将这些表添加到面板,并将面板添加到滚动窗格。有很多记录,大约70000条,所以我不能一次把所有的东西都载入内存 我的计划是通过一次只显示100条记录来分页显示,如果滚动到某个点,比如说表格NR50,它将加载接下来的100个表格并将它们添加到滚动窗格中 这就引出了我的问题 1) 我不知

伙计们。我需要关于如何最好地实施某事的建议。我的节目:

我有一个swing程序,它读取一个包含多条不同类型记录的文件。我将这些记录读入java对象,用它们的标题和内容制作JTable(因此每个表只有标题和1条记录),将这些表添加到面板,并将面板添加到滚动窗格。有很多记录,大约70000条,所以我不能一次把所有的东西都载入内存

我的计划是通过一次只显示100条记录来分页显示,如果滚动到某个点,比如说表格NR50,它将加载接下来的100个表格并将它们添加到滚动窗格中

这就引出了我的问题

1) 我不知道如何通知自己我已经滚动到某个点了。因此,假设我有100个JTables连接到一个JPanel,并连接到一个滚动窗格。我如何添加一个监听器来通知用户何时滚动到Jtable 50以获取参数

2) 我遇到的另一个问题与我如何将表格放入面板有关。我使用的swingworker如下所示:

private class TableRun extends SwingWorker<Void, JTable> {

        private ArrayDeque<FileRecord> fileRecords;
        private final GridBagConstraints gc;
        private final JPanel parentPanel;
        int counter = 1;

        TableRun(ArrayDeque<FileRecord> fileRecords, GridBagConstraints gc, JPanel parentPanel) {
            this.fileRecords = fileRecords;
            this.gc = gc;
            this.parentPanel = parentPanel;
        }

        @Override
        protected Void doInBackground() {
            Iterator<FileRecord> iterator = fileRecords.iterator();
            while (iterator.hasNext()) {
                publish(getTabel(iterator.next()));
            }

            return null;
        }

        @Override
        protected void process(final List<JTable> tables) {
                    Iterator<JTable> iterator = tables.iterator();
                    while(iterator.hasNext()) {
                        JTable table = iterator.next();
                        gc.fill = 1;
                        parentPanel.add(table.getTableHeader(), gc);
                        gc.gridy++;
                        parentPanel.add(table,gc);
                        gc.gridy++;

                        //validate takes a long time so i try to not do it too often.
                        if(counter == 50 || (counter % 5000) ==0 || (counter == fileRecords.size())) {
                            validate();
                        }
                        System.out.println("Sequence Nr : " + table.getModel().getValueAt(0,1) + " - Counter :" + counter++);
                    }
        }
    }
私有类TableRun扩展SwingWorker{
私人ArrayDeque文件记录;
私人终审法院;
私人最终JPanel家长小组;
int计数器=1;
TableRun(ArrayQue文件记录、GridBagConstraints gc、JPanel parentPanel){
this.fileRecords=fileRecords;
this.gc=gc;
this.parentPanel=parentPanel;
}
@凌驾
受保护的Void doInBackground(){
迭代器迭代器=fileRecords.Iterator();
while(iterator.hasNext()){
发布(getTabel(iterator.next());
}
返回null;
}
@凌驾
受保护的作废流程(最终列表表){
迭代器迭代器=tables.Iterator();
while(iterator.hasNext()){
JTable table=iterator.next();
gc.fill=1;
parentPanel.add(table.getTableHeader(),gc);
gc.gridy++;
parentPanel.add(表,gc);
gc.gridy++;
//验证需要很长时间,所以我尽量不太频繁地进行验证。
如果(计数器==50 | |(计数器%5000)==0 | |(计数器==fileRecords.size()){
验证();
}
System.out.println(“序列号:“+table.getModel().getValueAt(0,1)+”-计数器:“+Counter++”);
}
}
}
我将记录对象馈送给swingworker。然后,它将记录转换为具有所有必要格式的JTable,然后将它们添加到面板中。它有时调用validate来显示表,否则就不显示它们。(不确定是否有更好的方法进行此操作?)

所以我的问题与滚动有关。如果我最初只将70000条记录中的100条提供给我的swinworker,它显然会创建一个滚动窗格,认为只有100条记录。所以滚动条不是很小(很明显你不能滚动很远)。我真正想要的是,尽管我只显示100条记录,但我希望滚动窗格的大小是70000条记录的大小,以便您可以根据滚动条查看记录的大小。如果将滚动条拖动到底部的某个点,则需要将这些记录拉出来并显示出来。如何创建滚动窗格的大小大于其中的实际组件,但基于它们的大小

希望我的问题有意义

谢谢

我如何添加一个监听器来通知用户何时滚动过页面 为了便于讨论,Jtable 50

例如(一种可能的方法,您可以测试),(向我道歉)其他问题不可回答,请注意,您必须将鼠标事件(鼠标滚轮)从父对象(JScrollPane包含JPanel)重新修补到子对象包含JTables

import java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.image.buffereImage;
导入javax.swing.*;
导入javax.swing.repaitmanager;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
导入javax.swing.table.TableModel;
//http://stackoverflow.com/a/8249353/714968
公共类视口闪烁原始{
私有JFrame=新JFrame(“表格”);
私有JViewport viewport=新JViewport();
私有矩形RECT=新矩形();
私有矩形RECT1=新矩形();
专用JTable表=新JTable(50,3);
私有javax.swing.Timer;
私有整数计数=0;
私有布尔topOrBottom=false;
private GradientViewPortOriginal tableViewPort;
公共视口闪烁原始(){
tableViewPort=新的GradientViewPortOriginal(表格);
viewport=tableViewPort.getViewport();
viewport.addChangeListener(新的ChangeListener(){
@凌驾
公共无效状态已更改(更改事件e){
如果(tableViewPort.bolStart){
RECT=table.getCellRect(0,0,true);
RECT1=table.getCellRect(table.getRowCount()-1,0,true);
矩形viewRect=viewport.getViewRect();
if(视图矩形相交(矩形)){
System.out.println(“可见矩形->”+RECT);
tableViewPort.paintBackGround(新颜色(250150150));
}else if(视图矩形相交(矩形1)){
System.out.println(“可见的RECT1->”+RECT1);
tableViewPort.paintBackGround(新颜色(150250150));
}否则{
System.out.println(“可见矩形->?”;
助教
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.RepaintManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableModel;

//http://stackoverflow.com/a/8249353/714968
public class ViewPortFlickeringOriginal {

    private JFrame frame = new JFrame("Table");
    private JViewport viewport = new JViewport();
    private Rectangle RECT = new Rectangle();
    private Rectangle RECT1 = new Rectangle();
    private JTable table = new JTable(50, 3);
    private javax.swing.Timer timer;
    private int count = 0;
    private boolean topOrBottom = false;
    private GradientViewPortOriginal tableViewPort;

    public ViewPortFlickeringOriginal() {
        tableViewPort = new GradientViewPortOriginal(table);
        viewport = tableViewPort.getViewport();
        viewport.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                if (tableViewPort.bolStart) {
                    RECT = table.getCellRect(0, 0, true);
                    RECT1 = table.getCellRect(table.getRowCount() - 1, 0, true);
                    Rectangle viewRect = viewport.getViewRect();
                    if (viewRect.intersects(RECT)) {
                        System.out.println("Visible RECT -> " + RECT);
                        tableViewPort.paintBackGround(new Color(250, 150, 150));
                    } else if (viewRect.intersects(RECT1)) {
                        System.out.println("Visible RECT1 -> " + RECT1);
                        tableViewPort.paintBackGround(new Color(150, 250, 150));
                    } else {
                        System.out.println("Visible RECT1 -> ???? ");
                        tableViewPort.paintBackGround(new Color(150, 150, 250));
                    }
                }
            }
        });
        frame.add(tableViewPort);
        frame.setPreferredSize(new Dimension(600, 300));
        frame.pack();
        frame.setLocation(50, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        RepaintManager.setCurrentManager(new RepaintManager() {

            @Override
            public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
                Container con = c.getParent();
                while (con instanceof JComponent) {
                    if (!con.isVisible()) {
                        return;
                    }
                    if (con instanceof GradientViewPortOriginal) {
                        c = (JComponent) con;
                        x = 0;
                        y = 0;
                        w = con.getWidth();
                        h = con.getHeight();
                    }
                    con = con.getParent();
                }
                super.addDirtyRegion(c, x, y, w, h);
            }
        });
        frame.setVisible(true);
        start();
    }

    private void start() {
        timer = new javax.swing.Timer(100, updateCol());
        timer.start();
    }

    public Action updateCol() {
        return new AbstractAction("text load action") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {

                System.out.println("updating row " + (count + 1));
                TableModel model = table.getModel();
                int cols = model.getColumnCount();
                int row = 0;
                for (int j = 0; j < cols; j++) {
                    row = count;
                    table.changeSelection(row, 0, false, false);
                    timer.setDelay(100);
                    Object value = "row " + (count + 1) + " item " + (j + 1);
                    model.setValueAt(value, count, j);
                }
                count++;
                if (count >= table.getRowCount()) {
                    timer.stop();
                    table.changeSelection(0, 0, false, false);
                    java.awt.EventQueue.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            table.clearSelection();
                            tableViewPort.bolStart = true;
                        }
                    });
                }
            }
        };
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ViewPortFlickeringOriginal viewPortFlickering = new ViewPortFlickeringOriginal();
            }
        });
    }
}

class GradientViewPortOriginal extends JScrollPane {

    private static final long serialVersionUID = 1L;
    private final int h = 50;
    private BufferedImage img = null;
    private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB);
    private JViewport viewPort;
    public boolean bolStart = false;

    public GradientViewPortOriginal(JComponent com) {
        super(com);
        viewPort = this.getViewport();
        viewPort.setScrollMode(JViewport.BLIT_SCROLL_MODE);
        viewPort.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
        viewPort.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
        paintBackGround(new Color(250, 150, 150));
    }

    public void paintBackGround(Color g) {
        Graphics2D g2 = shadow.createGraphics();
        g2.setPaint(g);
        g2.fillRect(0, 0, 1, h);
        g2.setComposite(AlphaComposite.DstIn);
        g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h,
                new Color(0.1f, 0.8f, 0.8f, 0.5f)));
        g2.fillRect(0, 0, 1, h);
        g2.dispose();
    }

    @Override
    public void paint(Graphics g) {
        if (img == null || img.getWidth() != getWidth() || img.getHeight() != getHeight()) {
            img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
        }
        Graphics2D g2 = img.createGraphics();
        super.paint(g2);
        Rectangle bounds = getViewport().getVisibleRect();
        g2.scale(bounds.getWidth(), -1);
        int y = (getColumnHeader() == null) ? 0 : getColumnHeader().getHeight();
        g2.drawImage(shadow, bounds.x, -bounds.y - y - h, null);
        g2.scale(1, -1);
        g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h + y, null);
        g2.dispose();
        g.drawImage(img, 0, 0, null);
    }
}