以编程方式滚动 [英] Scrolling programmatically

查看:69
本文介绍了以编程方式滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望JTable的单元格与所选面板水平对齐.
这里是一个SSCCE来说明我的问题.感谢您的帮助.

I would like the cell of my JTable to be aligned horizontally with the selected panels.
Here is the a SSCCE to illustrate my problem. Thanks for any help.

public class TableCellAlignment {

    private final static int MAX = 50;
    private static SelectablePanel[] selectablePanels = new SelectablePanel[MAX];
    private static JScrollPane slaveScrollPane = new JScrollPane();
    private static JScrollPane masterScrollPane = new JScrollPane();
    private static JTable slaveTable = new JTable();

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TableCellAlignment().createGUI();
            }
        });
    }

    private static void createGUI() {
        JFrame f = new JFrame("TableCellAlignment");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel masterPanel = new JPanel(new GridLayout(MAX, 1));
        Integer[][] objs = new Integer[MAX][1];
        for (int i = 0; i < MAX; i++) {
            objs[i][0] = new Integer(i);
            SelectablePanel masterSelectablePanel = new SelectablePanel();
            masterSelectablePanel.setNum(i);
            selectablePanels[i] = masterSelectablePanel;
            masterPanel.add(masterSelectablePanel);
        }
        DefaultTableModel model = new DefaultTableModel(objs, new Object[]{"Column1"});
        model.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        slaveTable.setRowHeight(20);
                    }
                });
            }
        });
        model.addRow(objs);
        slaveTable.setModel(model);
        final JPanel p = new JPanel(new GridLayout(1, 2));
        masterScrollPane.setViewportView(masterPanel);
        slaveScrollPane.setViewportView(slaveTable);
        p.add(masterScrollPane);
        p.add(slaveScrollPane);
        f.add(p);

        f.setSize(400, 200);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class SelectablePanel extends JPanel {

        private PropertyChangeSupport cs;
        private int num;
        private boolean selected = false;

        public SelectablePanel() {
            cs = new PropertyChangeSupport(this);
            cs.addPropertyChangeListener(new SelectedPropertyChangeListener());
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    setSelected(true);
                }
            });
        }

        public int getNum() {
            return num;
        }

        public void setNum(int num) {
            this.num = num;
        }

        public boolean isSelected() {
            return selected;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (selected) {
                Color c = g.getColor();
                g.setColor(Color.blue);
                g.fillRect(0, 0, getWidth(), getHeight());
                g.setColor(Color.white);
                FontMetrics fm = g.getFontMetrics();
                g.drawString("" + getNum(), getWidth() / 2, (getHeight() + (fm.getAscent() - fm.getDescent())) / 2);
                g.setColor(c);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 20);
        }

        public void setSelected(boolean selected) {
            boolean oldVal = isSelected();
            this.selected = selected;
            cs.firePropertyChange("selected", oldVal, selected);
            repaint();
        }

        private class SelectedPropertyChangeListener implements PropertyChangeListener {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals("selected")) {
                    boolean selected = (boolean) evt.getNewValue();
                    if (selected) {
                        for (int i = 0; i < MAX; i++) {
                            SelectablePanel masterSelectablePanel = selectablePanels[i];
                            if (i != getNum() && masterSelectablePanel.isSelected()) {
                                masterSelectablePanel.setSelected(false);
                            }

                        }
                        slaveTable.setRowSelectionInterval(getNum(), getNum());
                        final JViewport viewport = slaveScrollPane.getViewport();
                        Rectangle rect = new Rectangle(getBounds().x, getBounds().y, 1, 1);
                        Rectangle r2 = viewport.getVisibleRect();
                        slaveTable.scrollRectToVisible(new Rectangle(rect.x, rect.y, (int)r2.getWidth(), (int)r2.getHeight()));
                    }
                }
            }
        }
    }
}

推荐答案

这是基本数学运算,不需要访问视口:

It's basic math and it does not require access to the viewport:

// in the isSelected block of the propertyChangeListener:
JComponent current = (JComponent) evt.getSource();
slaveTable.setRowSelectionInterval(getNum(), getNum());
// get the cellRect of the selected cell
Rectangle cellRect = slaveTable.getCellRect(getNum(), 0, false);
// get the bounds of the selected panel
Rectangle panelRect = current.getBounds();
// get the visible rect of the selected panel's parent
Rectangle parentVisibleRect = ((JComponent) current.getParent()).getVisibleRect(); 
// the diff above the current (to the parent's visible rect)
int aboveCurrent = panelRect.y - parentVisibleRect.y;
// translate the cell rect 
cellRect.y = Math.max(cellRect.y - aboveCurrent, 0);
// adjust size to slaveTable's visible height
cellRect.height = slaveTable.getVisibleRect().height;
slaveTable.scrollRectToVisible(cellRect);

请注意,此代码段假定面板的父级和表格的视图视口具有相同的大小,因此可以从表格中删除标题,或者将标题添加到面板的scrollPane中,或者使用可以对齐的LayoutManager两个scrollPanes的视口.

Note that this snippet assumes that the view's viewport of both the panel's parent and the table have the same size, so either remove the header from the table, or add a header to the panel's scrollPane, or use a LayoutManager which can align the viewports of the two scrollPanes.

这篇关于以编程方式滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆