2011-01-19 13 views
1

カスタムAbstractTableModel,TableCellEditorおよびDefaultTableCellRendererを作成する必要がある最初のJTableを作成しています。以前はこれらを作成する必要がなかったので、テーブルを必要に応じて動作させるためにいくつかの重要な進歩を遂げました。JTableセルのImageIconを更新します

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

JTableJLabelセルにアイコンを取得して設定する最も良い方法は、これらのモデル、エディタ、およびレンダラーのすべてが既にインスタンス化されているとします。

あなたの疑問に思うのであれば、私のモデルはすでにJLabel.classを返すように定義されています。変更が行われたらfireTableCellUpdated(row, col)とします。アップデート前とアップデート後にSystem.out.println(getIcon())を実行すると、ソースが変更されたことがわかります。

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 

答えて

0

は私がsetIcon(imgGray)を変更することで、これを固定

1)あなたのような何かをモデルにオブジェクトを追加しますif (getIcon() == null) setIcon(imgGray);

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

すべての私の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にヒットしました。あなたの洞察と助けに感謝します。これは私をひどく運転していた!

+0

setIconAt(...)メソッドは決してgetTableCellRenderer(...)を呼び出すべきではありません。これは適切な解決策ではないため、まだ問題が残っています。あなたが常にあなたが掲示したコードで定義されていないimgGrayアイコンになるように割り当てるので、すべてのセルについて同じアイコンが表示されます。すべてのセルに異なるアイコンが必要な場合は、アイコンをモデルに保存する必要があります。早く簡単な解決策を教えてくれました。 – camickr

0

コールモデルからfireTableDataChanged:

は、ここで(代わりにURL /イメージアイコンの修正と更新)コードの一部です。

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

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

てみチェンジ:あなたは、いくつかの混乱を行っている

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型の行で画像のURLを返す必要があり、 int col)、その後、URL.classを持つセルに対応するようにCellRendererを登録します。レンダラーはJTableから自動的に呼び出され、JTableを拡張する必要はありません。レンダラーとモデルを実装するだけで済みます。 setIconAtはsetValueAtを呼び出し、URLに列を置くだけで、レンダラーは残りの部分を処理します。

+0

私はすでに 'fireTableCellUpdated(row、col)'を起動しています。私はもう少し質問を更新します。 –

+0

JLabelで再描画しようとしました –

+0

私は試しましたが、変更はありません。とにかく 'fireTableCellUpdated(row、col)'はそれを処理する必要があります。前にJTablesを使ったことはありませんでした。アー! –

3

私のモデルはすでに、これらの細胞のためのJLabel.classを返すように定義された

しかし、あなたはこれらの細胞中の文字列値を期待して、あなたのレンダラのコードによるとされています

setText((String)value); 

あなたのsetIcon()メソッドが嫌いです。私はURLを渡しません。私はアイコンを渡します。おそらく、セルがレンダリングされるときにアイコンがメモリに読み込まれていないという問題があります。

あなたはTableModelの中JLableを保存しないでください

、JTableののJLabelのセルにアイコンを取得および設定するための最良の方法ものです。 Swingコンポーネントをモデルに格納するのは高価です。そのため、Swingコンポーネントはレンダラーを使用します。代わりに、 "LabelInfo"のようなカスタムオブジェクトを格納します。このオブジェクトには、テキストとアイコンの2つのプロパティが含まれています。次に、カスタムレンダラーがデフォルトレンダラーを拡張し、super.getTableCellRendererComponent()を呼び出します。その後、オブジェクトにアクセスしてレンダラーのテキスト/アイコンのプロパティを保持することができます。レンダラーにオブジェクトを作成しないでください。今

あなたが行うことができますモデルで何かを変更したい:あなたが必要とするすべてのthats

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

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

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

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; 
    } 
} 
+0

あなたの最初の点は意味がありますが、すでに動作しています。 'JLabel'のテキストを設定して更新し、初期アイコンを設定することができます。たぶん私はそこに何かが欠けているだけかもしれない。第二に、あなたはURLの代わりにアイコンを渡すことについて完全に正しいです、そして、私はこれを動作させたら、それを修正する予定でした。第三に、私はテーブルに何かを格納しようとしていない、私はあなたが記述したように2つのプロパティを持っていたい。 LabelInfoオブジェクトの概要を拡張、実装、またはインスタンス化すると、どのような意味がありますか? –

+0

LabelInfoオブジェクトは、テキストプロパティとアイコンプロパティの2つのgetter/setterを持つ単純なクラスです。次に、デフォルトのレンダラーがその値を表示するようにテキストを返すtoString()メソッドを追加できます。カスタムレンダラでは、このクラスからアイコンを取得してレンダラに追加します。 – camickr

+0

それは興味深いコンセプトですが、私は運転したくない複雑な道です。 'DefaultTableCellRenderer'は私のニーズのほとんどすべての機能を持っています。' String'と 'ImageIcon'を設定する機能です。問題はアイコンをどのように設定したかということでした。クラスの外から呼び出すのではなく、そのクラスの拡張の中でアイコン設定ロジックを移動したところ、正しく動作しました。しかし、努力してくれてありがとう、あなたは私の仕事のための適切な答えを見つけるために私に挑戦しました! –

関連する問題