1

DefaultTableModelの拡張機能を次のように使用しています。

これは、いくつかの回答からの入力を反映するように更新した後の新しいAchievementTableModelです。

public AchievementTableModel(Object[][] c, Object[] co) {
    super(c,co);
}
public boolean isCellEditable(int r, int c) {return false;}
public void replace(Object[][] c, Object[] co) {
    setDataVector(convertToVector(c), convertToVector(co));
    fireTableDataChanged();
}

私のGUIは、次のプロパティを持つJTableです。

if(table==null)
    table = new JTable(model);
else
    table.setModel(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
table.getTableHeader().setReorderingAllowed(false);
table.getTableHeader().setResizingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);

表示するデータを選択するJComboBoxがあります。TableModelは、model.replace(cells)を呼び出すことで更新され、上記のテーブル作成コードを再度実行します。

GUI JTableで行を選択し、table.getSelectedRow()値を出力すると、最初のJComboBoxを再選択した場合でも、最初の選択からmodel.replace(cells)呼び出しでテーブルデータを変更した後、常に-1が返されます。オプション。私が行方不明になっている理由はありますか?コードを変更する必要がありますか?

編集:コードはこの質問に答えようとすることで大きく変わったので、ここに更新されたコードがあります。新しいAchievementTableModelは上にあります。

これにより、モデルとテーブルが正しく表示され、ScrollPaneに表示されるように設定されます。

if(model==null)
    model = new AchievementTableModel(cells, columns);
else
    model.replace(cells, columns);
if(table==null) {
    table = new JTable(model);
    table.setFillsViewportHeight(true);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.getTableHeader().setReorderingAllowed(false);
    table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
    table.getColumnModel().setColumnSelectionAllowed(false);
    table.getTableHeader().setResizingAllowed(false);
} else
    table.setModel(model);

column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();

add(new JScrollPane(table), BorderLayout.CENTER);
4

8 に答える 8

2

わかりました、今私は興味があります

周りにはたくさんの参照があるので、本当に本当にコードをクリーンアップする必要があるようです。

選択したインデックスのテーブルが表示されない理由は、新しいレコードを作成するたびにJTable、選択したレコードを印刷するメソッドが元のレコードを指しているためです。「新しく」作成されたテーブルを表示しているので、古いテーブルが印刷されます-1

を使用するときに空のテーブルを取得する理由DefaultTableModelは、ベクトルがnull(おそらくコンボから取得される)ため、データとヘッダーの両方がテーブルから消えるためです。

Object[][]とにかくデータとして使用している場合は、サブクラスは必要ありません。

だからここにあなたがあなたのものを修正するために見ることができる何とか簡単なテストクラスがあります。

私はあなたの習慣TableModelDefaultTableModel

これは、カスタムテーブルモデルとは関係ありませんが、参照の使用方法とは関係ありません。

これがお役に立てば幸いです。

import javax.swing.*;
import java.awt.*;
import javax.swing.table.*;
import java.util.*;
import java.awt.event.*;
public class Test { 

    private DefaultTableModel tableModel = null;
    //private AchievementTableModel tableModel = null;
    private Object []   headers = new Object[]{"Name", "Last Name"};
    private Object [][] data;
    private Object [][] dataA = new Object[][]{{"Oscar","Reyes"},{"John","Doe"}};
    private Object [][] dataB = new Object[][]{{"Color","Green"},{"Thing","Car"}};
    private JTable table;


    public static void main( String [] args ) { 
        Test test = new Test();
        test.main();
    }
    public void main() { 
        // Create the frame
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        // Create the unique table.
        table = new JTable();
        frame.add(new JScrollPane( table ));

        // Add two buttons
        frame.add( new JPanel(){{ 
            // swap table model button ( simulates combo )
            add(new JButton("Change Table model"){{
                addActionListener( new ActionListener() { 
                    public void actionPerformed( ActionEvent e ) { 
                        if( tableModel == null ) { 
                            data = dataA;
                            tableModel = new DefaultTableModel( data, headers );
                            //tableModel = new AchievementTableModel( data, headers );
                            table.setModel( tableModel );
                        } else { 
                            data = data == dataA ? dataB : dataA;
                            tableModel.setDataVector( data, headers );
                            //tableModel.replace( data ); // not needed DefaultTableModel already has it.

                        }
                    }
                });
            }});
            // and print selectedRow button
            add( new JButton("Print selected row"){{
                addActionListener( new ActionListener() { 
                    public void actionPerformed( ActionEvent e ) { 
                        System.out.println(table.getSelectedRow());
                    }
                });
            }});

        }}, BorderLayout.SOUTH);

        // show the frame
        frame.pack();
        frame.setVisible( true );
    }

}

サブクラスは変更されていません。

class AchievementTableModel extends DefaultTableModel {

    public AchievementTableModel(Object[][] c, Object[] co) {
        super.dataVector = super.convertToVector(c);
        super.columnIdentifiers = super.convertToVector(co);
    }
    public int getColumnCount() {return super.columnIdentifiers.size();}
    public int getRowCount() {return super.dataVector.size();}
    public String getColumnName(int c) {return (String)super.columnIdentifiers.get(c);}
    @SuppressWarnings("unchecked")
    public Object getValueAt(int r, int c) {return ((Vector<Object>)super.dataVector.get(r)).get(c);}
    public boolean isCellEditable(int r, int c) {return false;}
    public void replace(Object[][] c) {
        super.dataVector = super.convertToVector(c);
        super.fireTableDataChanged();
    }
}

それを試して、テーブル参照が失われないことを確認し、常に正しいを出力してselectedRowください。

代替テキスト

それをあなたのコードと比較し、そこから修正してください。

于 2009-06-25T21:56:49.137 に答える
2

replaceを呼び出した後、新しいJTableでテーブルを再初期化しないでください。fireTableDataChanged()メソッドは、既存のテーブルに再描画する必要があることを警告します。何が起こっているのかというと、パネルに入れたテーブルを見ているのに、変数をJTableの別のインスタンスに変更しているということです。その新しいが表示されていないテーブルをクエリすると、選択した行数に対して-1が返されます。投稿を編集して、コードのその領域で何が起こっているかを表示すると役立つ場合があります。

2番目の編集:

これの代わりに:

  if(model==null)
    model = new AchievementTableModel(cells, columns);
  else
    model.replace(cells, columns);
  if(table==null) {
    table = new JTable(model);
    table.setFillsViewportHeight(true);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.getTableHeader().setReorderingAllowed(false);
    table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
    table.getColumnModel().setColumnSelectionAllowed(false);
    table.getTableHeader().setResizingAllowed(false);
  } else
    table.setModel(model);

  column = table.getColumn(columns[0]);
  column.setPreferredWidth(25);
  column = table.getColumn(columns[1]);
  column.setPreferredWidth(225);
  column = table.getColumn(columns[2]);
  column.setPreferredWidth(40);
  table.doLayout();

  add(new JScrollPane(table), BorderLayout.CENTER);

代わりにこれを行います:

 if(model==null) {
    model = new AchievementTableModel(cells, columns);
 } else {
    model.setDataVector(cells, columns);
 }
 if(table==null) {
    table = new JTable(model);
    table.setFillsViewportHeight(true);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.getTableHeader().setReorderingAllowed(false);
    table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
    table.getColumnModel().setColumnSelectionAllowed(false);
    table.getTableHeader().setResizingAllowed(false);

    column = table.getColumn(columns[0]);
    column.setPreferredWidth(25);
    column = table.getColumn(columns[1]);
    column.setPreferredWidth(225);
    column = table.getColumn(columns[2]);
    column.setPreferredWidth(40);
    table.doLayout();

    add(new JScrollPane(table), BorderLayout.CENTER);
   } else {
    table.setModel(model);
   }

新しいスクロールペインにテーブルを追加して、モデルが変更されるたびにパネルに再度追加する必要はありません。

于 2009-06-25T20:58:56.570 に答える
1

データをスワップアウトして選択範囲を削除する場合(インデックスが異なるため)、選択範囲を再計算してプログラムで設定する必要があります。

私の経験では、これが私がAbstractTableModel自分のTableModelインターフェースをゼロから拡張したり、正しく実装したりする傾向がある理由です。ここのようにバッキングデータ参照を変更すると、常に100万の問題が発生します。

于 2009-06-25T20:36:54.773 に答える
1

多分使ってみてください

super.setDataVector(Vector dataVector、Vector ColumnNames);

javax.​swing.​table.​DefaultTableModel
public void setDataVector(Vector dataVector, Vector columnIdentifiers)

JavaDocから

現在のdataVectorインスタンス変数を新しい行のベクトルdataVectorに置き換えます。各行は、dataVectorでオブジェクト値のベクトルとして表されます。columnIdentifiersは、新しい列の名前です。columnIdentifiersの名は、dataVectorの列0にマップされます。dataVectorの各行は、Vectorが長すぎる場合は切り捨てるか、短すぎる場合はnull値を追加することにより、columnIdentifiersの列数に一致するように調整されます。dataVectorにnull値を渡すと、不特定の動作が発生し、例外になる可能性があることに注意してください。パラメータ:dataVector-新しいデータベクトルcolumnIdentifiers-列の名前

于 2009-06-25T21:06:56.460 に答える
0

JTableを並べ替えるときは、JTableの現在のインデックスではなく、データのTableModelの元のインデックスを追跡する必要があります。視覚的にはテーブルがシフトしている可能性がありますが、基になるデータモデルはシフトしていません。

于 2009-06-25T20:35:03.857 に答える
0

選択を変更すると失われるように聞こえます。

「getSelectedRow()」は、モデルを変更する「前」に何かを返しますか?

その場合は、そのインデックスを保持し、モデルを変更してから、そのインデックスを再度設定します。

おそらく、そのためにカスタムListSelectionModelを使用する必要があります

于 2009-06-25T20:40:22.473 に答える
0

私が考えたもう1つのことはtable= new JTable(model);、変数'table'が参照しているテーブルを変更する場合ですが、それによって新しいテーブルが自動的にレンダリングされない場合があります。

テーブルがScrollPane内に含まれている場合は、ScrollPane.setViewportView(table);

于 2009-06-25T21:40:18.950 に答える
0

getSelectedRow()に対して常に-1を取得するという同じ問題がありました。問題は今までに解決された可能性があります。それにもかかわらず、私の問題を修正したコードを投稿します:

final int selectedRowIndex = table.rowAtPoint(mouseEvent.getPoint());
final int modelRowIndex = table.convertRowIndexToModel(selectedRowIndex);
于 2012-10-01T09:24:07.770 に答える