ComponentListener hört nicht zu

bloodyrocky

Mitglied
Hi zusammen,

ich habe mal wieder ein Problem und finde den Fehler nicht. Ich habe zwei JLabels die sich auf und ab bewegen. Dabei hört das eine auf einen Timer der das Label auf und ab bewegt und das ander wird mit der Maus auf und ab bewegt. Beiden Labels wurde ein ComponentListener hinzugefügt der dann reagieren soll, wenn die Labels bewegt werden. Beim Label, dass durch den Timer bewegt wird funktioniert das, bei dem anderen nicht. Die aufgerufene Funktion ist die selbe und wirkt sich auf das gleiche Objekt aus.

Hat jemand eine Idee warum der 2. nicht reagiert?
Hier noch der Codeauszug:
Java:
Timer t2 = new Timer(3000,new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                soll.setLocation(/*neue Position*/);
            }
        });
		
public void mouseMoved(MouseEvent e){
        int y = 0;
        if(e.getY() < 89) y = 89;
        else if (e.getY() > 450) y = 450;
        else y = e.getY();
        ist.setLocation(158, y);
    }


soll.addComponentListener(new ComponentListener() {
            public void componentResized(ComponentEvent e) {/*not used*/}
            public void componentShown(ComponentEvent e) {/*not used*/}
            public void componentHidden(ComponentEvent e) {/*not used*/}

            public void componentMoved(ComponentEvent e) {
                Point sollPoint = e.getComponent().getLocation();
                Point istPoint = ist.getLocation();
                Rectangle rect = gap.updatePosition(istPoint, sollPoint,
                        ist.getWidth(), ist.getHeight(), soll.getWidth(),
                        soll.getHeight());
                gap.setBounds(rect);
                gap.setRectangle(rect);
                gap.repaint();
            }
        });
        
        ist.addComponentListener(new ComponentListener() {
            public void componentResized(ComponentEvent e) {/*not used*/}
            public void componentShown(ComponentEvent e) {/*not used*/}
            public void componentHidden(ComponentEvent e) {/*not used*/}

            public void componentMoved(ComponentEvent e) {
                Point sollPoint = e.getComponent().getLocation();
                Point istPoint = ist.getLocation();
                Rectangle rect = gap.updatePosition(istPoint, sollPoint,
                        ist.getWidth(), ist.getHeight(), soll.getWidth(),
                        soll.getHeight());
                gap.setBounds(rect);
                gap.setRectangle(rect);
                gap.repaint();
            }
        });
 
bevor du dich aufwendig um die Komponenten kümmerst, hast du auch schon getestet, ob es überhaupt zu Maus-Events kommt?
da gibts feine Probleme wie addMouseListener vs addMouseMotionListener usw.

ohne fertiges Programm kann man diverse Fehlerursachen nicht wirklich ausschließen,
ich habe unten eins zusammengestellt, vielleicht hilft dir das schon, bei mir kommen alle drei Ausgaben,
ansonsten bitte erweitern z.B. so dass die Komponenten auch wirklich zu sehen sind, das hab ich auf die Schnelle noch nicht

Java:
public class TestGUI   extends JFrame {
    public TestGUI()   {
        JPanel p = new JPanel();
        p.setLayout(null);

        final JLabel ist = new JLabel("ist");
        final JLabel soll = new JLabel("soll");
        ist.setSize(30, 30);
        ist.setLocation(60, 60);
        soll.setSize(30, 30);
        soll.setLocation(200, 60);
        p.add(ist);
        p.add(soll);
        Timer t2 = new Timer(300, new ActionListener()    {
                public void actionPerformed(ActionEvent e)      {
                    soll.setLocation(soll.getLocation().x, soll.getLocation().y + 5);
                }
            });
        t2.start();


        p.addMouseMotionListener(new MouseAdapter()   {
                public void mouseMoved(MouseEvent e)   {
                    System.out.println("move");
                    ist.setLocation(ist.getLocation().x, ist.getLocation().y + 1);
                }
            });
        soll.addComponentListener(new ComponentAdapter()       {
                public void componentMoved(ComponentEvent e)        {
                    System.out.println("moved soll");
                }
            });
        ist.addComponentListener(new ComponentAdapter()        {
                public void componentMoved(ComponentEvent e)         {
                    System.out.println("moved ist");
                }
            });

        add(p);
        setSize(700, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args)  {
        new TestGUI();
    }
}
 
Zuletzt bearbeitet von einem Moderator:
Der MausListener funktioniert, das hatte ich schon vorher sicher gestellt. Die Komponente bewegt sich ordnungsgemäß auf und ab.

Ich wollte nur nicht die ganze Klasse einfügen, da es doch ein paar Zeilen Code sind und noch nicht "aufgeräumt" wurde von mir. Falls es hilft kann ich die aber gerne nachreichen.
 
so, ich habe jetzt mein Programm von oben noch um korrekte Anzeige und einigermaßen sinnvolle Bewegung erweitert,
soll geht langsam nach unten, ist bewegt sich ebenso, wenn man die Maus bewegt,
schon fast ein modernes Rennspiel, DirectX 10 in der nächsten Version

an deinem Code kann ich derzeit keinen Fehler erkennen, möglich ist immer noch, dass der MouseMotionListener nicht oder nicht oft genug aktiviert wird, dass die Berechnung zu keiner geänderten Postion kommt,
oder diese Position aufgrund außenstehender Gründe (Layout) nichts bewirkt,
oder dass du ein anderes Objekt bewegst als das welches den Listener hat
oder manch anderes,
bzw. du sagst ja dass alles zur Bewegung klappt, dann ist der ComponentListener vielleicht nicht oder an einem falschen Objekt registiert oder wird doch aktiv aber macht nichts, was Auswirkung hätte,

ein Testprogramm wäre die umfassende Hilfe zur Hilfe
 
Ich habe mal noch ein System.out gemacht, um zu sehen ob der Listener auf dem "ist" auch wirklich geht und siehe da der geht. Gut hätte ich schon früher drauf kommen können, dass zu probieren. 😳

Dennoch wird die Komponente nicht gezeichnet im Falle von "ist wurde bewegt". Interessanterweise beim soll schon und beide greifen auf das gleiche Objekt zu und beide benutzen die gleichen Aufrufe.

Hier dann doch mal der ganze Code für beide Klassen, die main in dem ich die Aufrufe mache und GapVisualizer für das zu zeichnende JLabel.

Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
import java.util.Calendar;
import javax.swing.*;

public class MainWindow extends JFrame implements MouseMotionListener{
    /*Class-wide variables*/
    private GraphicsDevice gDevice =
            GraphicsEnvironment.getLocalGraphicsEnvironment()
            .getDefaultScreenDevice();
    private DisplayMode dMode = gDevice.getDisplayMode();
    private Calendar calendar = Calendar.getInstance();
    private String hour = String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
    private String minute = String.valueOf(calendar.get(Calendar.MINUTE));
    private JLabel clockLabel;
    public GapVisualizer gap;
    public JLabel ist;
    public JLabel soll;
    private MediaTracker mt = null;
    double modifier = 0.6;

    public void createMainWindow(){
        mt = new MediaTracker(this);
        Image istImage =
                new ImageIcon(this.getClass().getResource("ist.png")).getImage();
        Image sollImage =
                new ImageIcon(this.getClass().getResource("soll.png")).getImage();
        mt.addImage(istImage, 1);
        mt.addImage(sollImage, 2);
        try{ mt.waitForAll(); } catch (InterruptedException ex){}
        soll = new JLabel(new ImageIcon(sollImage));
        ist = new JLabel(new ImageIcon(istImage));
        gap = new GapVisualizer(new Rectangle(100, 45, 190, 470));

        //setResizable(false);
        //setUndecorated(true);
        setSize(1024, 756); 

        /*Definition top panel*/
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout(0, 0));
        topPanel.setPreferredSize(
                new Dimension(dMode.getWidth(), 63));
        topPanel.setBackground(Color.green);
                
        JLabel cardeaLogoPanel = new JLabel("Logo");
        
        JPanel devicePanel = new JPanel();
        devicePanel.setBackground(Color.green);
        JLabel deviceLabel = new JLabel("Butterfliege");
        devicePanel.add(deviceLabel);
        
        JPanel clockPanel = new JPanel();
        clockPanel.setBackground(Color.green);
        clockPanel.setPreferredSize(new Dimension(150, 63));
        if (hour.length() == 1) hour = "0" + hour;
        if (minute.length() == 1) minute = "0" + minute;
        clockLabel = new JLabel(hour + ":"+ minute);
        clockPanel.add(clockLabel);
        
        topPanel.add(cardeaLogoPanel, BorderLayout.WEST);
        topPanel.add(devicePanel);
        topPanel.add(clockPanel, BorderLayout.EAST);

        /*Definition center panel*/
        JPanel centerPanel = new JPanel();
        centerPanel.setLayout(null);
        centerPanel.setBackground(Color.orange);

        JLabel balken = new JLabel(new ImageIcon("/balken.png"));
        balken.setBounds(100, 45, 192, 476);
        soll.setBounds(125, 411, 146, 73);
        ist.setBounds(158, 450, 81, 31);
        gap.setBounds(new Rectangle(166, 45, 190, 470));

        Timer t1 = null;
        t1 = new Timer(1,new ActionListener() {
            int y = 411;
            boolean moveDown = false;

            public void actionPerformed(ActionEvent e) {
                if (y > 85 && !moveDown) {
                y -= 2;
                if (y <= 85){
                    moveDown = true;
                    Global.flag1 = true;
                }
            } else if (moveDown) {
                y += 2;
                if (y > 411){
                    moveDown = false;
                    Global.flag1 = true;
                    y -= 2;
                }
            }
                soll.setLocation(125, y);
            }
        }); t1.start();

        Timer t2 = new Timer(3000,new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Global.flag2 = true;
            }
        });
        new RunMe(t1, t2).startRunMe();
        soll.addComponentListener(new ComponentAdapter() {
            public void componentMoved(ComponentEvent e) {
                Point sollPoint = e.getComponent().getLocation();
                Point istPoint = ist.getLocation();
                Rectangle rect = gap.updatePosition(istPoint, sollPoint,
                        ist.getWidth(), ist.getHeight(), soll.getWidth(),
                        soll.getHeight());
                gap.setBounds(rect);
                gap.setRectangle(rect);
                gap.repaint();
            }
        });
        
        ist.addComponentListener(new ComponentAdapter() {
            public void componentMoved(ComponentEvent e) {
                Point sollPoint = e.getComponent().getLocation();
                Point istPoint = ist.getLocation();
                Rectangle rect = gap.updatePosition(istPoint, sollPoint,
                        ist.getWidth(), ist.getHeight(), soll.getWidth(),
                        soll.getHeight());
                gap.setBounds(rect);
                gap.setRectangle(rect);
                gap.repaint();
            }
        });

        centerPanel.add(gap);
        centerPanel.add(ist);
        centerPanel.add(soll);
        centerPanel.add(balken);
        centerPanel.addMouseMotionListener(this);

        /*Definition bottom panel*/
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS));
        bottomPanel.setPreferredSize(new Dimension(dMode.getWidth(), 20));
        bottomPanel.setBackground(Color.green);

        JLabel versionLabel = new JLabel("Version: 1.0");
        bottomPanel.add(versionLabel);

        /*Compose frame*/
        add(bottomPanel, BorderLayout.SOUTH);
        add(topPanel, BorderLayout.NORTH);
        add(centerPanel, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        /*Update time every 30 sec.*/
        new Timer(30000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                calendar = Calendar.getInstance();
                hour = String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
                minute = String.valueOf(calendar.get(Calendar.MINUTE));
                if (hour.length() == 1) hour = "0" + hour;
                if (minute.length() == 1) minute = "0" + minute;
                clockLabel.setText(hour + ":" + minute);
            }
        }).start();

        /*Set visibility and fullscreen mode*/
        //gDevice.setFullScreenWindow(this);
        setVisible(true);
    }
    public void mouseMoved(MouseEvent e){
        int y = 0;
        if(e.getY() < 89) y = 89;
        else if (e.getY() > 450) y = 450;
        else y = e.getY();
        ist.setLocation(158, y);
    }
    public void mouseDragged(MouseEvent e){}
}

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

public class GapVisualizer extends JLabel{
    private Rectangle rect = null;
    private int maxDistanceCase1 = 365;
    private int maxDistanceCase2 = 322;
    private float modifier = 0.8f;
    
    public GapVisualizer(Rectangle rect){
        this.rect = rect;
    }

    public void setRectangle(Rectangle rect){
        this.rect = rect;
    }
    //Berechnung der Position und Größe des Rechtecks
    public Rectangle updatePosition(Point asIsPoint, Point toBePoint, int asIsWidth,
            int asIsHeight, int toBeWidth, int toBeHeight){
        int rectXAxis = 0;
        int rectYAxis = 0;
        int rectHeight = 0;
        int rectWidth = 0;

        if(toBePoint.y <= asIsPoint.y){
            modifier = (float)(asIsPoint.y - toBePoint.y) / (float)maxDistanceCase1;
            rectWidth = (int)(asIsWidth * modifier);
            rectXAxis = toBePoint.x + (toBeWidth / 2) - (rectWidth / 2);
            rectYAxis = toBePoint.y + (toBeHeight / 2);
            rectHeight = (asIsPoint.y + asIsHeight / 2) - rectYAxis;
            } else{
            modifier = (float)(toBePoint.y - asIsPoint.y) / (float)maxDistanceCase2;
            rectWidth = (int)(asIsWidth * modifier);
            rectXAxis = asIsPoint.x + (asIsWidth / 2) - (rectWidth / 2);
            rectYAxis = asIsPoint.y + (asIsHeight / 2);
            rectHeight = (toBePoint.y + toBeHeight / 2) - rectYAxis;
            }
        return new Rectangle(rectXAxis, rectYAxis, rectWidth, rectHeight);
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillRect(0, 0, (int)rect.getWidth(), (int)rect.getHeight());
    }
}
 
jetzt bist du schon so weit gekommen, und keine Idee wie es weiter geht?
wenn du siehst, dass beide Listener arbeiten, aber nur einer was gutes macht, dann schaue dir doch IM DETAIL an, was die Listener machen,
hier ganz simpel, welches Rectangle sie ausrechnen, der ist-Listener macht da ziemlich Mist (width = 0),
und bei fast gleicher Rechnung muss man nicht lange nach der Ursache suchen:
die Positionen für soll + ist sind falsch,

im ist-Listener ist sowohl
> Point sollPoint = e.getComponent().getLocation();
als auch
> Point istPoint = ist.getLocation();
der ist-Punkt, denn das Event gehört ja zur ist-Komponente


hätte man/ ich bei genauen schauen auch im ersten Posting schon erkennen können,
aber ohne ausführbaren Code ist mir persönlich sowas zu aufwendig, ich wüßte gar nicht was das gap machen soll 😉
 
Zuletzt bearbeitet von einem Moderator:
Ok, das war jetzt peinlich :autsch:
Ja darauf hätte sogar ich kommen können, dass das nicht geht. Mal wieder vor lauter Bäume den Wald nicht gesehen. 😳

Trotzdem vielen Dank!
 

Zurück
Oben