Java SwingのmouseDragged
メッセージMouseMotionListener
のコールバックスピードに関する質問があります。 This postは関連性がありますが、全く同じではありませんので、私自身の質問を始めました。Java Swing mouseDraggedコールバックスピード
私は、基本的にデジタル化されたTCG(トレーディングカードゲーム)エミュレータである商業的流通を目の当たりにしていない小さな社内アプリケーションを作っています。 MtG(Magic the Gathering)に精通している人なら、そのようなプログラムから聞いたことがあります。私はthisのように見えるものを作成しようとしていますが、それほどファンシーはありません。
私のGUIは、メニュー付きのJFrameと、さまざまなボタンとラベルを含むパネルで構成されていますが、私は問題を説明するために関連する部分のみを扱います。本質的には
、私はいつでもあなたがプレイすることができ、あなたの手札のカードを示し、その中にJList
とのことでJScrollPane
、と、左側にJPanel
と垂直分割JSplitPane
を使用しています。分割の右側には、DEFAULT_LAYER
のサブ画像(のサブクラスは画像を追加するためにdraw
の機能を上書きします)があり、PALETTE_LAYER
の上のさまざまなレイヤーに、再生中のカードが表示されます。JLayeredPane
カスタムCardPanel
(カードを示すJPanel
の別のサブクラス)によって(ArrayList
に集められた) JLayeredPane
全体は、あなたがすでにプレイしたすべてのカードを使ってあなたの前のテーブルを表しています。
私が最初に周りのカードを移動するためにマウスドラッグイベントを使用し、その後、イベントを拾う私はマウスプレスを登録することができ、これはカード上であったかどうかを確認するためにJLayeredPane
にMouseListener
とMouseMotionListener
を添加することにより開始し、最後にそれを戻すためのマウスリリース。これはすべて正常に動作し、ロギング情報を追加すると、mouseDragged
のコールバック関数が頻繁に呼び出されることがわかり、視覚的に速くドラッグすることができます。
今日私はJList
のカードをダブルクリックするのではなく、手札からカードを「テーブル」にドラッグできるように機能を追加することにしたので、JList
に適切なリスナーを追加しましたMousePressed
とMouseReleased
のようないくつかの関数を埋めています。マウスを押すと、リストのどのカードがクリックされたかを確認し、リストをロックしてカスタムCardPanel
を作成します(ただし、まだどこにも追加しないで、割り当てて起動します)。ドラッグされたマウスでは、このフラグが設定されているかどうかをチェックします。そうであれば、カーソルの位置を確認します。もしそれがJLayeredPane
の上にあれば、私はCardPanel
をDRAG_LAYER
に加え、別のフラグを設定します。この2番目のフラグがマウスドラッグの連続呼び出しで設定されている場合は、パネルをもう一度追加しませんが、場所を変更するだけです。この機能は、私の以前のマウスドラッグコールバックの機能と実質的に同じです。マウスを離すと、リストのロックが解除され、JLayeredPane
の正しいレイヤーにCardPanel
を追加します。
すべてが意図したとおりに働いているので、私は私のコードは大丈夫ですかなり確信しているが、ちょうど1若干の問題があります:
(代わりの階層ペインから、階層化区画にリストからカードをドラッグするとmouseDragged
コールバックがJList
(1秒あたり約10回)で非常に低い頻度で呼び出され、目に見えない遅延を導入していることがわかりました(ドラッグの最初のケースでは1秒あたり約30回)。
問題を明確にするためにコードスニペットを追加しますが、自分で実行できるようにするためにすべてのコードを追加するのは恐れがあります。
この投稿の主な質問は、mouseDragged
が1つだけ速く呼び出される理由を知っている人は誰ですかMouseMotionListener
よりもMouseMotionListener
よりも速く呼ばれていますか? JLayeredPane
コンポーネントへのリスナーは、高速連続呼び出しを行い、リスナーはJList
への呼び出しが大幅に遅くなります。
注:私はNetbeansで開発しており、組み込みのグラフィカルなSwing Interface Builderを使用しています。私はメインクラスとしてJFrameフォームを使用しています。
public class MyFrame extends JFrame{
...
protected JLayeredPane layeredPane;
protected JList cardsInHandList;
...
...
protected ArrayList<String> cardsInHand;
...
private void attachListeners(){
layeredPane.addMouseListener(new MouseAdapter(){
public void MousePressed(MouseEvent e){
// set a flag, start a drag
}
public void MouseReleased(MouseEvent e){
// unset a flag, stop a drag
}
});
layeredPane.addMouseMotionListener(new MouseMotionAdapter(){
public void MouseDragged(MouseEvent e){
// drag the card around
// gets called a lot!
// actual code:
if (e.getButton() == MouseEvent.BUTTON1) {
if (!dragging) return; // the flag
int x = e.getX() - 10;
int y = e.getY() - 10;
// snap to grid
x /= GRIDX;
x *= GRIDX;
y /= GRIDY;
y *= GRIDY;
// redraw the card at its new location
draggedCard.setLocation(x, y);
}
}
});
cardsInHandList.addMouseListener(new MouseAdapter(){
public void MousePressed(MouseEvent e){
// set a flag, start a drag
}
public void MouseReleased(MouseEvent e){
// unset a flag, stop a drag
}
});
cardsInHandList.addMouseMotionListener(new MouseMotionAdapter(){
public void MouseDragged(MouseEvent evt){
// check cursor location, drag if within bounds of layeredPane
// gets called a whole lot less!! _Why?_
// actual code:
if (!draggingFromHand) return; // the flag
// check location of cursor with own method (contains() didn't work for me)
if (isCursorAtPointAboveLayeredPane(evt.getLocationOnScreen())) {
// calculate where and snap to grid
int x = (int) (evt.getLocationOnScreen().getX() - layeredPane.getLocationOnScreen().getX())-10;
int y = (int) (evt.getLocationOnScreen().getY() - layeredPane.getLocationOnScreen().getY())-10;
// snap to grid
x /= GRIDX;
x *= GRIDX;
y /= GRIDY;
y *= GRIDY;
if(!draggingFromHandCardPanelAdded){
layeredPane.add(draggingFromHandCardPanel, JLayeredPane.DRAG_LAYER);
draggingFromHandCardPanelAdded = true;
} else {
draggingFromHandCardPanel.setLocation(x,y);
}
}
}
});
}
私は、問題を再現短い実行可能な例を構築し、どこかのコードを添付しようとするでしょうが、今の私はskootになりました。事前に
おかげ
PS:私はTransferHandlersとを含む、Javaでドラッグする別の方法があることを認識していますすべてのことを、それはあまりにも多くの手間のように思える、それはへの実際の答えではありません1つのコールバックが他のコールバックよりも多く呼び出されているように見えるので、その代わりに使用するように教えてください。
は多分、私が答えるのは難しい、ウナギの@Hovercraft完全によって多分偉大なポストがためにあなたを助けることができるので4に、質問を分離することを分割参照、グローバルなイベントリスナーを使用してより良い結果を得る可能性があります私がそこに見る15番目の質問の1つ http://stackoverflow.com/search?q=user%3A522444+DragLabelOnLayeredPane – mKorbel