TableCellRenderer でのカスタム Swing JComponent の使用
-
21-08-2019 - |
質問
OK、簡単なカスタム JComponent を作成する方法はわかりました。TableCellRenderer をオーバーライドする方法を知っています。この2つを組み合わせることはできないようです。
こちらがサンプルです JComponent
わたしは作った:
public static class BarRenderer extends JComponent
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
this.xmin=xmin;
this.xmax=xmax;
}
@Override protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.drawRect(r.x, r.y,
(int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
}
public void setXval(double x) {
this.xval = x;
repaint();
}
public double getXval() { return xval; }
}
スタンドアロンの JComponent として正常に動作します。電話する setXval(something)
そしてそれは問題なく更新されます。(編集:データを定期的に更新するスイング タイマーを使用しています)
ただし、このコンポーネントが TableCellRenderer.getTableCellRendererComponent() で返すものである場合、問題のセルをクリックしたときにのみ再描画されます。何が与えますか?本当に単純なことを省略しているに違いありません。
解決
は、パフォーマンス上の理由からJTableは、複数のセルをペイントするレンダラコンポーネントを再利用する - あなたはJTableのコンポーネントを見るときに、それが位置に存在するコンテナコンポーネントの伝統的な意味では実際に存在しません。これは、レンダリングコンポーネントに再描画()を呼び出すと、何もしないことを意味します。
最も効果的なオプションは、あなたのTableModelにあるバーの整数値を格納することです。あなたのTableCellRendererを、次に、このようになります:
public class BarTableCellRenderer implements TableCellRenderer {
private final BarRenderer rendererComponent = new BarRenderer(0, 10);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
rendererComponent.setXval((Integer)value);
return rendererComponent;
}
}
そして、あなたはTableModelの整数を変更することができますし、それは(あなたが使用しているのTableModelの実装に依存しTableModel.fireTableCellUpdatedが必要な場合があります)バーの再描画をトリガします。
他のヒント
あなたたち (Russ Hayward と Andrew) の二人が協力してくれました。重要なのは、基本的に次のことを行うことでした。
- 表示される状態をレンダラーではなく TableModel 自体に保存します。
- TableModel の状態が変化したときに、
fireTableCellUpdated()
と呼ばれます - しか持っていない 1つ TableCellRenderer オブジェクトと 1つ カスタム列の JComponent (セルごとに 1 つではありません)
- 内で
TableCellRenderer.getTableCellRendererComponent()
直後にレンダリングする目的でセルの状態を保存します (長期保存は TableModel にあります)。 - その状態を JComponent に提供します
- JComponentを返す
- オーバーライド
JComponent.PaintComponent()
- 内で
- 便利な可能性の 1 つは、カスタム レンダラーが JComponent を拡張して TableCellRenderer を実装することです。
TableCellRenderer.getTableCellRendererComponent()
セルの状態を保存し、return this;
これは、現在機能するコードの関連する抜粋です。
class TraceControlTableModel extends AbstractTableModel {
/* handle table state here */
// convenience method for setting bar value (table model's column 2)
public void setBarValue(int row, double x)
{
setValueAt(x, row, 2);
}
}
// one instance of BarRenderer will be set as the
// TableCellRenderer for table column 2
public static class BarRenderer extends JComponent
implements TableCellRenderer
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
super();
this.xmin=xmin;
this.xmax=xmax;
}
@Override protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.drawRect(r.x, r.y,
(int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
}
@Override
public Component getTableCellRendererComponent(JTable arg0,
Object value,
boolean isSelected, boolean hasFocus,
int row, int col)
{
// save state here prior to returning this object as a component
// to be painted
this.xval = (Double)value;
return this;
}
}
は、異なるXVALをそれぞれ有するが、それは最初に、各セルを意味する別の見ているバーがあり、正しくレンダラのでしょうか?
あなたはそれはあなたがそれをクリックしない限り、再描画しないと言うとき、何かが変化するデータを視覚的に表示(レンダリングバー)を引き起こしている必要がありますあなたの基礎となるデータに起こっていますか?
データが変更されますが、テーブルはimmediatley再描画されない場合は、、その後、私はあなたのTableModelが正常に動作していないと言うでしょう。
データの変化の根底にある - >するTableModelの変更 - > TableModelEventを発射 - > JTableの再描画
はTableModel tuturialを見てください:のhttp:/ /java.sun.com/docs/books/tutorial/uiswing/components/table.html#dataする
あなたが正しいすべてをやっていることを確認する。