1

AbstractTableModelカスタム、、、TableCellEditorおよびを作成する必要がある最初のJTableを作成していますDefaultTableCellRenderer。以前にこれらを作成する必要がなかったことを考えると、テーブルを希望どおりに動作させるために、かなりの進歩を遂げました。

しかし、私はオーバーライドしているさまざまな方法すべてに圧倒されており、特定のセルのImageIconを変更する方法を見つけようとして車輪を回しています。 セルにはJLabelが含まれている必要があります。これ ImageIcon には、とテキスト文字列の両方が必要です。私はすでにイニシャルを設定できますがImageIcon(おそらく間違って行っていますが)、更新されたを設定することはできませんImageIcon。失敗することはありませんが、変更は行われません。

一般的な意味で、これらのモデル、エディター、およびレンダラーのすべてがすでにインスタンス化されていると仮定して、アイコンを取得してのJLabelセルに設定するための最良の方法は何ですか?JTable

JLabel.class私のモデルは、疑問に思っている場合は、これらのセルに戻るようにすでに定義されています。またfireTableCellUpdated(row, col)、変更が行われたと思われる場合は、これも行います。System.out.println(getIcon())更新の前後に行うと、ソースが変更されていることさえわかります。

コードの一部を次に示します(URL / ImageIconの修正で更新されています)

class MonitorTable extends JTable {
   MonitorTableModel model = new MonitorTableModel(rows, columnNames);
   setModel(model);
   ...
   public void setIconAt(ImageIcon icon, int row, int col) {
      model.setIconAt(icon, row, col);
   } // End setIconAt(ImageIcon, int, int)
   ...

   class MonitorTableModel extends AbstractTableModel {
      ...
      public void setIconAt(ImageIcon icon, int row, int col) {
         StatusTableCellRenderer cell =
            (StatusTableCellRenderer)getColumnModel().getColumn(col).getCellRenderer().
            getTableCellRendererComponent(myTableObject, null, false, false, row, col);

         System.out.println(cell.getIcon()); // Shows initial icon source
         cell.setIcon(icon);
         fireTableCellUpdated(row, col);     // Should update the table
         System.out.println(cell.getIcon()); // Shows new icon source
         System.out.println("Cell updated");
      } // End setIconAt(ImageIcon, int, int)
   } // End class MonitorTableModel

   public class StatusTableCellRenderer extends DefaultTableCellRenderer {
      public Component getTableCellRendererComponent(JTable table, Object value,
         boolean isSelected, boolean hasFocus, int row, int col) {

         setIcon(imgGray);
         setText((String)value);
         return this;
      } // End getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
   } // End class StatusTableCellRenderer
} // End class MonitorTable
4

3 に答える 3

3

私のモデルは、これらのセルに対して JLabel.class を返すようにすでに定義されています。

しかし、レンダラーのコードによると、これらのセルには String 値が必要です。

setText((String)value); 

あなたの setIcon() メソッドが好きではありません。URL は渡しません。アイコンを渡します。セルがレンダリングされるときにアイコンがメモリに読み込まれていないという問題が発生している可能性があります。

アイコンを取得して JTable の JLabel セルに設定する最良の方法は何ですか?

JLable を TableModel に格納しないでください。Swing コンポーネントをモデルに格納するのはコストがかかるため、Swing コンポーネントはレンダラーを使用します。代わりに、テキストとアイコンの 2 つのプロパティを含む "LabelInfo" のようなカスタム オブジェクトを保存します。次に、カスタム レンダラーがデフォルトのレンダラーを拡張し、super.getTableCellRendererComponent() を呼び出します。その後、オブジェクトにアクセスして、レンダラーのテキスト/アイコン プロパティを保存できます。レンダラーでオブジェクトを作成するべきではありません。

モデルの何かを変更したい場合は、次のようにします。

LabelInfo info = (LabelInfo)table.getValueAt(row, column);
info.setIcon(...);
table.setValueAt(info, row, column);

必要なのはそれだけです。setValueAt(...) メソッドに既に組み込まれているため、セルなどを再描画するためのカスタム コードはありません。あなたのテーブルモデルの。

編集: TableModel でカスタム オブジェクトを使用する簡単な例。

1) オブジェクトをモデルに追加するには、次のようにします。

LabelInfo info = new LabelInfo("some Text", yourIcon);
table.setValueAt(info, row, column);

2) カスタム レンダラーのコードは次のようになります。

class LabelInfoRenderer extends DefaultTableCellRenderer
{
    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        LableInfo info = (LabelInfo)value;
        setIcon( info.getIcon() );

        return this;
    }
}
于 2011-01-19T21:22:15.437 に答える
0

モデルから fireTableDataChanged を呼び出します。

JLabel からも repaint メソッドを呼び出してみてください。

それを行うためのより良い方法は、CellRenderer を実装し、JPanel を返し、paintComponent で draw メソッドを作成することです。ImageIcon の代わりに BufferedImage をロードし、それを使用して JPanel で描画できます。

Renderer を次のように変更してみてください。

public class StatusTableCellRenderer extends DefaultTableCellRenderer {
     public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int col) {
        JLabel comp = new JLabel(new ImageIcon(imgGray));
        comp.setText((String)value);
        return comp;
     } // End getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
  }

これは TableModel を操作する正しい方法ではありません。getValueAt(int row, int col) で画像の URL を返す必要があります。その後、CellRenderer を登録してセルに対応する URL を指定します。クラス。レンダラーは JTable から自動的に呼び出されます。JTable を拡張する必要もありません。レンダラーとモデルを実装するだけで済みます。setIconAt は setValueAt を呼び出して URL を列に配置するだけで、残りはレンダラーが処理します。

于 2011-01-19T20:16:27.217 に答える
0

setIcon(imgGray)に変更することでこれを修正しましたif (getIcon() == null) setIcon(imgGray);

問題は、私のgetTableCellRendererComponent方法が毎回アイコンを imgGray に設定していたことです。「古い」値が(再)設定された後に「新しい」アイコン値が処理されたにもかかわらず、setIconAtを呼び出す私のメソッドは明らかにオーバーライドされていました。getTableCellRendererComponent

最終的にすべてのメソッドを削除しsetIcon、関連するロジックをStatusTableCellRendererクラスに移動しました。このようにして、セルの値を渡し、レンダラーがその値に基づいてアイコン設定を行うようにします。この方法はより理にかなっていて、美しく機能します。初期設定とその後のアップデートは全て想定通りに動作することを確認しております。

アイコンを設定するロジックは非常に単純です。事前定義された特定のしきい値に基づいて、事前定義されたアイコンを設定します。

double val;
if (getIcon() == null) setIcon(imgGray);       // Initialize
if ((value == null) || (value == "")) {
   val = 0;
} else {
   val = Double.parseDouble(value.toString());
} // End if

if (val <= THRESHOLD1) {
   setIcon(icon1);
} else if (val <= THRESHOLD2) {
   setIcon(icon2);
...
} // End if
setText(value.toString());

JLabelデフォルトがまさに私が必要としていたものであったときに、使用する新しいオブジェクトを作成するための提案について非常に心配していました。これは不必要であり、パフォーマンスに影響を与える可能性がありましたJTable。皆様のご理解とご協力に感謝いたします。これは私をバタバタさせていました!

于 2011-01-19T22:06:29.670 に答える