1

私は一周してきましたが、誰も私に答えを持っていないようです。JPanel実行中にラベルを追加/削除する場所があります。問題は、新しいラベルを追加するたびに、新しいラベルがrevalidate()表示されるようにする必要があることです。毎回revalidate()、非常に迷惑なちらつきが発生し、すべてのラベルがウィンドウの上部まで1ミリ秒間ゴーストしてから、元の状態に戻ります。電話をかけるのrevalidate()は、ラベルを追加した後だけです。塗装方法を変えないか、何も変えなかった

public void paintComponent(Graphics page)
{
    super.paintComponent(page);
}

私のページが悪く見えないように。私は本当にこれにいくつかの助けを使うことができました。JFrameJlabelとゲームを使って小惑星ゲームを作りましたJpanel。それはうまく機能しますが、このちらつきとコンポーネント「パネルの上部にすばやくゴースティングする」は耐え難いものであり、これがrevalidate()方法であることは事実です。

4

4 に答える 4

2

具体的な例として、Asteroidsちらつきはまったくありません。ここにいくつかの理由があります:

  • イベントディスパッチスレッドで実行されます。

  • JPanelデフォルトでダブルバッファリングされているを使用します。

  • を使用してアニメーションのペースを調整しjavax.swing.Timer、でゲームのモデルを更新しactionPerformed()ます。

  • をオーバーライドしますが、アクションリスナーがパネル全体を再描画するため、paintComponent()安全に省略できます。super.paintComponent()

  • リスナーはpaintImmediately()、潜在的な遅延を回避するために呼び出します。repaint()プラットフォームに違いがあるかどうかを確認するために代用してください。

補遺:この反例に示されているように、revalidate()ちらつきは発生しません。ラベルを置き換える代わりに、次に示すように、ラベルのアイコンを更新します

于 2013-02-16T14:17:51.707 に答える
2

Swingコンポーネントのフィルカリングで問題が発生したとき、それは並行性の問題であることが判明しました。あなたはゲームをしているので、それはあなたがアニメーションをしていることを意味します、それはここに当てはまるかもしれません。

からのみSwingコンポーネントを変更するように注意してくださいAWT-EVENT thread。を使用するSwingUtilities.invokeLaterか、を使用してアニメーションを実行しますjavax.swing.Timer

于 2013-02-16T10:51:24.503 に答える
2

それらを再利用することを検討しましたか?つまりsetVisible(false)、不要なときに使用しますか?

ラベルを追加および削除することが、ゲームに必要なことを達成するための最良の方法であるかどうかはわかりません。個人的には自分で絵を描いてみたいと思います。

于 2013-02-16T14:37:37.790 に答える
2

ラベル(または通常はGUIコンポーネント)を使用して、すばやくアニメーション化され、動的に作成/移動されるオブジェクトを表すことは実用的ではありません。車を使って居間から台所まで運転するようなものです。

Swingコンポーネントには多くの優れた機能があります。たとえば、必要なスペースを決定でき、レイアウトマネージャーはそれを使用して自動的に適切に配置できます。残念ながら、ゲームの場合、すべての優れた機能は必要ありません。また、それに伴う処理オーバーヘッドを支払う必要もありません。各コンポーネントにピアコンポーネントがあることを義務付けるスイングマルチプラットフォーム機能によって、問題はさらに複雑になります(ピアはコンポーネントをアクティブな外観にレンダリングすることを処理します)。

これを解決するために、個々のゲームオブジェクトをスイングコンポーネントとして表現しません。代わりに、単一のスイングコンポーネント(通常はJPanel)をキャンバスとして使用して、ゲームオブジェクトをペイントします。そのJPanelに対して定期的に(たとえば、1秒間に30回または60回)repaint()を呼び出すだけです。もちろん、JPanelのpaintComponent()をオーバーライドして、独自のコードを使用してすべてのゲームオブジェクトをペイントします。

編集:独自のレンダリングを行う方法の概要を説明します

ゲーム関連のオブジェクトを整理する方法を決定する必要があります。非常に単純なスケルトンは次のようになります(ゲッター/セッターは省略)。

public class GameObject {
    public int x;
    public int y;
    public Image image;
}

実際には、このクラスには追加のメンバーがあります(オブジェクトの移動方法を制御する動作や、アニメーションのいくつかの状態/カウンターなど)。また、可能な動作(船、小惑星、弾丸など)ごとに具体的なサブクラスを使用して抽象化することもできます。GameObjectのすべてのインスタンスは、ある種のコレクションで管理されています。リストを使用していると思います。

paintComponentを実装する場合、リストをループして各オブジェクトの画像をレンダリングするだけです。

public void paintComponent(Graphics g) {
    List<GameObject> list = ... // however you obtain it in your game
    for (GameObject gobject : list) {
        g.drawImage(gobject.image, gobject.x, gobject.y, (ImageObserver) null);
    }
}

より精巧なゲームは、ゲームオブジェクトが互いにどのように重なり合うかを制御するためにゲームオブジェクトを注文する場合があります。しかし、原則として、その信じられないほど単純です。

于 2013-02-16T15:18:07.560 に答える