# Mouse + Keylistener



## Underfaker (30. Apr 2014)

Hallo zusammen,

besteht die Möglichkeit in Java für eine bestimmte Komponente zwei Listener so zu implementieren, dass man beide Exvents abfragen kann.
Mir geht es darum die Aktion "Mausrad rotieren" nur dann abzuarbeiten wenn gleichzeitig Strg gedrückt wird.

Hat da jemand etwas Brauchbares?

Besten Dank im voraus


----------



## Joose (30. Apr 2014)

Klar geht das 

Erstelle eine Klasse die beide Listener implementiert und füge ein(!) Objekt dieser Klasse als Key UND als MouseListener hinzu!

Wenn du nun STRG drückst setze einfach ein Flag, und frage diese Flag ab wenn das Mouserad gedreht wird.


----------



## Underfaker (30. Apr 2014)

Danke für den Hinweis.

Meine Klasse sieht nun so aus:

```
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;


public class KeyMouseListener implements KeyListener, MouseWheelListener 

{
	
	PanelForCoordinate panel;
	
	public KeyMouseListener(PanelForCoordinate panel)
	
	{
		this.panel = panel;
	}
	
	boolean flag = false;

	@Override
	public void mouseWheelMoved(MouseWheelEvent e) 
	{
		if (flag)
		{
			int scrollType = e.getWheelRotation();
			if (scrollType < 0 )
			{
				int bla = panel.getSlider().getValue();
				panel.getSlider().setValue(++bla);
			}
			else
			{
				int bla = panel.getSlider().getValue();
				panel.getSlider().setValue(--bla);
			}
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {
		System.out.println(e);
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == 17)
			flag = true;
		else
			flag = false;
		System.out.println("bla");
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

}
```
In der Klasse wo ich diesen Listener setze, ist ein Panel und dieser Slider der beeinflusst werden soll.
Wenn ich bei dem WheelListener die if-Abfrage weg mache, führt er den beinhalteten Code aus.
Aber das Programm reagiert in keinster Weise auf iregndwelche Tastendrücke.
Gibt es auch dafür eine Idee?


----------



## Joose (30. Apr 2014)

Schaut schon mal gut aus, wie setzt du denn den Listener? (zeige beide Stellen).

Soweit ich weiß wird das keyPressed Event nur ausgelöst von Tasten die "druckbare Zeichen schreiben", du müsstest ein keyDown Event verwenden.


----------



## Underfaker (30. Apr 2014)

Zeile 37 und 38:

```
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;


public class PanelForCoordinate extends JPanel  implements ChangeListener{

	private Coordinate coordinateSystem;
	private JSlider slider;
    public PanelForCoordinate(int size)
    
    {
    	try {
			UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	this.setSize(size, size);
    	slider = new JSlider(1, 50, 25);
    	KeyMouseListener keyMouseListener = new KeyMouseListener(this);
    	this.addMouseWheelListener(keyMouseListener);
    	this.addKeyListener(keyMouseListener);
    	SwingUtilities.updateComponentTreeUI(slider);
        slider.addChangeListener(this);
        SwingUtilities.updateComponentTreeUI(slider);
        setLayout(new BorderLayout());
        add(slider, BorderLayout.SOUTH);
        coordinateSystem = new Coordinate(size);
        add(coordinateSystem, BorderLayout.CENTER);
    }
    
    public JSlider getSlider()
    
    {
    	return slider;
    }
    
	@Override
	public void stateChanged(ChangeEvent e) {
		double factor = (double)((JSlider)e.getSource()).getValue()/50;
		coordinateSystem.setFactor(factor*16);
		coordinateSystem.repaint();
		this.repaint();
	}
	
	
}
```

In einem anderen Beispiel hab ich einem Button das übergeben:

```
btnNewButton.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println(e);
			}
		});
```
Der reagiert auch auf Tastendrucke


----------



## Underfaker (30. Apr 2014)

Könnte es damit zusammenhängen, dass es dem Panel hinzugefügt wird?
Das scheint mir nämlich allgemein problematisch zu sein, wenn man ein Panel auf einem Panel hat.


----------



## Joose (30. Apr 2014)

Underfaker hat gesagt.:


> Der reagiert auch auf Tastendrucke



Wie gesagt, es gibt 3 verschiedene Events bei Keys


keydown - wird ausgelöst sobald die taste gedrückt wird (wiederholt sich solange die taste gedrückt bleibt)
keypress - wird ausgelöst wenn eine taste mit druckbaren zeichen gedrückt (und auch wieder losgelassen wurde)
keyup - wird ausgelöst sobald die taste losgelassen wird

Natürlich musst du auch aufpassen welches Control den Fokus (bzw. Keyboard Focus hat).


----------



## Underfaker (30. Apr 2014)

Ja kannst du mir dann vielleicht das beantworten?
Da die Klasse KeyListener nur die Methoden keyTyped, keyPressed und keyReleased kennt, weiß ich nicht wie ich keyDown anbinde.
Und wie sorge ich dafür, dass wenn ich einem Panel diesen Listener übergebe und das Panel dann auf ein Frame packe, dass dann der Panel-listener reagiert?
Mit dem Satz "welches Control den Focus hat", kann ich so leider nichts anfangen.

Danke schon mal


----------



## Underfaker (30. Apr 2014)

Oha, das war ja einfach.
Hab in dem Frame gesagt, dass das Panel focusable sein soll und schon geht es, yeha

Jetzt fehlt nur noch das wenn ich einmal auf Strg gedrückt habe, dass es dann auch ohne den Tastendruck geht, also benötige ich wohl kDown.

Kannst du mir das mit dem KeyDown zeigen?
Ich habe es zwar nun so gelöst, das bei keyRelesed einfach wieder ein false gesetzt wird, allerdings wird - wie du sagst - jetzt der keyPressed ununterbrochen ausgeführt, das könnte man sich ja sparen.


----------



## Joose (2. Mai 2014)

Wie du geschrieben hast, stellt das KeyListener Interface (nicht Klasse!!) 3 Methoden bereit. Eine davon enstpricht dem drücken einer Taste, eine dem loslassen einer Taste und eine entsprichten dem drücken+loslassen einer Taste (begrenzt auf druckbare Zeichen).


----------



## Underfaker (2. Mai 2014)

Ja wie du schon festgestellt hast, hatte ich das schon festgestellt(!). Oo

Naja es läuft auf jeden Fall jetzt so wie ich es wollte, das mit dem Focus ist natürlich schwierig, da er immer wo anders zu landen scheint aber wird schon.

Danke für die Hilfe.


----------



## Joose (2. Mai 2014)

Underfaker hat gesagt.:


> Ja wie du schon festgestellt hast, hatte ich das schon festgestellt(!). Oo



Ging für mich nicht klar hervor 



Underfaker hat gesagt.:


> Naja es läuft auf jeden Fall jetzt so wie ich es wollte, das mit dem Focus ist natürlich schwierig, da er immer wo anders zu landen scheint aber wird schon.
> 
> Danke für die Hilfe.



Naja entweder suchst du über Google einen Blogbeitrag der das Thema Focus Handling in Swing behandelt, oder du testest es selber ausgiebig. Generell muss man bei Listener "Geschichten" genau in der Doku lesen in welcher Reihenfolge die abgearbeitet werden und von welchen Komponenten da dann reagiert werden kann usw.


----------



## Harry Kane (2. Mai 2014)

@TE:
Wenn es nur darum geht, dass eine Mausrad-Aktion nur dann ausgeführt wird, wenn die Ctrl-Taste gedrückt wird, warum fragst du nicht einfach 
	
	
	
	





```
mouseEvent.isCtrlDown()
```
 ab ?


----------

