2

標準のJTableを作成したいのですが、すべての行が1つの特定の列にまたがっています。そのため、その列には、レンダラーとしてJTextPaneを含むセルが1つだけ含まれている必要があります。あなたはそれをする簡単な方法を知っていますか?

注意:サードパーティのソフトウェアは必要ありません。

ありがとう。

4

2 に答える 2

3

@MvG のある種のオーバーレイのアイデアによってトリガーされたのは、JLayer を使用した概念実証です (jdk7 でコアに追加されました。以前のバージョンでは、SwingLabsで非常によく似た JXLayer を使用します)。

基本的な成分:

  • glassPane で textArea を管理する LayerUI
  • 列上の textArea のサイズ変更/配置を行うカスタム layoutManager
  • glassPane の再レイアウトを強制するいくつかのリスナー

少なくともそれを機能させるのは驚くほど簡単です。ただし、いくつかの粗いエッジがあります。

  • いつものように、テーブル内のナビゲーション: テーブルにフォーカスがある場合、そのセル選択は textArea の下に移動します。おそらくカスタム selectionModel が必要です
  • 列の移動中、列の下の表の行が表示されます
  • ?? おそらく別の悪魔の群れです。結局のところ、私たちはUIを混乱させています:-)

いくつかのコード:

public static class RowSpanUI extends LayerUI<JTable> {
    public static String COLUMN_TO_SPAN_KEY = "Table.columnToSpan";
    private JLayer layer;
    private JTextArea area;

    @Override
    public void installUI(JComponent c) {
        super.installUI(c);
        this.layer = (JLayer) c;
        installTextArea();
        installListeners();
    }


    @Override
    public void doLayout(JLayer<? extends JTable> l) {
        super.doLayout(l);
        l.getGlassPane().doLayout();
    }

     private void installTextArea() {
        area = new JTextArea(10, 20);
        layer.getGlassPane().setBorder(BorderFactory.createLineBorder(Color.RED));
        layer.getGlassPane().setLayout(new ColumnLayoutManager(this));
        layer.getGlassPane().add(area);
        layer.getGlassPane().setVisible(true);
    }

    public JTable getView() {
        return (JTable) layer.getView();
    }

    public int getViewColumnToSpan() {
        Object clientProperty = getView().getClientProperty(COLUMN_TO_SPAN_KEY);
        if (clientProperty instanceof Integer) {
            return getView().convertColumnIndexToView((int) clientProperty);
        }   
        return -1;
    }

    /**
     * Install listeners to manually trigger a layout of the glassPane.
     * This is incomplete, just the minimum for demonstration!
     */
    protected void installListeners() {
        ComponentListener compL = new ComponentListener() {

            @Override
            public void componentShown(ComponentEvent e) {
                doLayout(layer);
            }

            @Override
            public void componentResized(ComponentEvent e) {
                doLayout(layer);
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                doLayout(layer);
            }

            @Override
            public void componentHidden(ComponentEvent e) {
                // TODO Auto-generated method stub

            }
        };
        layer.addComponentListener(compL);

        TableColumnModelListener columnL = new TableColumnModelListener() {

            @Override
            public void columnRemoved(TableColumnModelEvent e) {
                doLayout(layer);
            }

            @Override
            public void columnMoved(TableColumnModelEvent e) {
                doLayout(layer);
            }

            @Override
            public void columnMarginChanged(ChangeEvent e) {
                doLayout(layer);
            }

            @Override
            public void columnAdded(TableColumnModelEvent e) {
                doLayout(layer);
            }

            @Override
            public void columnSelectionChanged(ListSelectionEvent e) {
            }

        };
        getView().getColumnModel().addColumnModelListener(columnL);
    }

}

public static class ColumnLayoutManager implements LayoutManager {

    private RowSpanUI ui;

    public ColumnLayoutManager(RowSpanUI ui) {
        this.ui = ui;
    }

    @Override
    public void layoutContainer(Container parent) {
        Component child = parent.getComponent(0);
        child.setBounds(getColumnBounds());
    }

    @Override
    public Dimension preferredLayoutSize(Container parent) {
        return ui.getView().getSize();
    }

    protected Rectangle getColumnBounds() {
        int viewColumn = ui.getViewColumnToSpan();
        if (viewColumn < 0) {
            return new Rectangle();
        }
        Rectangle r = ui.getView().getCellRect(0, viewColumn, false);
        r.height = ui.getView().getHeight();
        return r;
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
        return preferredLayoutSize(parent);
    }
    @Override
    public void addLayoutComponent(String name, Component comp) {
    }

    @Override
    public void removeLayoutComponent(Component comp) {
    }
}

// usage
JTable table = new JTable(myModel);
table.putClientProperty(RowSpanUI.COLUMN_TO_SPAN_KEY, 2);
JLayer layer = new JLayer(table, new RowSpanUI());
于 2012-07-30T15:09:08.040 に答える
1

セルの四角形へのクリッピングを含むのレンダリングは、問題のプラグイン可能なルック アンド フィールのユーザー インターフェイス実装JTableの奥深くに埋もれています。物事を変更すると厄介なビジネスになり、実際の JFC の実装に大きく依存します。

代わりに、それらの卵のセルを好きなように描画し、テーブルの上に別の透明なペインを用意して、説明したスパンされたコンテンツでそれらの領域をオーバーレイすることをお勧めします. まだ厄介で、おそらくかなりの作業ですが、移植可能になる可能性が高くなります。

于 2012-07-30T12:28:23.820 に答える