Tinkas Webseite

Java bietet einem als Programmierer mehrere Möglichkeiten, Eingaben mit einer Maus zu verarbeiten.
Hier soll es explizit um Java AWT und Swing gehen.

Mauseingaben mit Java AWT und Swing

Eines kurz zusammengefasst:
Mit Java AWT war es zum ersten Mal möglich, mit Java graphische Oberflächen zu erstellen. Aufgrund interner Entscheidungen folgte Java Swing, welches auf AWT aufbaut und nutzt. Deshalb wird, obwohl mit Swing programmiert wird, oft auch java.awt importiert. AWT und Swing sind jedoch nicht das selbe!

Definitionen und Erklärungen

Normalerweise macht dein Programm seine Sachen, ohne darauf zu achten, was um es herum passiert. Dies sorgt für einen schnellen und gezielten Ablauf des Programms. Wenn das Programm jetzt aber auf unsere Maus reagieren soll, brauchen wir einen Listener (dt. eher Horcher). Der Listener beobachtet unsere Maus und wenn die Maus etwas tut, was einen Einfluss auf unseren Programm haben soll, kriegt das der Listener mit und kontaktiert unser Programm, sodass es auf unsere Maus reagiert.

Eine Maus kann verschiedene Events (dt. Aktionen) auslösen, die individuell behandelt werden können. Wir müssen dem Listener mitteilen, auf welche Events er achten soll und was dann getan werden muss. Java unterscheidet zwischen zwei Arten von Events.
Die Mouse Events decken das Drücken einer Maustaste, das Loslassen einer Taste sowie das komplette Klicken (also klicken und loslassen) ab. Dazu gehört auch, wenn der Mauszeiger auf ein bestimmtes Element trifft oder verlässt. Ein Beispiel hierfür wäre wie sich der Mauszeiger ändert, wenn er auf eine Scrollleiste an der rechten Fensterseite geführt wird.
Die Mouse Motion Events sind eher für die Bewegungen der Maus da. Dazu zählt die einfache Bewegung als auch das Bewegen mit einer gedrückten Taste.

MouseEvents

Für gewöhnlich werden die Mouse Events in einer separaten Klasse (hier jetzt MausHandler) behandelt. Dazu kann dann das Interface MouseListener implementiert werden. Als Interface werden Methoden bereits gestellt, nämlich mousePressed, mouseReleased, mouseclicked, mouseEntered und mouseExited, die mit @Override überschrieben werden müssen, auch wenn vielleicht gar nicht alle Methoden gebraucht werden.

Eine zweite Möglichkeit ist das Erben von der Klasse MouseAdapter. Damit ändert sich der Schlüsselbegriff von implements zu extends. Diese Klasse hat alle Methoden von MouseListener bereits (leer) überschrieben. Daher können die Methoden, die du nicht brauchst, auch komlett weggelassen werden.

Codeschnipsel, wie überschriebene Methoden von MouseListener, die nicht benutzt werden, werden als Boilerplate-Code bezeichnet. Solche Codeschnipsel fügen keine neue Logik oder Funktionalität hinzu und können deinen Code eventuell sogar schwerer lesbarer machen oder sogar anfällig für Fehler sein. Dennoch musst du alle Methoden eines Interfaces überschreiben, was die Codeschnipsel unnötig aber trotzdem wichtig macht. Paradox, ich weiß. Vermeide also eher Interfaces wie MouseListener, wenn es bereits Klassen wie MouseAdapter gibt.

Wird eine Maustaste geklickt, werden die Methoden in der folgenden Reihenfolge aufgrufen: mousePressed, mouseReleased, mouseClicked.
Daher empfehle ich, diese Reihenfolge der Methoden auch so in der Klasse niederzuschreiben, um eventuelle Missverständnisse beim Programmieren vorzubeugen.

Code-Template mit MouseListener-Interface

MausHandler-Klasse:


    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    
    public class MausHandler implements MouseListener {
        
        //Konstruktor optional
        public MausHandler() {}
        
        @Override
        public void mousePressed(MouseEvent e) {}
        
        @Override
        public void mouseReleased(MouseEvent e) {}
        
        @Override
        public void mouseClicked(MouseEvent e) {}
        
        @Override
        public void mouseEntered(MouseEvent e) {}
        
        @Override
        public void mouseExited(MouseEvent e) {}
    }

Main-Klasse:


    ...
    import javax.swing.JButton;
    ...
    
    public class Main {
    
        ...

            //eine Methode
            ...
            JButton button = new JButton();
            MausHandler mh = new MausHandler();
        
            //vergiss nicht, die neue Klasse als Listener an ein Component anzuhängen:
            button.addMouseListener(mh);
            ...
        
        ...
    }

Code-Template mit MouseAdapter-Klasse

MausHandler-Klasse:

Alle @Override-Methoden sind optional. Bitte lösche alle Methoden, die du leer lässt.


    import java.awt.event.MouseEvent;
    import java.awt.event.MouseAdapter; //Wichtig! Der Import ändert sich
    
    public class MausHandler extends MouseAdapter {
        
        //Konstruktor optional
        public MausHandler() {}
        
        //Methode optional
        @Override
        public void mousePressed(MouseEvent e) {}
        
        //Methode optional
        @Override
        public void mouseReleased(MouseEvent e) {}
        
        //Methode optional
        @Override
        public void mouseClicked(MouseEvent e) {}
        
        //Methode optional
        @Override
        public void mouseEntered(MouseEvent e) {}
        
        //Methode optional
        @Override
        public void mouseExited(MouseEvent e) {}
    }

Main-Klasse:

Es ändert sich nichts für die Main-Klasse.


    ...
    import javax.swing.JButton;
    ...
    
    public class Main {
    
        ...

            //eine Methode
            ...
            JButton button = new JButton();
            MausHandler mh = new MausHandler();
        
            //vergiss nicht, die neue Klasse als Listener an ein Component anzuhängen:
            button.addMouseListener(mh);
            ...
        
        ...
    }

MouseMotionEvents

Auch für die MouseMotionEvents gibt es jeweils das MouseMotionListener-Interface und die MouseMotionAdapter-Klasse.
Für die MouseMotionEvents werde ich unsere Klasse MausMotionHandler nennen.

Das MouseMotionListener-Interface besitzt nur zwei Methoden, mouseDragged und mouseMoved.
mouseDragged wird ausgelöst, wenn auf ein Component wie ein Fenster eine Maustaste gedrückt gehalten wird und das Component so verschoben wird.
mouseMoved wird ausgeführt, wenn der Mauszeiger auf ein Component geführt wurde und keine Maustaste gedrückt wird. Der kleine Unterschied zu mouseEntered und mouseExited von MouseListener ist der, dass die beiden Methoden nur einmal beim Hinein- bzw. Hinausbewegen des Components aufgerufen werden. mouseMoved wird hingegen bei jeder kleinsten Bewegung innerhalb des Components ausgeführt.

Vergiss nicht, dass ein Listener mit deiner MausMotionHandler- bzw. MausHandler-Klasse an ein Component hinzugefügt wird. Deshalb muss erst mit dem Component interagiert werden, damit der Listener aktiv wird.

Code-Template mit MouseMotionListener-Interface

MausMotionHandler-Klasse:


    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;
    
    public class MausMotionHandler implements MouseMotionListener {
        
        //Konstruktor optional
        public MausHandler() {}
        
        @Override
        public void mouseDragged(MouseEvent e) {}
        
        @Override
        public void mouseMoved(MouseEvent e) {}
    }

Main-Klasse:


    ...
    import javax.swing.JFrame;
    ...
    
    public class Main {
    
        ...

            //eine Methode
            ...
            JFrame frame = new JFrame();
            MausMotionHandler mmh = new MausMotionHandler();
        
            //vergiss nicht, die neue Klasse als Listener an ein Component anzuhängen:
            frame.addMouseMotionListener(mmh);
            ...
        
        ...
    }

Code-Template mit MouseMotionAdapter-Klasse

MausMotionHandler-Klasse:

Alle @Override-Methoden sind optional. Bitte lösche alle Methoden, die du leer lässt.


    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter; //Wichtig! Der Import ändert sich
    
    public class MausMotionHandler extends MouseMotionAdapter {
        
        //Konstruktor optional
        public MausHandler() {}
        
        //Methode optional
        @Override
        public void mouseDragged(MouseEvent e) {}
        
        //Methode optional
        @Override
        public void mouseMoved(MouseEvent e) {}
    }

Main-Klasse:

Es ändert sich nichts für die Main-Klasse.


    ...
    import javax.swing.JFrame;
    ...
    
    public class Main {
    
        ...

            //eine Methode
            ...
            JFrame frame = new JFrame();
            MausMotionHandler mmh = new MausMotionHandler();
        
            //vergiss nicht, die neue Klasse als Listener an ein Component anzuhängen:
            frame.addMouseMotionListener(mmh);
            ...
        
        ...
    }

Die Adapter-Klassen sind zwar sinnvoller, aber als Programmierer muss man recherchieren/wissen, welche Klasse welche Interfaces implementiert hat, um dann zu wissen, welche Methoden überhaupt zur Verfügung stehen. Vielleicht hilft an dieser Stelle deine IDE dir mit seinen Vorschlägen oder Autovervollständigungen?