Swing JButton macht Eventhandling kaputt

lamborgotti

Neues Mitglied
hallo,

Ich habe mich schon öfters mal darin versucht, irgendwie objektorientiert zu programmieren und jedes mal scheitert es daran, das irgendwas passiert, was ich nicht kapier ;(
Ich hab eigenlich noch gar nicht damit angefangen, was ich eigentlich tun will, aber schon bei aufbauen komm ich nicht weiter:

Im wesentlichen will ich ein Fenster mit 2 Panels(field und amaturen), im Linken will ich Knöpfe u.ä. und im Rechten grafische Sachen zeichnen.
Ausserdem hat die Oberklasse (World) einen KeyListener und wenn ich die Pfeiltasten bewege soll
sich im rechten Fenster(field) was bewegen, das hat auch prima geklappt, nur wenn ich jetzt im linken
Panel (amaturen) einen JButton hinzufüge, gehn die Keys nicht mehr(keine bewegung und kein System.out("blabla"))...?
Warum?
Ich könnte noch Stunden davor sitzen, es macht keinen Sinn, kann mir irgendwer helfen


Java:
public abstract class AWorld implements ActionListener, KeyListener, MouseListener {
	protected JFrame frame;
	protected Field field;
	protected Amaturen amaturen;
	[...]
	private void init() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() { 
           
	  // call the method that shows the frame and initialize it
		this.createAndShowGUI(); 

		if (this.timerticks && this.timer != null) 
			this.timer.start();

		// add listeners (key and mouse)
		this.frame.addKeyListener(this);
		this.field.addKeyListener(this);
		//this.amaturen.addKeyListener(this);
		this.frame.addMouseListener(this);
		this.field.addMouseListener(this);
		//this.amaturen.addMouseListener(this);
	}
		});	
	}
}

/////////////////////////////////////////////////////////////////////////////
public final class World extends AWorld {
	public static void main(String args[]) {
		new World();
	}
	
	/** 
	 * This function is called by the World class to create your
	 * main window. 
	 */
	@Override
	protected void createAndShowGUI() {
	  this.frame = new JFrame("...");

	  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
	  frame.getContentPane().setLayout(
                 new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));
	    
	 this.enableTicks(1000);
	    		
	 this.field = new Field();
	 this.amaturen = new Amaturen();
		
	 frame.add(this.amaturen);
	 frame.add(this.field);
		
	 frame.pack();  
	 frame.setResizable(false);
         frame.setVisible(true);
    }
    
    public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			field.movePlayer(0, -10);
			System.out.println("asdf");
		}
		if (e.getKeyCode() == KeyEvent.VK_UP) {
			field.movePlayer(0, 10);
		}
		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			field.movePlayer(-10, 0);
		}
		if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			field.movePlayer(10, 0); 
			System.out.println("right");
		}	
	}
    
}
  
/////////////////////////////////////////////////////////////////////////////
public class Amaturen extends JPanel //implements ActionListener
{
	public ZeitIndex zeitIndex; 
	public JButton startStop; 
	public JPanel pZeit;
	public JPanel pButtons;
	
	public Amaturen ()
	{
		setBorder(BorderFactory.createLineBorder(Color.black));
		setBackground(new Color(120, 120, 255));
		
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		
		this.pZeit = new JPanel();
		this.zeitIndex = new ZeitIndex(0);
		this.pZeit.add(zeitIndex);
		this.add(pZeit);
		
		this.pButtons = new JPanel();
		this.startStop = new JButton("Start/Stop");
		//this.startStop.addActionListener(this);
		this.pButtons.add(startStop);    //<<=== HIER spinnts
		this.add(pButtons);
	}
}
Grüße und Danke schon im Voraus!
 
Zuletzt bearbeitet:
Ist so jetzt schwer nachzuvollziehen, aber .. kann es sein, dass die Component, wo die KeyListener dranhängen, NICHT mehr den Focus hat, wenn der Button eingefügt wird? Schau ggf. mal, ob die Keys wieder funktionieren, wenn du vorher einmal mit der Maus auf die Component klickst, die die KeyListener hat. Ansonsten könnte ein KSKB vielleicht helfen...
 
ja kann ich verstehn ich hab mal versucht möglichst viel wegzustreichen was irrelavant für das Problem ist und es in eine Datei gemacht:
Java:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

abstract class AWorld implements ActionListener, KeyListener, MouseListener {
	protected JFrame frame;
	protected Field field;
	protected Amaturen amaturen;

	public AWorld() 
	{
		this.init();
	}

	abstract protected void createAndShowGUI();

	@Override
	public final void actionPerformed(ActionEvent e) {}

	@Override
	public void keyPressed(KeyEvent e) {}
	@Override
	public void keyReleased(KeyEvent e) {}
	@Override
	public void keyTyped(KeyEvent e) {}
	@Override
	public void mouseClicked(MouseEvent e) {}
	@Override
	public void mouseEntered(MouseEvent e) {}
	@Override
	public void mouseExited(MouseEvent e) {}
	@Override
	public void mousePressed(MouseEvent e) {}
	@Override
	public void mouseReleased(MouseEvent e) {}
  
	
	private void init() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUIWrapper();
			}
		});	
	}
	
	private void createAndShowGUIWrapper() {
		
		this.createAndShowGUI(); 

		// add listeners (key and mouse)
		this.frame.addKeyListener(this);
		this.field.addKeyListener(this);
		this.amaturen.addKeyListener(this);
		
		this.frame.addMouseListener(this);
		this.field.addMouseListener(this);
		this.amaturen.addMouseListener(this);
	}
}


/////////////////////////////////////////////////////////////////////////////////////
public final class World extends AWorld {

	public static void main(String args[]) {
		new World();
	}
	
	@Override
  protected void createAndShowGUI() {
     this.frame = new JFrame("How to react on key events?");

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));
        
     this.field = new Field();
     this.amaturen = new Amaturen();
      
     // Pack the Elements on the frame
     frame.add(this.amaturen);
     frame.add(this.field);
      
     frame.pack();  
     frame.setResizable(false);
     frame.setVisible(true);     
   }

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			field.movePlayer(0, -10);
			System.out.println("down");
		}
		if (e.getKeyCode() == KeyEvent.VK_UP) {
			field.movePlayer(0, 10);
			System.out.println("up");
		}
		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			field.movePlayer(-10, 0);
			System.out.println("left");
		}
		if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			field.movePlayer(10, 0); 
			System.out.println("right");
		}	
	}
}
/////////////////////////////////////////////////////////////////////////////////////
class Amaturen extends JPanel implements ActionListener
{ 
	public JPanel pButtons;
	public JButton startStop;
		
	public Amaturen ()
	{
		setBorder(BorderFactory.createLineBorder(Color.black));
		setBackground(new Color(120, 120, 255));
		
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		
		this.pButtons = new JPanel();
		this.startStop = new JButton("Start/Stop");
		this.startStop.addActionListener(this);
		this.add(startStop);            /////   <<<<============  Problem, wenn nicht auskommentiert
		this.add(pButtons);                                        // dann gehen Tasten nicht mehr
	}
	
	public Dimension getPreferredSize() {
        return new Dimension(200, 600);
  }
	
	public void actionPerformed(ActionEvent evt)
	{
		this.setBackground( Color.blue );
		System.out.println("asdf");
	  repaint();  
	}
	
}
/////////////////////////////////////////////////////////////////////////////////////
class Field extends JPanel {

  public Bubbel bubbel1;

	public Field() {
		setBorder(BorderFactory.createLineBorder(Color.black));
		setBackground(new Color(200, 200, 255));
		
		bubbel1 = new Bubbel(100, 100);
	}
		
	public Dimension getPreferredSize() {
      return new Dimension(800, 600);
  }

  public void paintComponent(Graphics g) {
      super.paintComponent(g);       

      // Zeichen Bubbel, den man bewegen kann
      g.setColor(Color.red);
      g.fillArc(bubbel1.x, bubbel1.y, 10, 10, 0, 360);
  } 
    
    public void movePlayer (int x, int y)
    {
    	bubbel1.x += x;
    	bubbel1.y -= y;
    	repaint();
    }       
}
/////////////////////////////////////////////////////////////////////////////////////
class Bubbel 
{
	int x;
	int y;

	public Bubbel (int x, int y)
	{
		this.x = x;
		this.y = y;    
	}
}
Das mit dem Fokus ist schon mal ein guter Tipp, aber mit draufklicken geht das auch nicht. Und ich weiss auch nicht, wie ich den Fokus wieder zurück auf den Listener zurückbekomme.
Ich bin mir auch nicht so sicher was die gesamte Struktur von den Dateien angeht, ich hab die Grundstrucktor von einer Vorlage(deswegen das abstrakte AWorld), aber ich glaube ich nutze sie nicht ganz im Sinne des Erfinders.
 
Zuletzt bearbeitet:
Hmja.. in bezug auf die Struktur... Wenn man objektorientiert programmiert, verwendet man Klassen. Umgekehrt gilt diese Implikation NICHT. Also, mir ist nicht ganz klar, wozu die Vererbung mit der AWorld in diesem Fall gut sein soll ???:L

Es ist - wie vermutet - das Problem mit dem Focus: Wenn man
Code:
     this.field = new Field();
     [b]this.field.setFocusable(true); // <--- diese Zeile [/b]
 ....
einfügt, kann man mit "TAB" den Focus zwischen dem Button und dem Feld hin- und herschalten - und wenn er im Feld ist, kann man den Punkt bewegen. Mit
Code:
...
     [b]this.field.requestFocus(); // <--- dieser Zeile[/b]
     frame.setVisible(true);
kann man auch erreichen, dass das Spielfeld am Anfang dem Focus hat - bis man einmal den Button klickt.

Spontan würden mir mindestens ... 4 oder 5 Wege einfallen, wie man dieses Problem lösen könnte... und davon sind nur die wenigsten für das Problem angebracht. Am ehesten noch mit einem KeyEventDispatcher oder mit Key bindings How to Use Key Bindings (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)

Ich würde eher zu letzterem raten, da das recht "high-level" und trotzdem ganz gut steuerbar ist, aber ... warte mal ab, ob noch jemand weitere Vorschläge macht...
 

Neue Themen


Zurück
Oben