【问题标题】:Scrolling programmatically以编程方式滚动
【发布时间】:2013-04-07 20:35:11
【问题描述】:

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

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()));
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 顺便说一句,+1 用于提供 SSCCE。顺便说一句:在实际代码中,您将在 setSelected 而不是侦听器中进行重绘。但是,这只是一个例子:-)
  • 好的,谢谢你的提示。我想我还是会编辑它以使用 JList,我认为这是 mKorbel 建议我让它更清晰的方法,但它的帖子已被删除。谢谢你的回答。
  • 正如我上周评论(删除评论)最好的问题......,然后我只评论,answers are around, some with great quality, but need to know how to search here,不要将 JCompones 放到 JList 或 JTable 中,只有它的描述,JButton 的字符串值,让 XxxRenderer 完成这项工作(绘制 JButton),顺便说一句,她的回答为您的投票而哭泣

标签: java swing jtable


【解决方案1】:

【讨论】:

  • 那个例子是正确的(本身就令人惊讶,来自 java2s.com ;-) 但在这个问题的上下文中,没有必要访问视口 :-)
【解决方案2】:

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

// 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);

请注意,这个 sn-p 假定面板的父视图和表格的视图的视口具有相同的大小,因此要么从表格中删除标题,要么将标题添加到面板的 scrollPane,或者使用 LayoutManager可以对齐两个scrollPanes的视口。

【讨论】:

    猜你喜欢
    • 2011-01-16
    • 2011-01-15
    • 2010-11-13
    • 2014-05-22
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多