web-dev-qa-db-ja.com

Java Swing revalidate()vs repaint()

JPanelのコンテンツを頻繁に置き換えるSwingアプリケーションを作成しています。これを行うには、removeAll()を呼び出してから、新しいコンテンツを追加して、revalidate()を呼び出します。

ただし、古いコンテンツは実際にはまだ表示されていることがわかりました(ただし、新しいコンテンツによって不明瞭になっています)。 repaint()に加えてrevalidate()への呼び出しを追加すると、期待どおりに動作します。

私が経験した他の機会では、revalidate()を呼び出すだけで十分であると確信しています。

したがって、基本的に私の質問は-両方の関数を呼び出す必要があり、そうでない場合、それぞれをいつ呼び出す必要がありますか?

204
William

repaint()およびrevalidate()を呼び出す必要があります。前者は、Swingにウィンドウの領域が汚れていることを伝えます(removeAll()によって削除された古い子供の画像を消去するために必要です)。後者は、レイアウトを再計算するようにレイアウトマネージャーに指示します(これはコンポーネントを追加するときに必要です)。これにより、パネルのchildrenが再描画されますが、パネル自体が再描画することはありません( this を参照してください再描画トリガーのリスト)。

より一般的な注意事項として、元のパネルを再利用するのではなく、新しいパネルを作成して親で交換することをお勧めします。

153
kdgregory

Remove()またはremoveAll()を実行するたびに、呼び出す必要があります

  validate();
  repaint();

新しいコンポーネントのadd()を完了した後。

Remove()を実行する場合、validate()またはrevalidate()の呼び出しは必須です-関連するjavadocsを参照してください。

私自身のテストでは、repaint()も必要であることが示されています。正確な理由はわかりません。

82
Noel Grandin

revalidatename__は、新しいコンポーネントが追加されるか、古いコンポーネントが削除されると、コンテナで呼び出されます。この呼び出しは、新しいコンポーネントリストに基づいてリセットするようレイアウトマネージャーに指示する命令です。 revalidatename__は、コンポーネントが「ダーティリージョン」と考えるものを再描画するための呼び出しをトリガーします。 JPanelname__のすべての領域がRepaintManagername__によってダーティと見なされるわけではありません。

repaintname__は、コンポーネントに自分自身を再描画するよう指示するために使用されます。多くの場合、自分のような条件をクリーンアップするためにこれを呼び出す必要があります。

58
akf

revalidate()はコンテナのレイアウトを要求するだけで、単にrevalidate()の呼び出しを経験したときに、子コンポーネントの境界の更新が原因で、再レイアウト中に境界が変更されたときにrepaint()がトリガーされます。あなたが言及した場合、コンポーネントのみが削除され、コンポーネントの境界は変更されません。この場合、repaint()"accidentally"トリガーされません。

3
Antony Ng