- PR -

JScrollPaneについて

1
投稿者投稿内容
Manoaman
会議室デビュー日: 2006/11/04
投稿数: 8
投稿日時: 2006-11-17 17:34
こんにちは。
JScrollPaneの以下の点について調査しているのですが、もしご存知であれば可能であるか教えてください。また、可能であれば実現方法を教えて下さい。どうぞよろしくお願いします。

1.JScrollPaneにくみこまれたJTableの特定行のみをViewportの中で表示させることは可能でしょうか?(特定行のみ表示させて左右スクロールさせたい。)

2.JTableが組み込まれた複数のJScrollPaneの左右スクロールを同期させる場合、片方のJScrollPaneのスクロールバーを表示せずスクロールを同期させたい。

3.複数のJTableをJScrollPaneにくみこみたい。もし可能な場合、片方のテーブルは特定行のみ(TableRowModel?)

nekoyama
ベテラン
会議室デビュー日: 2005/03/12
投稿数: 71
投稿日時: 2006-11-18 03:08
引用:

1.JScrollPaneにくみこまれたJTableの特定行のみをViewportの中で表示させることは可能でしょうか?(特定行のみ表示させて左右スクロールさせたい。)


JTable.setPreferredScrollableViewportSize()の設定またはgetPreferredScrollableViewportSize()のオーバーライド。
もしくは、JScrollPane,Viewportのサイズ設定で可能でしょう。

引用:

2.JTableが組み込まれた複数のJScrollPaneの左右スクロールを同期させる場合、片方のJScrollPaneのスクロールバーを表示せずスクロールを同期させたい。


JTable.getCellRect(),scrollRectToVisible(),getVisibleRect()で、
おそらく可能です。

引用:

3.複数のJTableをJScrollPaneにくみこみたい。もし可能な場合、片方のテーブルは特定行のみ(TableRowModel?)


JScrollPaneはContainerインスタンスなので、ネストすれば、複数のJTableは設定できます。
特定行のみ表示する方法については、上記。

ところで、私にはManoamanが実装しようとしているUIの用途が想像できないので、
非常に興味があるのですが、上のようなUIはどういう場合に使用できるのですか?
宜しければ教えてください。

[/quote]
Manoaman
会議室デビュー日: 2006/11/04
投稿数: 8
投稿日時: 2006-11-19 13:19
未記入さん、お返事ありがとうございます。

引用:
JTable.getCellRect(),scrollRectToVisible(),getVisibleRect()で、
おそらく可能です。



なるほど、こういう方法もあるのですね。このスレッドを見る前に自己解決してしまっていたのですが、setVerticalScrollBarPolicyでScrollPaneConstants.VERTICAL_SCROLLBAR_NEVERを設定することでも可能なようでした。ありがとうございます。

引用:
JTable.setPreferredScrollableViewportSize()の設定またはgetPreferredScrollableViewportSize()のオーバーライド。
もしくは、JScrollPane,Viewportのサイズ設定で可能でしょう。



setPreferredScrollableViewportSize()の設定とViewportを取得した上でのサイズ設定では、どうも一列のみ表示することができなかった(表示枠が全く変わらなかった)のですが、JScrollPaneのsetPreferredSizeでJTableの表示枠を制限することが可能でした。但し、下記コードのContainerにJPanel、Boxクラスを追加してる時に、BorderLayout.Northの位置にBoxをするとJScrollPaneの高さを0にしようとも、列とそのしたにあるViewPortの空白(?)が表示されてしまいます。BorderLayoutでどの位置に置いても、おなじ状態(一列のみが表示される状態)にしたいのですが可能でしょうか?

また、getPreferredScrollableViewportSize()のオーバーライドとあるのですが、もう少し具体的に教えてください。これはJTableを継承したサブクラスを作成して、制限枠のサイズを返すということでしょうか?

引用:
ところで、私にはManoamanが実装しようとしているUIの用途が想像できないので、
非常に興味があるのですが、上のようなUIはどういう場合に使用できるのですか?
宜しければ教えてください。



もともとは連結したヘッダセルにJComboBoxを組み込みたいことに起因しているのですが、ヘッダに対して「連結」と「JCombBoxの組み込み」はそれぞれ分かったのですが、連結セルに組み込むことの解決方法が分からず、JTableを二つ使って実現しようと思ったところです。ひょっとするともっと簡単で良い方法があるのかもしれませんが、とりあえずは一つの実現方法としてJTable二つを使ってみようと思いました。


コード:
package sample;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

import edu.ucla.loni.inspector.manager.ScrollBarManager;

public class SampleTable extends JFrame implements ActionListener {

        private JComboBox comboBox;
        private JTable table1;
        private JTable table2;
        private DefaultTableModel tableModel1;
        private DefaultTableModel tableModel2;
        private JScrollPane scrollPane1;
        private JScrollPane scrollPane2;
        private JButton button;
        private JPanel panel;
        private Box tableBox;

        // Constants.
        private final String COMBO_BOX_TITLE  = "Files";
        private final String[] COLUMN_NAMES   = {"Column1", "Column2", "Column3"};
        private final int FIRST_COLUMN        = 0;
        private final int SECOND_COLUMN       = 1;
        private final int THIRD_COLUMN        = 2;
        private final int FIRST_THREE_COLUMNS = 3;
        private final String ADD_COLUMN       = "Add Column";
        private final int COLUMN_WIDTH        = 150;

        public SampleTable() {
                setBounds(10,10,700,700);

                setTables();
                       tableBox = new Box(BoxLayout.Y_AXIS);
                tableBox.add(scrollPane1);
                tableBox.add(scrollPane2);

                button = new JButton(ADD_COLUMN);

                panel = new JPanel();
                panel.add(button);
                button.addActionListener(this);
                button.setActionCommand(ADD_COLUMN);

                // Add conponents.
                getContentPane().add(new JPanel(),BorderLayout.NORTH);  // <---  ここをNORTHにするか、CENTERにするかでRowの表示枠サイズが変化
                getContentPane().add(tableBox,BorderLayout.CENTER);     // <---  ここをNORTHにするか、CENTERにするかでRowの表示枠サイズが変化
                getContentPane().add(panel,BorderLayout.SOUTH);
                       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                // Not called from EDT.
                SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                                setVisible(true);
                        }
                });
        }

        private void setTables() {
                // Set table 1 ------------------------------------------------->
                tableModel1 = new DefaultTableModel(1,1);
                tableModel1.setValueAt(COMBO_BOX_TITLE, 0, 0);
                table1 = new JTable(tableModel1);
                table1.setTableHeader(null);
                table1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

                int width = COLUMN_WIDTH * FIRST_THREE_COLUMNS;
//                table1.getColumnModel().getColumn(FIRST_COLUMN).setWidth(width);
                table1.getColumnModel().getColumn(FIRST_COLUMN).setPreferredWidth(width);
                table1.getColumnModel().getColumn(FIRST_COLUMN).setMinWidth(width);
                table1.getColumnModel().getColumn(FIRST_COLUMN).setMaxWidth(width);

                // Set a view port size.
//              table1.setPreferredScrollableViewportSize(new Dimension(400,10)); <---- 特定Rowの表示

                // Set JComboBox as an editor.
                TableColumn fileColumn = table1.getColumnModel().getColumn(FIRST_COLUMN);
                comboBox = new JComboBox();
                comboBox.addItem(COMBO_BOX_TITLE);
                fileColumn.setCellEditor(new DefaultCellEditor(comboBox));

                // end of set table 1 <------------------------------------------

                // Set table 2 ------------------------------------------------->
                tableModel2 = new DefaultTableModel(COLUMN_NAMES,0);
                table2 = new JTable(tableModel2);
                table2.getTableHeader().setReorderingAllowed(false);
                table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

                // First column.
//                table2.getColumnModel().getColumn(FIRST_COLUMN).setWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(FIRST_COLUMN).setPreferredWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(FIRST_COLUMN).setMinWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(FIRST_COLUMN).setMaxWidth(COLUMN_WIDTH);

                // Second column.
//                table2.getColumnModel().getColumn(SECOND_COLUMN).setWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(SECOND_COLUMN).setPreferredWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(SECOND_COLUMN).setMinWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(SECOND_COLUMN).setMaxWidth(COLUMN_WIDTH);

                // Third column.
//              table2.getColumnModel().getColumn(THIRD_COLUMN).setWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(THIRD_COLUMN).setPreferredWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(THIRD_COLUMN).setMinWidth(COLUMN_WIDTH);
                table2.getColumnModel().getColumn(THIRD_COLUMN).setMaxWidth(COLUMN_WIDTH);

                // end of set table 2 <------------------------------------------

                // Set tables in a JScrollPane.
                scrollPane1 = new JScrollPane(table1);
                scrollPane1.setPreferredSize(new Dimension(400,20)); <---- 特定Rowの表示
                scrollPane1.setVerticalScrollBarPolicy(
                       ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
                scrollPane1.setHorizontalScrollBarPolicy(
                       ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
                scrollPane2 = new JScrollPane(table2);
                scrollPane2.setPreferredSize(new Dimension(400,480));
                // Make scroll simultaneous.
           
                final JScrollBar scrollBar1 = scrollPane1.getHorizontalScrollBar();
                JScrollBar scrollBar2 = scrollPane2.getHorizontalScrollBar();
                scrollBar2.addAdjustmentListener(new AdjustmentListener() {
                    public void adjustmentValueChanged(AdjustmentEvent e) {
                       scrollBar1.setValue(e.getValue());
                    }
                });
        }

        public void actionPerformed(ActionEvent e) {
                String command = e.getActionCommand();
                if(command.equals(ADD_COLUMN)){
                        TableColumn column2 = new TableColumn();
                        table2.getColumnModel().addColumn(column2);
                        int resizeWidth = 0;
                        for(int i=FIRST_COLUMN;i<FIRST_THREE_COLUMNS;i++){
                                resizeWidth += table2.getColumnModel().getColumn(i).getWidth();
                        }

                        TableColumn column = new TableColumn();
                        table1.getColumnModel().addColumn(column);
                        table1.getColumnModel().getColumn(FIRST_COLUMN).setPreferredWidth(resizeWidth);
                }
        }

        public static void main(String[] args) {
                // Convention for starting Swing application?
                SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                                SampleTable st = new SampleTable();
                        }
                });
        }

}

nekoyama
ベテラン
会議室デビュー日: 2005/03/12
投稿数: 71
投稿日時: 2006-11-19 15:06
[quote]
Manoamanさんの書き込み (2006-11-19 13:19) より:
未記入さん、お返事ありがとうございます。

引用:

なるほど、こういう方法もあるのですね。このスレッドを見る前に自己解決してしまっていたのですが、setVerticalScrollBarPolicyでScrollPaneConstants.VERTICAL_SCROLLBAR_NEVERを設定することでも可能なようでした。ありがとうございます。


"ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVERを設定することでも可能"なわけないですよね?
そのプロパティは、Viewport内のViewComponentのサイズが変更された場合に、
ScrollBarの表示、非表示の挙動を決めてるだけなんですから。

そのプロパティを設定したところで、2つのJTableの表示領域が自動で同期されるわけが
ないです。

後に見る人のために、実装方法を書かれてはどうでしょう?

引用:

setPreferredScrollableViewportSize()の設定とViewportを取得した上でのサイズ設定では、どうも一列のみ表示することができなかった(表示枠が全く変わらなかった)のですが、JScrollPaneのsetPreferredSizeでJTableの表示枠を制限することが可能でした。但し、下記コードのContainerにJPanel、Boxクラスを追加してる時に、BorderLayout.Northの位置にBoxをするとJScrollPaneの高さを0にしようとも、列とそのしたにあるViewPortの空白(?)が表示されてしまいます。BorderLayoutでどの位置に置いても、おなじ状態(一列のみが表示される状態)にしたいのですが可能でしょうか?


可能だと思いますが、正直なところ、上記の文章がよく理解できません。

引用:

また、getPreferredScrollableViewportSize()のオーバーライドとあるのですが、もう少し具体的に教えてください。これはJTableを継承したサブクラスを作成して、制限枠のサイズを返すということでしょうか?


そういうことです。
不要な継承を増やす可能性があるため、どんな場合でも推奨できるという方法では
ありません。
ただし、サブクラスに決してサイズ変更を許さないというメリットもあります。
Swingでは結構、使用されるHackの1つです。
要件によって使い分けるべきです。

引用:

もともとは連結したヘッダセルにJComboBoxを組み込みたいことに起因しているのですが、ヘッダに対して「連結」と「JCombBoxの組み込み」はそれぞれ分かったのですが、連結セルに組み込むことの解決方法が分からず、JTableを二つ使って実現しようと思ったところです。ひょっとするともっと簡単で良い方法があるのかもしれませんが、とりあえずは一つの実現方法としてJTable二つを使ってみようと思いました。


残念ながら、丸投げに近いソースの上に長くて、読む気になれません。

まぁ、色々な要件の中で、良い選択肢の1つであるならば、別ですが、
ヘッダをちょっとHackするためだけにJTableを2つ用意するのは、
実装的には、あまりにも。。と思いますが。
データが少なければ、良いですがDefaultTableModelで実装した場合、
あまりにも無駄が多いですし。

そんなことする位なら、自前で描画した方がシンプルな気がしますが。
まぁ、あくまで、工数とかを考慮しない実装上の話です。

追加ですが、上記実装は、どんなUIに使用できるのですか?
私も、以前、そのサンプルを見たことがあるのですが、それを使用する
UIのインスピレーションが湧かなかったもので。
1

スキルアップ/キャリアアップ(JOB@IT)