Swing Eigene Komponente reagiert falsch auf mouseClicked()

Hutmacher

Bekanntes Mitglied
Dies hier ist ein kleines Beispiel einer eigenen Komponente, die von JComponent erbt. Sie soll nur ein Rechteck malen und wenn man diese auf der GUI anklickt, etwas ausprinten.

Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JComponent;

public class Compo extends JComponent implements MouseListener
{
	public Compo()
	{
		setPreferredSize(new Dimension(123, 123));
		setSize(123, 123);
		addMouseListener(this);
	}
	
	@Override 
	public void paintComponent(Graphics graphics)
	{
		super.paintComponents(graphics);
		graphics.drawRect(0, 0, 122, 122);
	}

	@Override
	public void mouseClicked(MouseEvent e)
	{
		System.out.println("sdfk");
		
	}

           // ↓ Wayne ↓
	@Override
	public void mouseEntered(MouseEvent e)
	{
		// TODO Auto-generated method stub
		
	}

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

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

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

Dazu noch die GUI mit Main-Methode:
Java:
import javax.swing.*;

public class GUI extends JFrame
{
	
	public GUI()
	{
		super("Testing");
		setSize(740, 650);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Compo rectangle = new Compo();
		getContentPane().add(rectangle);
	}
	
	public static void main(String[] args)
	{
		new GUI().setVisible(true);
	}
}

Das Ganze kann man also als „Kurzes kompilierbares Beispiel“ ansehen ;D

Wenn ich ich auf das Rechteck klicke, wird etwas ausgegeben – soweit, so gut. Das Problem ist nun, dass es auch ausgegeben wird, wenn ich danebe klicke – egal, wohin im Fenster ich klicke!

Woran liegt das, was habe ich vegessen/falsch gemacht?
 
Hallo Hutmacher,

wenn Du Deiner JComponent z.b. mit ...
Java:
   setBorder(BorderFactory.createLineBorder(Color.black));
... einen Rahmen gibst, siehst Du was passiert.
Die Ursache hierfür ist das Standard-Layout des JFrame (BorderLayout).

Setze die folgende Zeile in den Konstruktor des JFrame ein und Du erhältst das von Dir gewünschte Ergebnis:
Java:
   setLayout(null);

Ich hoffe, ich konnte Dir damit helfen. 🙂

VG ROlf

(EDIT: Sorry, das Standard-Layout des JFrame ist natürlich das BorderLayout. Hab es soeben geändert.)
 
Zuletzt bearbeitet:
Jep, das stimmt zwar, aber das Problem ist ja, dass diese Komponente in einer geordneten GUI mit Layout X auch funktionieren muss – zum Beispiel ein JButton funktioniert ja nicht auch nur mit dem Null-Layout =)
(hätte ich vielleicht dazuschreiben sollen ^^')
 
Wieso? Der Button wird doch dann genauso ans Layout angepasst. Wenn du dein Fenster vergrößerst/verkleinerst, veränderst du doch evtl., je nachdem welches Layout du hast auch die Größe des Buttons. Das gezeichnetete Rechteck hat dann damit nichts zu tun:
Java:
	public static void main(String[] args) throws Exception {
		JFrame frame = new JFrame();
		JButton btn = new JButton("Blub"){
			@Override
			protected void paintComponent(Graphics g) {
				super.paintComponent(g);
				g.drawRect(0, 0, 122, 122);
			}
		};
		btn.setPreferredSize(new Dimension(122, 122));
		btn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
		        System.out.println("sdfk");
			}
		});
		frame.add(btn);
		frame.setSize(740, 650);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}

So gehts z.B. mit deiner Komponente auch:
Java:
	public static void main(String[] args) throws Exception {
		JFrame frame = new JFrame();
		JPanel panel = new JPanel();
		panel.add(new Compo());
		frame.add(panel);
		frame.setSize(740, 650);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
 
Stimmt, die JButton-Komponente verhält sich doch genauso, wie Deine "Compo". ;-)

Wenn Du Deine Komponente zuerst in ein JPanel packst und den dann
dem ContentPane des JFrame hinzufügst, dann sollte es funktionieren.

VG ROlf
 
Dankeschön, die Lösung funktioniert gut.
Ich wollt mal wieder den Weg der puren Komponente, die „auch ohne“ funktioniert, gehen.

@ r.w.:
Compo heißt das nur, weil das ein Test und ich zu faul für „TestComponent“ war … na ja, letzenendes habe ich es ja doch geschrieben ^^
 

Zurück
Oben