MouseMotionListener#mouseDragged() in großen Abständen

Status
Nicht offen für weitere Antworten.

hupfdule

Top Contributor
Also mein Problem ist folgendes. Ich habe einen MouseMotionListener, der auf Draggingbewegungen in einer JTable hört. Allerdings ist beim Draggen eine deutliche Verzögerung spürbar. Da die mouseDragged() Methode einige Berechnungen anstellt, dachte ich, dass diese zu langsam ablaufen würden. Ein Test hat allerdings gezeigt, dass dem nicht so ist. Nach einigen Tests mittels System.currentTimeMillis() wird die gesamte mouseDragged() Methode in weniger als einer Millisekunde abgearbeitet. Das erscheint mir zwar etwas sehr wenig, aber selbst wenn es 10ms sind, dürfte eine solche Verzögerung doch eigentlich nicht spürbar sein.

Ich habe daher mal getestet, in welchen Abständen die mouseDragged-Methode aufgerufen wird, und da ist das Bild schon ein anderes. In knapp 300 Durchläufen (also während eines einzigen Drag-Vorgangs) wurde mouseDragged in 131 Fällen 156ms nach dem vorigen Aufruf abgearbeitet (zwischen zwei Aufrufen lagen 156ms). In 52 Fällen war der Abstand 157ms. Alle anderen Zeiten wurden weniger als 30 mal erreicht und weisen eine große Spannbreite auf (0 bis 266 ms).

(Ich hoffe das war soweit halbwegs klar, was ich meine.)

Meine Frage nun:

Woher kann diese große Verzögerung resultieren? Die Abarbeitung der Methode selbst geht ja deutlich schneller. Wo könnte ich ansetzen, um hier den Flaschenhals zu finden?
 

hupfdule

Top Contributor
Es wird tatsächlich zum Draggen verwendet. ;-)

Also genauer gesagt, kann man Zellen der Tabelle an andere Positionen der Tabelle ziehen. Das kann sowohl mit einzelnen, als auch mehreren Zellen erfolgen. Um dem Benutzer zu zeigen, wo denn diese Zellen nun fallen gelassen werden, markiere ich diese auf der Tabelle (in Form eines Rectangle2D, das um die betreffenden Zellen gezeichnet wird). Aus verschiedenen Gründen (Markierung der Drop-Position, Einschränkung der Selektionsmöglichkeiten, Funktionsaufruf beim Droppen, etc.) habe ich dafür nicht die DnD API von SUN benutzt, sondern alles über einen MouseListener und MouseMotionListener gemacht.

Das Problem ist nun, dass beim Ziehen der Marker etwas "hinterher hinkt". Er wird nicht schnell genug gezeichnet. Daher dachte ich, dass meine ganzen Berechnungen vlt. zu lange brauchen. Das scheint aber eben nicht der Fall zu sein.
 

hupfdule

Top Contributor
Ich habe die JTable abgeleitet und dort die paint(Graphics) Methode überschrieben:

Code:
 public void paint(Graphics g){
        super.paint(g);
        if (marker != null){
            if (fill){
                ((Graphics2D)g).fill(marker);
            }else{
                ((Graphics2D)g).draw(marker);
            }
        }
    }

Der Marker ist wie gesagt ein Rectangle2D und vor dem Aufruf von table.repaint() gesetzt. Dass diese das Problem ist, vermute ich eher nicht, denn dann müsste doch die mouseDragged(MouseEvent) Methode insgesamt länger brauchen, denn dort rufe ich den entsprechenden Code auf:

Code:
public void mouseDragged(MouseEvent e) {
           [...]           
            
           if (this.currently_pressed_button == e.BUTTON1 && this.is_in_drag_mode && !isNothingSelected()){
                [...]
                
                if (isValidDropTarget(e)){
                    lastDropMarker= markDropTarget(e, lastDropMarker);
                    setCursor(DragSource.DefaultMoveDrop);
                }else{
                    setCursor(DragSource.DefaultMoveNoDrop);
                    lastDropMarker= null;
                    removeMarkers();
                }
        }

Der Aufruf table.repaint() passiert in markDropTarget(). Daher sollte das Zeichnen des Markers selbst ja auch in diesem Thread ablaufen. Wenn das also zu lange dauern würde, müsste doch die gesamte mouseDragged(MouseEvent) Methode sehr lange brauchen. Was sie ja offenbar nicht tut...
 

hupfdule

Top Contributor
Hab meine Messung noch mal gemacht mit System.nanoTime. Die Ergebnisse stehen unten. Jede Messung ist ein Durchlauf der gesamten mouseDragged(MouseEvent) Methode. Zeilen mit "L:" bezeichnen die Laufzeit der Methode (also wie lange es gedauert hat, bis die Methode abgearbeitet war), Zeilen mit "D:" bezeichnen die Differenz vom Ende des letzten mouseDragged(MouseEvent) Aufrufs, bis zum Beginn des nächsten.

Code:
L: 26798378
D: 256736
L: 217346
D: 81998411
L: 340267
D: 104986807
L: 278806
D: 109113030
L: 715454
D: 108650401
L: 369041
D: 109004916
L: 323504
D: 109039557
L: 333841
D: 109055760
L: 331048
D: 109120293
L: 458438
D: 108869982
L: 332166
D: 109014413
L: 321550
D: 109059112
L: 331048
D: 109071963
L: 328533
D: 109197398
L: 308978
D: 108908255
L: 305346
D: 109064700
L: 317638
D: 109134261
L: 350045
D: 108965804
L: 500902
D: 108868864
L: 318476
D: 109061348
L: 324622
D: 109079226
L: 323505
D: 109030338
L: 326019
D: 109076433
L: 316521
D: 113331442
L: 315962
D: 104810528
L: 316521
D: 109088166
L: 338032
D: 109022236
L: 309536
D: 109039836
L: 431061
D: 108954909
L: 314565
D: 109061347
L: 327416
D: 109053525
L: 322946
D: 109036763
L: 310934
D: 109102972
L: 323784
D: 109119735
L: 312051
D: 108969715
L: 311771

Ziemlich klar zu sehen ist, dass (außer am Anfang) die Zeit zwischen zwei Aufrufen deutlich größer ist, als die Zeit, die zur Abarbeitung der Methode nötig ist.
 

André Uhres

Top Contributor
Ich denke "paint" zu überschreiben ist in diesem Fall nicht die beste Wahl.
Versuch's mal so:
Code:
...
    private Rectangle rect2D = new Rectangle();
    private int w = 100;
    private int h = 40;
...
    private final void paintBorder(JTable table, Point pt) {
        //letztes Rechteck löschen:
        table.paintImmediately(rect2D.getBounds());
        //Rahmen malen:
        table.getGraphics().drawRect((int) pt.getX() ,(int) pt.getY(), w-1, h-1);
        //neues Rechteck setzen:
        rect2D.setRect((int) pt.getX(),(int) pt.getY(), w, h);
    }
...    
    private void jTable1MouseDragged(java.awt.event.MouseEvent evt) {
        paintBorder(jTable1, evt.getPoint());
    }
...
 

hupfdule

Top Contributor
Tatächlich. Es ist spürbar (und messbar) schneller. Ich danke dir!

Mein Denkfehler war vermutlich, dass ja der EventDispatcherThread mit dem Neuzeichnen der Tabelle beschäftigt ist und daher so lange brauch, bis mouseDragged erneut aufgerufen wird.
Mit deiner Variante dauert das Zeichnen natürlich nicht so lange, weil ja nur kleine Bereiche der Tabelle neu gezeichnet werden müssen.

Also noch mal: Besten Dank für deine Hilfe :)
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M mouseDragged im MouseMotionListener AWT, Swing, JavaFX & SWT 1
J mouseDragged und MouseMotionListener AWT, Swing, JavaFX & SWT 3
Arif Swing MouseMotionListener liefert falsche Werte ? AWT, Swing, JavaFX & SWT 7
L JComponent und MouseMotionListener AWT, Swing, JavaFX & SWT 2
javampir MouseMotionListener rechte Maustaste AWT, Swing, JavaFX & SWT 4
D Swing Objekte bewegen mit MouseMotionListener AWT, Swing, JavaFX & SWT 4
C MouseMotionListener AWT, Swing, JavaFX & SWT 5
C MouseMotionListener fired keine Events mehr wenn in Button AWT, Swing, JavaFX & SWT 2
B MouseMotionListener stotterhafte Ausführung AWT, Swing, JavaFX & SWT 2
M MouseListener/MouseMotionListener AWT, Swing, JavaFX & SWT 2
F AWT MouseMotionListener e.getButton() ist immer 0 unter Linux und Windows AWT, Swing, JavaFX & SWT 6
T MouseMotionListener außerhalb von Frame AWT, Swing, JavaFX & SWT 3
S MouseMotionListener AWT, Swing, JavaFX & SWT 7
M MouseMotionListener oder mouseListener AWT, Swing, JavaFX & SWT 6
J Problem mit eigener Titelleiste und MouseMotionListener AWT, Swing, JavaFX & SWT 2
M Java, Swing: MouseMotionListener AWT, Swing, JavaFX & SWT 19
F MouseMotionListener und Parameter? AWT, Swing, JavaFX & SWT 4
B MouseMotionListener zu träge? AWT, Swing, JavaFX & SWT 3
L MouseMotionListener AWT, Swing, JavaFX & SWT 2
N "globaler" MouseListener (+MouseMotionListener) AWT, Swing, JavaFX & SWT 4
K MouseMotionListener zu lahm? AWT, Swing, JavaFX & SWT 3
M JavaFX javafx mousedragged klappt nicht AWT, Swing, JavaFX & SWT 2
Z Bildervorschau, MouseDragged das Bild verschieben AWT, Swing, JavaFX & SWT 1
S 2D-Grafik MouseDragged Linien zeichnen AWT, Swing, JavaFX & SWT 4
P JFrame manuell Grösse verändern durch 'mouseDragged' AWT, Swing, JavaFX & SWT 3
R Swing Verschieben eines jButtons mittels MouseDragged AWT, Swing, JavaFX & SWT 4
Landei Swing MouseDragged auf Containerebene? AWT, Swing, JavaFX & SWT 7
H Ich kann MouseDragged nicht abfangen AWT, Swing, JavaFX & SWT 3
R JLayeredPane - Drag&Drop - mouseDragged AWT, Swing, JavaFX & SWT 6
G Scrollen per mouseDragged (JScrollPane) AWT, Swing, JavaFX & SWT 8
M gezeichnete Punkte dynamisch verschieben mit mousedragged AWT, Swing, JavaFX & SWT 4
P JDialog mit mouseDragged(), verschieben ? AWT, Swing, JavaFX & SWT 14
L JavaFX Gridpane mit gleich großen Spalten AWT, Swing, JavaFX & SWT 23
E JavaFX Sehr viel und unterschiedlich Großen Inhalt auf einer "Fläche" ... Umsetzbar ? AWT, Swing, JavaFX & SWT 3
S Bilddatei kopieren, aber ohne verluste und ohne zu großen Speicherverbrauch AWT, Swing, JavaFX & SWT 17
G JList mit einer großen Anzahl an Einträgen AWT, Swing, JavaFX & SWT 15
S Buttons mit großen Icon AWT, Swing, JavaFX & SWT 7
R Kleine Panels auf einem großen Panel frei platzieren AWT, Swing, JavaFX & SWT 11
A Probelme mit großen BufferedImage in paintComponent AWT, Swing, JavaFX & SWT 7
S GridLayout mit sehr großen Abständen AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben