title: Scrolling programmatically
body: <p>I would like the cell of my JTable to be aligned horizontally with the selected panels.<br/>Here is the a SSCCE to illustrate my problem.  Thanks for any help.<br/></p>
  
  <pre><code>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 &lt; 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 &lt; MAX; i++) {
                              SelectablePanel masterSelectablePanel = selectablePanels[i];
                              if (i != getNum() &amp;&amp; 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()));
                      }
                  }
              }
          }
      }
  }
  </code></pre>