7

チャット プログラムのチャット データを保持するために JList を使用しています。
カスタム リスト レンダラーを使用して、カスタム JPanel オブジェクトを要素タイプとしてレンダリングします。
この JPanel には、2 つの JLabels (名前と時刻用に上部に固定) と 1 つの JTextArea (チャット メッセージ用に下部に固定) が含まれています。

次のようになります。

写真1

すべてうまく機能しますが、非表示/表示機能を追加したいと考えています。
以前にプログラムされた PopupMenu ハンドラーを使用して、要素を右クリックするとポップアップが表示されるようにしました。

pic2

非表示(または表示、トグル)をクリックすると、要素が次のように最小化されます...

pic3

唯一の問題は... JList のセル サイズが更新されないことです。これは、テキストがあった場所に大きな空の領域が表示されるためです。
しかし、別のメッセージを入力すると...

pic4

JList は、「非表示」操作を完了するセル サイズを修正します。
私の質問は、プログラムで JList を再検証/再描画/などする方法です。
そして、私がすべての明白な解決策を試していないとは思わないでください...

public void setHidden(boolean hidden) {
    // this is in the custom JPanel class
    System.out.println("Initial: " + this.getPreferredSize());

    // TextArea is the JTextArea which we set invisible when we want to hide it.
    TextArea.setVisible(!hidden); // TextArea is a variable btw
    this.invalidate();
    this.validate();
    this.repaint();

    System.out.println("After: " + this.getPreferredSize());
    container.revalidate();
}

/*
 * This is what the above printlns show when you hide, then show the element.
 *
 * Initial: java.awt.Dimension[width=176,height=38]
 * After: java.awt.Dimension[width=176,height=20]
 * Initial: java.awt.Dimension[width=176,height=20]
 * After: java.awt.Dimension[width=176,height=38]
 */

public void revalidate() {
    // container.revalidate() ^^^
    // list is the list containing the chat elements
    list.invalidate();
    list.validate();
    list.repaint();
}

カスタム JPanel クラスは、GroupLayout を使用してコンポーネントをレンダリングします。
プログラムで JList にそのセル サイズを再検証させる方法についての知識はありますか?
...私が投稿した方法以外に?:)

解決策:
メソッドを次々と検索し、それらが私の問題を解決するかどうかをテストした後、非表示/表示操作の後にこのコードを実行すると、セルの高さ (および幅) が再計算され、セルの不要な視覚的な「ちらつき」が発生しないことがわかりました。 JList.

list.setFixedCellHeight(0);
list.setFixedCellWidth(0);
list.setFixedCellHeight(-1);
list.setFixedCellWidth(-1);
4

3 に答える 3

3

コードを見ることなく、私は推測することしかできません。最も可能性の高い理由は、リストの足元で非表示を実行していることです。つまり、モデルがリスナーに通知していません。リストのUIデリゲートは、セルサイズを内部にキャッシュします。これは、ListEventsを受信するとクリアされます。

于 2012-02-23T09:58:50.703 に答える
2

JTableこれは、に 2 つの列 (ChatおよびBoolean) がTableModelあり、表示される列のみがある場合のジョブです。トリックは、2 番目の列のみにパラメーターとして設定するRowFilterChatを実装して使用することです(では、 の戻り値でフィルタリングできます) 。String "false"ObjectJTableBooleanString "true" / "false"

于 2012-02-23T07:48:58.613 に答える
0

これはJListクラスの非常に独特な欠点です。無関係な領域でコードの一部をクリーンアップする過程で、私自身がこの問題に遭遇しました。

価値があるのは、要素を から削除してからListModel再度追加すると、JList 内の関連するレンダリングされたコンポーネントに適切な寸法が生成されることです。これは奇妙な方法であり、リストが受け入れられた(そして推奨される)ソリューションと同じように動作するようです。

list.setFixedCellHeight(0);
list.setFixedCellWidth(0);
list.setFixedCellHeight(-1);
list.setFixedCellWidth(-1);

私のプロジェクトのコードはもともと のremoveAllElements()メソッドを呼び出してからListModel、 を使用してすべての要素を 1 つずつ追加するように記述されていたため、この問題に遭遇しましaddElement()た。ユーザーが JList に表示されているコンポーネントの寸法を変更する必要がある場合はいつでもモデルをそのままにしておくようにプログラムを書き直すことにするまで、すべてがうまく機能していました。つまり、要素がリストに追加またはリストから削除されていないため、モデルを含める必要はありませんでした。残念ながら、レンダラーの優先サイズを変更した後は、要素を正しくレイアウトするためのメソッド呼び出しのrepaint()量はありません。私の場合、親コンポーネントのサイズ変更のみ (arevalidate()JListJFrame)意図した動作を生成しました。

于 2014-07-19T18:30:27.830 に答える