JSplitScrollPane DEMO

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneLayout;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumnModel;


/**
 *
 * @author raistlic
 * @date   Jan 28, 2013
 */
public class JSplitScrollPane extends JScrollPane {
  
  public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {

      @Override
      public void run() {

        try {

          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch(Exception e) {

          e.printStackTrace();
        }

        JFrame f = new JFrame("Test Normal ScrollPane");
        TestTableModel tm = new TestTableModel(100, 30);

        JTable rowHeader = tm.getRowHeaderTable();
        JTable content = tm.getContentTable();

        JScrollPane pane = new JSplitScrollPane();
        pane.setViewportView(content);
        pane.setColumnHeaderView(content.getTableHeader());
        pane.setRowHeaderView(rowHeader);
        pane.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowHeader.getTableHeader());

        f.getContentPane().add(pane, BorderLayout.CENTER);
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setVisible(true);
      }
    });
  }
  
  private final JSplitPane splitPane;
  private JPanel left, right;
  public JSplitScrollPane() {
    
    super();
    
    splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
    left = new JPanel(this.new RowHeaderLayout());
    right = new JPanel(this.new ContentLayout());
    splitPane.setLeftComponent(left);
    splitPane.setRightComponent(right);
    setLayout(new SplitedScrollPaneLayout());
    
    setRowHeader(createViewport());
    setColumnHeader(createViewport());
    setViewport(createViewport());
    
    left.add(getRowHeader());
    right.add(getViewport());
    right.add(getColumnHeader());
    
    right.add(getHorizontalScrollBar());
    right.add(getVerticalScrollBar());
    
    this.add(splitPane);
  }
  
  @Override
  public void setCorner(String key, Component corner) {
    
    Component old = getCorner(key);
    super.setCorner(key, corner);
    
    if(old != null)
      left.remove(old);
    
    if( corner != null ) {
      
      if( key.equals(UPPER_LEFT_CORNER) ||
          key.equals(LOWER_LEFT_CORNER) )
        left.add(corner);
      else
        right.add(corner); // probably problematic, just for demo
    }
    
  }
  
  private int calculateTopPreferredHeight() {
    
    int result = 0;
    Component c = getCorner(UPPER_LEFT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    c = getCorner(UPPER_RIGHT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    c = getColumnHeader();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    return result;
  }
  
  private int calculateBottomPreferredHeight() {
    
    int result = 0;
    Component c = getHorizontalScrollBar();
    result = Math.max(result, c.getPreferredSize().height);
    c = getCorner(LOWER_LEFT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    c = getCorner(LOWER_RIGHT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    return result;
  }
  
  private int calculateCenterPreferredHeight() {
    
    int result = 0;
    Component c = getRowHeader();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    c = getViewport();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().height);
    return result;
  }
  
  private int calculateLeftPreferredWidth() {
    
    int result = 0;
    Component c = getCorner(UPPER_LEFT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    c = getCorner(LOWER_LEFT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    c = getRowHeader();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    return result;
  }
  
  private int calculateCenterPreferredWidth() {
    
    int result = 0;
    Component c = getColumnHeader();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    c = getViewport();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    return result;
  }
  
  private int calculateRightPreferredWidth() {
    
    int result = 0;
    Component c = getCorner(UPPER_RIGHT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    c = getCorner(LOWER_RIGHT_CORNER);
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    c = getVerticalScrollBar();
    if( c != null )
      result = Math.max(result, c.getPreferredSize().width);
    return result;
  }
  
  private class RowHeaderLayout implements LayoutManager {

    @Override
    public void addLayoutComponent(String name, Component comp) {}

    @Override
    public void removeLayoutComponent(Component comp) {}

    @Override
    public Dimension preferredLayoutSize(Container parent) {
      
      int top = calculateTopPreferredHeight();
      int center = calculateCenterPreferredHeight();
      int bottom = calculateBottomPreferredHeight();
      
      int width = calculateLeftPreferredWidth();
      
      return new Dimension(width, top + center + bottom);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
      
      return preferredLayoutSize(parent);
    }

    @Override
    public void layoutContainer(Container parent) {
      
      Rectangle bounds = parent.getBounds();
      bounds.x = 0;
      bounds.y = 0;
      Insets insets = parent.getInsets();
      bounds.x += insets.left;
      bounds.y += insets.top;
      bounds.width -= insets.left + insets.right;
      if( bounds.width <= 0 )
        return;
      bounds.height -= insets.top + insets.bottom;
      if( bounds.height <= 0 )
        return;
      
      int top = Math.min(calculateTopPreferredHeight(), bounds.height);
      Component c = getCorner(UPPER_LEFT_CORNER);
      if( c != null )
        c.setBounds(bounds.x, bounds.y, bounds.width, top);
      bounds.y += top;
      bounds.height -= top;
      if( bounds.height <= 0 )
        return;
      
      int bottom = Math.min(calculateBottomPreferredHeight(), bounds.height);
      c = getCorner(LOWER_LEFT_CORNER);
      if( c != null )
        c.setBounds(bounds.x, bounds.y + bounds.height - bottom, bounds.width, bottom);
      bounds.height -= bottom;
      if( bounds.height <= 0 )
        return;
      
      c = getRowHeader();
      if( c != null )
        c.setBounds(bounds);
    }
  }
  
  private class ContentLayout implements LayoutManager {

    @Override
    public void addLayoutComponent(String name, Component comp) {}

    @Override
    public void removeLayoutComponent(Component comp) {}

    @Override
    public Dimension preferredLayoutSize(Container parent) {
      
      int heightTop = calculateTopPreferredHeight();
      int heightCenter = calculateCenterPreferredHeight();
      int heightBottom = calculateBottomPreferredHeight();
      
      int widthCenter = calculateCenterPreferredWidth();
      int widthRight = calculateRightPreferredWidth();
      
      return new Dimension(widthCenter + widthRight, 
                           heightTop + heightCenter + heightBottom);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
      
      return new Dimension(100, 100);
    }

    @Override
    public void layoutContainer(Container parent) {
      
      Rectangle bounds = parent.getBounds();
      bounds.x = 0;
      bounds.y = 0;
      Insets insets = parent.getInsets();
      bounds.x += insets.left;
      bounds.y += insets.top;
      bounds.width -= insets.left + insets.right;
      bounds.height -= insets.top + insets.bottom;
      if( bounds.width <= 0 )
        return;
      if( bounds.height <= 0 )
        return;
      
      int rightWidth = Math.min(bounds.width, calculateRightPreferredWidth());
      Rectangle right = new Rectangle(
              bounds.x + bounds.width - rightWidth, bounds.y, rightWidth, bounds.height);
      Rectangle center = new Rectangle(
              bounds.x, bounds.y, bounds.width - right.width, bounds.height);
      int top = Math.min(bounds.height, calculateTopPreferredHeight());
      Component c = getCorner(UPPER_RIGHT_CORNER);
      if( c != null )
        c.setBounds(right.x, right.y, right.width, top);
      c = getColumnHeader();
      if( c != null && center.width > 0 )
        c.setBounds(center.x, center.y, center.width, top);
      right.y += top;
      right.height -= top;
      center.y += top;
      center.height -= top;
      if( right.height <= 0 )
        return;
      
      int bottom = Math.min(right.height, calculateBottomPreferredHeight());
      c = getCorner(LOWER_RIGHT_CORNER);
      if( c != null )
        c.setBounds(right.x, right.y, right.width, bottom);
      getHorizontalScrollBar().setBounds(
              center.x, center.y + center.height - bottom, center.width, bottom);
      right.height -= bottom;
      center.height -= bottom;
      if( right.height <= 0 )
        return;
      
      getVerticalScrollBar().setBounds(right);
      c = getViewport();
      if( c != null )
        c.setBounds(center);
    }
  }
  
  private static class SplitedScrollPaneLayout extends ScrollPaneLayout {

    @Override
    public void addLayoutComponent(String name, Component comp) {}

    @Override
    public void removeLayoutComponent(Component comp) {}

    @Override
    public Dimension preferredLayoutSize(Container parent) {
      
      @SuppressWarnings("unchecked")
      JSplitScrollPane ssp = (JSplitScrollPane)parent;
      return ssp.splitPane.getPreferredSize();
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
      
      @SuppressWarnings("unchecked")
      JSplitScrollPane ssp = (JSplitScrollPane)parent;
      return ssp.splitPane.getMinimumSize();
    }

    @Override
    public void layoutContainer(Container parent) {
      
      @SuppressWarnings("unchecked")
      JSplitScrollPane ssp = (JSplitScrollPane)parent;
      
      Rectangle rec = ssp.getBounds();
      rec.x = 0;
      rec.y = 0;
      Insets insets = ssp.getInsets();
      rec.x += insets.left;
      rec.y += insets.top;
      rec.width -= insets.left + insets.right;
      rec.height -= insets.top + insets.bottom;
      
      ssp.splitPane.setBounds(rec);
    }
  }
}

class TestTableModel extends AbstractTableModel {

  private int rows;
  private int cols;
  private JTable rowHeader;
  private JTable content;

  TestTableModel(int rows, int cols) {

    assert rows > 0;
    assert cols > 0;

    this.rows = rows;
    this.cols = cols;

    rowHeader = createRowHeaderTable();
    content = createContentTable();

    rowHeader.setPreferredScrollableViewportSize(new Dimension(150, 150));
    rowHeader.setSelectionModel(content.getSelectionModel());
    content.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
  }

  JTable getRowHeaderTable() {

    return rowHeader;
  }

  JTable getContentTable() {

    return content;
  }

  @Override
  public int getRowCount() {

    return rows;
  }

  @Override
  public int getColumnCount() {

    return cols + 1;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {

    if( columnIndex == 0 )
      return String.format("Row Header %03d", rowIndex + 1);
    else
      return String.format("Cell [ %03d, %03d ]", rowIndex + 1, columnIndex);
  }

  private JTable createRowHeaderTable() {

    JTable table = new JTable(this);
    TableColumnModel model = new DefaultTableColumnModel();
    model.addColumn(table.getColumnModel().getColumn(0));
    table.setColumnModel(model);
    return table;
  }

  private JTable createContentTable() {

    JTable table = new JTable(this);
    TableColumnModel model = table.getColumnModel();
    model.removeColumn(model.getColumn(0));
    table.setColumnModel(model);
    return table;
  }
}


这里就先不作整理了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值