SWT MouseWheelListener auf Composite beschränken?

Alan47

Mitglied
Hallo zusammen,

ich bin seit einigen Tagen dabei, mich mit SWT vertraut zu machen (ich habe bislang hauptsächlich mit Swing gearbeitet). Dabei bin ich auf ein Problem gestoßen.

Im Groben schaut mein Fenster aktuell so aus:

2qjdgrt.jpg


Auf dem grau hinterlegten Composite wird ein MouseWheelListener eingehängt (via composite.addMouseWheelListener(...) ). Dieser soll den Inhalt des Composites vergrößern bzw verkleinern wenn der Benutzer das Mausrad bewegt - das funktioniert soweit auch prima.

Allerdings wird dieser Listener immer aufgerufen wenn sich das Mausrad bewegt, und zwar ganz unabhängig davon, wo sich der Mauszeiger gerade befindet.


Meine Frage wäre daher: wie stellt man es in SWT am Besten an, dass ein MouseWheelListener nur dann aufgerufen wird, wenn sich die Maus auf einer bestimmten Komponente der GUI (oder einem ihrer Kinder) befindet?

Versucht habe ich bislang:


Java:
public void onMouseWheel(MouseEvent e){ 
   // schlecht, da es nicht funktioniert wenn der cursor auf einem Kind vom Composite sitzt.
   // funktioniert zumindest teilweise.
   if(getComposite().getDisplay().getCursorControl() == getComposite()){  
       // ändere zoom-level
   }
}

Java:
public void onMouseWheel(MouseEvent e){
   // schlecht, da e.x und e.y relativ zur Component sind die das Event ausgelöst hat.
   // sprich: das funktioniert überhaupt nicht.
   if(getComponent().getBounds().contains(e.x, e.y)){
       // ändere zoom-level
   }
}


Muss ich wirklich die erste Variante wählen und die gesamte Composite-Hierarchie durchgehen? Das muss doch auch einfacher gehen oder?


Gruß,


Alan
 

eMmiE

Bekanntes Mitglied
Nimm statt MouseEvent einfach MouseInfo.getPointerInfo().getLocation()
Das liefert dir Werte zurück, die relativ zur linken oberen Bildschirmecke sind
 

Alan47

Mitglied
Hi,

erstmal danke für die Antwort! Der folgende Code...

Java:
MouseInfo.getPointerInfo().getLocation();

... ist leider für AWT/Swing, mein Problem dreht sich um SWT. Aber die prinzipielle Idee hab ich verstanden und bin zu folgender Lösung gelangt:

Java:
private void mouseScrolled(final MouseEvent e) {
        Composite comp = getComposite();
        // ermittle die Maus-Position (analog zu deinem Code)
		Point mousePos = comp.getDisplay().getCursorLocation();
        // bestimme die absolute Position der Komponente am Bildschirm
		Point componentOrigin = comp.toDisplay(0, 0);
		int x = componentOrigin.x;
		int y = componentOrigin.y;
        // bestimme die Breite und Höhe der Komponente am Bildschirm
		int width = this.viewer.getBounds().width;
		int height = this.viewer.getBounds().height;
        // erstelle das Rechteck, welches den sichtbaren Bereich der Komponente angibt
		Rectangle onScreenRect = new Rectangle(x, y, width, height);
        // prüfe ob der Mauszeiger sich in diesem Rechteck befindet
		if (onScreenRect.contains(mousePos)) {
			// verändere Zoom-Level...
		}
	}


Und siehe da: das funktioniert! Allerdings fällt es mir schwer zu glauben, dass das wirklich der von SWT vorgesehene Weg ist - mein Gefühl sagt mir, dass das auch einfacher gehen muss. Immerhin muss dieses Rechteck, das von meinem Code zusammen gebaut wird, auch von SWT irgendwo verwaltet werden, ansonsten könnten ja die ganzen "mouseEnter" und "mouseExit" Listener niemals aufgerufen werden... :reflect:


Gruß,


Alan
 

Alan47

Mitglied
Hi,
danke für den Hinweis, auf diese Art geht es wahrscheinlich auch, daran hab ich noch nicht gedacht. Ich bin mit meinem Code (den ich in meinem vorherigen Post gezeigt habe) aber recht zufrieden, da er für meine Zwecke genau passt und keine rekursiv eingehängten Listener erfordert.

Gruß,

Alan
 

dzim

Top Contributor
Ok, wollte es eh nur der Vollständigkeit halber erwähnt haben, weil ich es wahrscheinlich so gemacht hätte (wobei ich noch nie in SWT gezoomt habe...)
 

Alan47

Mitglied
Der Vollständigkeit halber: Das Zoomen eines Bildes in SWT geht tatsächlich sehr einfach, vor allem wenn man eine Subklasse von org.eclipse.swt.widgets.Canvas erstellt. Man hängt einen PaintListener in dieses Element ein. In dessen "paintWidget" Methode erhält man ein PaintEvent, welches den Graphics Context (GC) enthält. Auf diesen kann man nun folgende Methode aufrufen:

Java:
gc.drawImage(image,  // das Bild, welches angezeigt werden soll
                     srcX,          // -----
                     srcY,          // Diese vier Parameter bestimmen ein Rechteck auf dem Quell-Bild, von wo aus
                     srcWidth,      // die Pixel genommen werden sollen.
                     srcHeight,     //------
                     destX,        //------
                     destY,        // Analog zu den vorherigen vier bestimmen diese Parameter das Rechteck, in welches
                     destWidth,    // gezeichnet werden soll. 
                     destHeight    //------
                    );

Wenn man nun noch ein simples double-Feld (inkl. Getter & Setter) zur Subklasse hinzufügt, welches den Zoom-Faktor enthält, kann man die "destWidth" und "destHeight"-Parameter einfach mit diesem multiplizieren und fertig. Natürlich sollte man noch die computeSize(...)-Methode überschreiben und die Größe des Widgets ebenfalls mit dem Zoom-Faktor multiplizieren.

Ein paar Anmerkungen noch dazu:
  • die gc.drawImage(...)-Methode mit 9 Parametern benötigt eine erweiterte Grafik-Subkomponente im System. Laut Javadoc ist dies nicht auf allen Systemen verfügbar.
  • Man kann die Art und Weise, wie das Bild vergrößert wird, mittels gc.setAntialias(...) und gc.setInterpolation(...) beeinflussen. Auch hier ist das erweiterte Grafik-Subsystem erforderlich.
 

Androbin

Bekanntes Mitglied
... Also die Eclipse API sagt was anderes... ...
Anders die JavaDoc 8
drawImage
public abstract boolean drawImage(Image img,
int dx1,
int dy1,
int dx2,
int dy2,
int sx1,
int sy1,
int sx2,
int sy2,
Color bgcolor,
ImageObserver observer)
Draws as much of the specified area of the specified image as is currently available, scaling it on the fly to fit inside the specified area of the destination drawable surface.
Transparent pixels are drawn in the specified background color. This operation is equivalent to filling a rectangle of the width and height of the specified image with the given color and then drawing the image on top of it, but possibly more efficient.

This method returns immediately in all cases, even if the image area to be drawn has not yet been scaled, dithered, and converted for the current output device. If the current output representation is not yet complete then drawImage returns false. As more of the image becomes available, the process that loads the image notifies the specified image observer.

This method always uses the unscaled version of the image to render the scaled rectangle and performs the required scaling on the fly. It does not use a cached, scaled version of the image for this operation. Scaling of the image from source to destination is performed such that the first coordinate of the source rectangle is mapped to the first coordinate of the destination rectangle, and the second source coordinate is mapped to the second destination coordinate. The subimage is scaled and flipped as needed to preserve those mappings.

Parameters:
img - the specified image to be drawn. This method does nothing if img is null.
dx1 - the x coordinate of the first corner of the destination rectangle.
dy1 - the y coordinate of the first corner of the destination rectangle.
dx2 - the x coordinate of the second corner of the destination rectangle.
dy2 - the y coordinate of the second corner of the destination rectangle.
sx1 - the x coordinate of the first corner of the source rectangle.
sy1 - the y coordinate of the first corner of the source rectangle.
sx2 - the x coordinate of the second corner of the source rectangle.
sy2 - the y coordinate of the second corner of the source rectangle.
bgcolor - the background color to paint under the non-opaque portions of the image.
observer - object to be notified as more of the image is scaled and converted.
Returns:
false if the image pixels are still changing; true otherwise.
Since:
JDK1.1
See Also:
Image, ImageObserver, ImageObserver.imageUpdate(java.awt.Image, int, int, int, int, int)
 

Alan47

Mitglied
Anders die JavaDoc 8

Oha, da schau an! Das war mir nicht bewusst. Zumindest in der SWT-Version, die ich momentan verwende, stimmt aber die "alte" Eclipse-Doc noch. Interessant, dass die SWT-Entwickler sich dazu entschlossen haben, das zu ändern.

Jedenfalls danke für den Hinweis! Wenn ich auf die neueste Version upgraden sollte, werde ich das ändern müssen...

Ich sehe auch gerade, die von dir zitierte Methode hat auch 2 Parameter mehr:

Code:
Color bgcolor,
ImageObserver observer


... die gibt's in meiner Version hier noch gar nicht. Machen aber durchaus Sinn!



EDIT: Bist du dir sicher, dass dein JavaDoc zu einer *SWT* Klasse gehört? Sie erwähnt einen ImageObserver, der sich in einem AWT-Paket befindet...
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Probleme mit MouseWheelListener und JLayeredPane in Applet AWT, Swing, JavaFX & SWT 2
Landei Swing globaler MouseWheelListener? AWT, Swing, JavaFX & SWT 2
S StackOverflowError bei MouseWheelListener für JApplet AWT, Swing, JavaFX & SWT 5
G Probleme mit JTable und MouseWheelListener AWT, Swing, JavaFX & SWT 3
Saxony MouseWheelListener (ein Mix aus SWT, AWT und Swing) AWT, Swing, JavaFX & SWT 6
Y Objekte grafisch darstellen ohne GMF - Composite auf Canvas? AWT, Swing, JavaFX & SWT 2
G SWT JAVA Swt Composite übereinanderlegen AWT, Swing, JavaFX & SWT 6
S SWT TableCell mit Composite als Inhalt / Höhe der Cell/Row AWT, Swing, JavaFX & SWT 5
reibi SWT Bild auf Composite zentrieren AWT, Swing, JavaFX & SWT 7
D SWING - Ein Composite scrollen AWT, Swing, JavaFX & SWT 6
lumo SWT Composite Mouse Track Lisetner AWT, Swing, JavaFX & SWT 2
lumo SWT Composite Focus AWT, Swing, JavaFX & SWT 2
A SWT Scrollable Composite innerhalb eines Composites AWT, Swing, JavaFX & SWT 3
J SWT Größe eines Composite mit Gridlayout festlegen AWT, Swing, JavaFX & SWT 2
G SWT Button in Composite vor anderem Button einfügen AWT, Swing, JavaFX & SWT 10
A SWT Auf einem Tabb (FormPage) einzelnes Composite neu zeichnen AWT, Swing, JavaFX & SWT 7
A SWT SWT - Unbekannte Fläche (Objekt) erscheint im Composite AWT, Swing, JavaFX & SWT 6
lumo SWT Composite + Image + zeichnen AWT, Swing, JavaFX & SWT 4
N SWT - über Thread Composite erstellen und Anhängen AWT, Swing, JavaFX & SWT 6
J SWT 4 Objekte auf einem Composite anordnen AWT, Swing, JavaFX & SWT 5
S SWT Composite mit Layout Manager geht nicht AWT, Swing, JavaFX & SWT 4
L SWT Composite klonen AWT, Swing, JavaFX & SWT 2
lumo SWT Absolute position einer Composite/Control AWT, Swing, JavaFX & SWT 5
B SWT Composite neu zeichnen AWT, Swing, JavaFX & SWT 3
M Shell vs. Composite AWT, Swing, JavaFX & SWT 3
P SWT Composite und viele Labels AWT, Swing, JavaFX & SWT 10
A SWT Composite bleibt leer AWT, Swing, JavaFX & SWT 7
K Composite Inhalt wird nicht angezeigt AWT, Swing, JavaFX & SWT 5
G Composite - Rand wird nicht richtig dargestellt AWT, Swing, JavaFX & SWT 3
7 SWT-Composite für Wizard, Event finden? AWT, Swing, JavaFX & SWT 5
der JoJo [SWT]Meherer Composite's , immer nur eins anzeigen AWT, Swing, JavaFX & SWT 2
T FillLayout und Composite AWT, Swing, JavaFX & SWT 10
C SWT Composite Border im Nachhinein setzen AWT, Swing, JavaFX & SWT 1
I Composite AWT, Swing, JavaFX & SWT 5
H CardLayout beschränken AWT, Swing, JavaFX & SWT 2
S Swing TextPane größe beschränken AWT, Swing, JavaFX & SWT 2
G LayoutManager BorderLayout WEST Bereich auf maximale Größe beschränken AWT, Swing, JavaFX & SWT 19
H Swing Ausgabe auf 2 nachkomma stellen beschränken AWT, Swing, JavaFX & SWT 3
J Swing jSlider nur auf bestimmte werte beschränken AWT, Swing, JavaFX & SWT 15
A Die Eingabe in einem JTextField beschränken AWT, Swing, JavaFX & SWT 5
M jTextField mit Eingabe beschränken AWT, Swing, JavaFX & SWT 4
D LAF auf JFrame beschränken oder Substance LAF im Fullscreen AWT, Swing, JavaFX & SWT 6
S JTextField und JOptionPane - Zeicheneingabe beschränken AWT, Swing, JavaFX & SWT 3
W jTextField eingabelänge beschränken AWT, Swing, JavaFX & SWT 10
H JTable aktualisieren / InternalFrames auf Panel beschränken AWT, Swing, JavaFX & SWT 6
F Eingabe in JPasswordField auf vier Zeichen beschränken AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen


Oben