repaint wird nicht während Druck auf Maustaste ausgeführt.

Crian

Top Contributor
In folgendem kleinen, ausführbaren Beispiel ist das Problem gut zu sehen.

Was passieren soll: Der Kreis soll per Mausklick in ihn hinein und Ziehen der Maus bewegt werden. Beim loslassen des Mausknopfes soll er nicht weiter mit der Maus mitwandern.

Was passiert: Der Kreis wird beim loslassen der Maus an der richtigen neuen Position gezeichnet. Während der Knopf 1 der Maus gedrückt ist, wird nicht neu gezeichnet. Auch die ausgegebene Mausposition wird nicht aktualisiert.

Ich vermute, dass das
Code:
repaint()
im
Code:
MouseMotionAdapter
sich auf die falsche Komponente bezieht.

Java:
package ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MovePointWithMouse extends JPanel implements MouseListener {

    private static final long serialVersionUID = -7626346552604778427L;

    /** Zugrundeliegender Frame in dem der Spielpanel läuft. */
    private JFrame frame;

    /** X-Koordinate der linken oberen Ecke des Punktes. */
    private int x;

    /** Y-Koordinate der linken oberen Ecke des Punktes. */
    private int y;

    /** Durchmesser des Punktes */
    private int diameter;

    /** Gibt an, ob der Kreis gerade mit der Maus bewegt werden soll. */
    private boolean circleSticksAtMouse;

    /** X-Koordinate der aktuellen Mausposition. */
    private int mouseActualX;

    /** Y-Koordinate der aktuellen Mausposition. */
    private int mouseActualY;


    /**
     * Konstruktor
     *
     * @param width
     *            Breite des Spielpanels.
     * @param height
     *            Höhe des Spielpanels.
     */
    public MovePointWithMouse(int width, int height) {
        circleSticksAtMouse = false;
        diameter = 300;
        setCircleKoordinates(width/2, height/2);

        this.setPreferredSize(new Dimension(width, height));
        this.setBackground(Color.WHITE);
        this.addMouseListener(this);
        this.addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseMoved(final MouseEvent e) {
                mouseActualX = e.getX();
                mouseActualY = e.getY();
                if (circleSticksAtMouse) {
                    setCircleKoordinates(mouseActualX, mouseActualY);
                }
                repaint();
            }
        });

        frame = new JFrame("Move Point");
        frame.setLocation(100, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);

        frame.pack();
        frame.setVisible(true);
    }

    /**
     * Setzt die Kreiskoordinaten, die sich auf die linke, obere Ecke beziehen,
     * nach Koordinaten, die den Mittelpunkt des Kreises bezeichnen.
     *
     * @param centerX
     *            X-Koordinate des Mittelpunktes
     * @param centerY
     *            Y-Koordinate des Mittelpunktes
     */
    private void setCircleKoordinates(int centerX, int centerY) {
        int radius = diameter/2;
        x = centerX - radius;
        y = centerY - radius;
    }

    /** Auf Panel zeichnen. */
    @Override
    public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);

        graphics.setColor(Color.BLUE);
        graphics.drawString("Mouseposition: " + mouseActualX + ", "
                + mouseActualY, 10, 20);

        graphics.setColor(Color.BLACK);
        graphics.fillOval(x, y, diameter, diameter);
    }

    @Override
    public void mouseClicked(MouseEvent event) {
    }

    @Override
    public void mouseEntered(MouseEvent event) {
    }

    @Override
    public void mouseExited(MouseEvent event) {
        if (circleSticksAtMouse) {
            circleSticksAtMouse = false;
            Point point = event.getPoint();
            int mouseX = (int) point.getX();
            int mouseY = (int) point.getY();
            setCircleKoordinates(mouseX, mouseY);
            repaint();
        }
    }

    @Override
    public void mousePressed(MouseEvent event) {
        if (event.getButton() == MouseEvent.BUTTON1) {
            if (!circleSticksAtMouse) {
                Point point = event.getPoint();
                int mouseX = (int) point.getX();
                int mouseY = (int) point.getY();
                if (trifftKreis(mouseX, mouseY)) {
                    circleSticksAtMouse = true;
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent event) {
        if (event.getButton() == MouseEvent.BUTTON1) {
            if (circleSticksAtMouse) {
                circleSticksAtMouse = false;
                Point point = event.getPoint();
                int mouseX = (int) point.getX();
                int mouseY = (int) point.getY();
                setCircleKoordinates(mouseX, mouseY);
                repaint();
            }
        }
    }

    /**
     * Ermittelt, ob die übergebenen Koordinaten im Kreis liegen.
     *
     * @param xx X-Koordinate
     * @param yy Y-Koordinate
     * @return Wahrheitswert.
     */
    private boolean trifftKreis(int xx, int yy) {
        /*
         * Falls der Klick außerhalb des umschließenden Quadrats ist, gleich
         * abbrechen:
         */
        if (xx < x || xx > x + diameter || yy < y || yy > y + diameter) {
            return false;
        }

        /* Mittelpunkt des Kreises bestimmen: */
        int radius = diameter/2;
        int mx = x + radius;
        int my = y + radius;

        /* Nach Pythagoras: */
        int dx = xx-mx; // Vorzeichen egal, da quadriert wird
        int dy = yy-my; // Vorzeichen egal, da quadriert wird
        if (dx*dx + dy*dy <= radius*radius) {
            return true;
        }
        else {
            return false;
        }
    }

    /** Startpunkt des Programms. */
    public static void main(String[] args) {
        new MovePointWithMouse(800, 600);
    }

}
 
Zuletzt bearbeitet:
mouseMoved() ist nur für nicht-geklickte Maus zuständig,
du brauchst noch mouseDragged(),

-----

du solltest dir beim Klick in den Kreis den Versatz zwischen der Mausposition und den Mittelpunkt des Kreises merken,
und bei jedem Neusetzen wieder einbeziehen,
so kannst du den Kreis sauber versetzen, ohne dass dessen Mittelpunkt genau zur Maus springt
(edit: was du bisher wohl noch gar nicht gemerkt hast, nur mit Sprung zum Ende)
 
Zuletzt bearbeitet von einem Moderator:
Außerdem solltest du die vorsichtig sein, bei Variablennamen. int x und int y gibts bereits in der Klasse Component von der deine Klasse erbt. Das kann zu lustigen Resultaten führen.
 
Diese privaten Variablen sind eigentlich unkritisch. Wenn man dann aber noch ein "getX()" schreibt, bei dem die eigene zurückgegeben wird, haut's ihn natürlich raus...
 
Danke!

Mit

Java:
            public void mouseDragged(final MouseEvent e) {
                mouseActualX = e.getX();
                mouseActualY = e.getY();
                if (circleSticksAtMouse) {
                    setCircleKoordinates(mouseActualX, mouseActualY);
                }
                repaint();
            }

war es gelöst. Und ich hab x und y sicherheitshalber umbenannt.
 

Zurück
Oben