String auf JPanel bewegen

Nortix

Mitglied
Hallo und ein frohes Neues!

Bin gerade dabei mein kleines Programm zu erweitern.
Es wird dabei auf einem JPanel ein Koordinatensystem gezeichnet, in welches Vektoren eingefügt werden können. Jeder Vektor, der übrigens in einer ArrayList gespeichert ist, hat eine Beschriftung. Diese soll der Benutzer nun bewegen können. Ich habe mich schon informiert und bekomme es hin, dass man einen Text bewegen kann.

Java:
public void mousePressed(MouseEvent arg0) {
        bDragged = false;
        Point mousePoint = arg0.getPoint();
        int width = fm.stringWidth("Test");
        int height = fm.getHeight();
        Rectangle rec = new Rectangle(xPos,yPos-height,width,height);
        if(rec.contains(mousePoint)){         
            bTouche = true;
        }
        else{         
            bTouche = false;
        }
    }
    public void mouseReleased(MouseEvent arg0) {
        if (bDragged){
            Point mousePoint = arg0.getPoint(); 
            Graphics2D g = (Graphics2D) this.getGraphics();
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            this.repaint();
        }
    }
    
    public void mouseDragged(MouseEvent arg0){
        if (bTouche){        
            Point mousePoint = arg0.getPoint();        
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            bDragged=true;  
            this.repaint();
        }      
    }
 
    public void mouseMoved(MouseEvent arg0){
        xOld = -1;
        yOld = -1;
    }

Das klappt wunderbar, nur passt es nicht ganz auf mein Problem. Ich habe den Code nun so weit angepasst, dass es meiner Meinung nach möglich sein müsste, die Beschriftungen zu bewegen.
Nun stoße ich aber auf zwei Probleme. Ich möchte die Beschriftung mittig und ein wenig verschoben setzen. Wenn ich das mache, kann ich den Text nicht mehr bewegen. Wenn der Text aber im Koordinatensystem auf (0|0) liegt, kann ich diesen einmalig bewegen. Wenn ich den Text dann loslasse, lässt er sich nicht mehr greifen. Ich nehme an, dass die Rectangles nicht richtig plaziert werden?

Java:
    private int touchedI;
    private int xOld = -1;
    private int yOld = -1;
    private FontMetrics fm = this.getFontMetrics(new Font("Arial",Font.BOLD,10));
    public void mousePressed(MouseEvent evt) {
        bDragged = false;
        Point mousePoint = evt.getPoint();
        for(Vektor v:vektoren){
            int width = fm.stringWidth(v.getName());
            int height = fm.getHeight();
            Rectangle rec = new Rectangle((int) v.getPosition().getX(),(int) v.getPosition().getX()-height,width,height);
            v.setRectangle(rec);
        }
        for(int i=0;i<vektoren.size();i++){
            Rectangle rec = vektoren.get(i).getRectangle();
            if(rec.contains(mousePoint)){         
                bTouche = true;
                
                touchedI=i;
            }
            else{         
                bTouche = false;
            }
        }
    }
    public void mouseReleased(MouseEvent evt) {
        if (bDragged){
            double xPos=vektoren.get(touchedI).getPosition().getX();
            double yPos=vektoren.get(touchedI).getPosition().getY();
            Point mousePoint = evt.getPoint(); 
            Graphics2D g = (Graphics2D) this.getGraphics();
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
                vektoren.get(touchedI).setPosition(new Point2D.Double(xPos,yPos));
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            this.repaint();
        }
    }
    
    public void mouseDragged(MouseEvent evt){
        if (bTouche){        
            double xPos=vektoren.get(touchedI).getPosition().getX();
            double yPos=vektoren.get(touchedI).getPosition().getY();
            Point mousePoint = evt.getPoint();        
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
                vektoren.get(touchedI).setPosition(new Point2D.Double(xPos,yPos));
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            bDragged=true;  
            this.repaint();
        }      
    }
 
    public void mouseMoved(MouseEvent arg0){
        xOld = -1;
        yOld = -1;
    }
private void vektorBeschriftung(Vektor v, Graphics2D g2d){
        if(!vektorBeschriftung){
        }
        else{
            //zoom ist für die Skalierung zuständig. (350|350) ist der Mittelpunkt des Koordinatensystems  in Pixeln

            double mittelPunktX = (v.getEndX()*zoomX+350)-(v.getStartX()*zoomX+350);
            mittelPunktX/=2;
            mittelPunktX+=v.getStartX();
            mittelPunktX+=350 + 10;
            
            double mittelPunktY = (v.getEndY()*zoomX+350)-(v.getStartY()*zoomX+350);
            
            mittelPunktY/=2;
            mittelPunktY-=v.getStartX();
            mittelPunktY=350-mittelPunktY+10;
            v.setPosition(new Point2D.Double(mittelPunktX,mittelPunktY));
            //wenn diese ^ Zeile auskommentiert wird, ist Position auf (0|0) und der Text lässt sich einmalig bewegen
            g2d.drawString(v.getName(), (int) v.getPosition().getX(), (int) v.getPosition().getY());
    }
}

Hinzu kommt noch, dass die Beschriftung mit meiner Berechnung sowieso nicht richtig plaziert wird. Wenn ich einen Vektor mit v=-2|-2 habe, der an (-5|5) startet, wird die Beschriftung auf (-5|-5) gesetzt. Das ist aber ein anderes Problemchen.

Ich hoffe, dass es verständlich erklärt wurde und ihr mir helfen könnt!

Gruß
 
Zuletzt bearbeitet:
poste ein vollständiges Programm,
nur aus dem Code zu analysieren was welche Variable macht (da auch Erklärungen eingespart sind bzw. zumindest "Wenn ich einen Vektor mit v=-2|-2" nicht in Programmvariablen übersetzt ist) ist unnötig aufwendig

ein wichtiger Tipp:
verzichte unbedingt darauf, in mouseReleased/ mouseDragged Code zu wiederholen,
arbeite evtl. nur in mouseDragged, in released gar nichts tun zur Bewegung,
notfalls eine gemeinsame Methode von beiden Stellen aufrufen
 
Java:
    private int touchedI; //Index des berührten Vektors
    private int xOld = -1;
    private int yOld = -1;
    private FontMetrics fm = this.getFontMetrics(new Font("Arial",Font.BOLD,10));
    public void mousePressed(MouseEvent evt) {
        bDragged = false;
        Point mousePoint = evt.getPoint();
        for(Vektor v:vektoren){
            int width = fm.stringWidth(v.getName()); //getName ist die Beschriftung des Vektors
            int height = fm.getHeight();
            Rectangle rec = new Rectangle((int) v.getPosition().getX(),(int) v.getPosition().getX()-height,width,height); //getPosition ist die Position der Beschriftung als Point2D gespeichert
            v.setRectangle(rec); //das Rectangleobjekt wird im Vektor gespeichert
        }
        bTouche=false;
        for(int i=0;i<vektoren.size();i++){
            Rectangle rec = vektoren.get(i).getRectangle();
            //die Rectangles der Vektoren werden geprüft, ob sie den Mauspunkt beinhalten
            if(rec.contains(mousePoint)){         
                bTouche = true;
                touchedI=i;
                //hier war vorher noch ein Fehler, da bTouche immer überschrieben wurde
            }
        } 
            
        }
    }
    public void mouseReleased(MouseEvent evt) {
        if (bDragged){
            double xPos=vektoren.get(touchedI).getPosition().getX();
            double yPos=vektoren.get(touchedI).getPosition().getY();
            Point mousePoint = evt.getPoint(); 
            Graphics2D g = (Graphics2D) this.getGraphics();
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
                vektoren.get(touchedI).setPosition(new Point2D.Double(xPos,yPos));
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            this.repaint();
        }
    }
    
    public void mouseDragged(MouseEvent evt){
        if (bTouche){        
            double xPos=vektoren.get(touchedI).getPosition().getX();
            double yPos=vektoren.get(touchedI).getPosition().getY();
            Point mousePoint = evt.getPoint();        
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
                vektoren.get(touchedI).setPosition(new Point2D.Double(xPos,yPos));
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            bDragged=true;  
            this.repaint();
        }      
    }
 
    public void mouseMoved(MouseEvent arg0){
        xOld = -1;
        yOld = -1;
    }
private void vektorBeschriftung(Vektor v, Graphics2D g2d){
        if(!vektorBeschriftung){
        }
        else{
            //zoom ist für die Skalierung zuständig. (350|350) ist der Mittelpunkt des Koordinatensystems  in Pixeln

            double mittelPunktX = (v.getEndX()*zoomX+350)-(v.getStartX()*zoomX+350);
            mittelPunktX/=2;
            mittelPunktX+=v.getStartX();
            mittelPunktX+=350 + 10;
            
            double mittelPunktY = (v.getEndY()*zoomX+350)-(v.getStartY()*zoomX+350);
            
            mittelPunktY/=2;
            mittelPunktY-=v.getStartX();
            mittelPunktY=350-mittelPunktY+10;
            v.setPosition(new Point2D.Double(mittelPunktX,mittelPunktY));
            //wenn diese ^ Zeile auskommentiert wird, ist Position auf (0|0) und der Text lässt sich einmalig bewegen
            g2d.drawString(v.getName(), (int) v.getPosition().getX(), (int) v.getPosition().getY());
    }
}

Mein ganzes Programm kann ich nicht posten, da es mehrere tausend Zeilen umfasst.

Habe jetzt den Quelltext ein wenig angepasst und kommentiert.
Ein Vektor wird vereinfacht so erstellt:
Code:
public Vektor(double startX, double startY, double endX, double endY, String name)
Dabei steht
Code:
startX
für die X-Koordinate an dem der Vektor startet. Die anderen Variablen sind analog dazu, also wird der Vektor mit seinem Startpunkt
Code:
startX|startY
und seinem Endpunkt
Code:
endX|endY
eingelesen.
Ein Vektor mit v=2|-2, der an (-5|5) startet wäre also
Code:
Vekor(-5, 5, -3, 3, name)

Auf dem Bild sieht man sehr gut die falsch positionierte Beschriftung:

vektor.jpg



Ist es jetzt verständlicher?
 
wenn du nur 100 von 1000 und mehr Zeilen postest, was soll man dann von den anderen 900+ halten?
wenn sie nicht wichtig sind, dann lasse sie doch einfach weg,
ergänze den geposteten Code neu um ein JFrame, ein Panel mit paint-Methode, eine main-Methode und was immer alles fehlt,

das Zeichnen des Koordinatensystems ist nicht so wichtig, aber schadet ja auch nicht

bzw. wird eigentlich umso wichtiger,
ich habe mir jetzt etwas mehr angeschaut und vermute deine Fehler in Code wie

Java:
            double mittelPunktY = (v.getEndY()*zoomX+350)-(v.getStartY()*zoomX+350);
            
            mittelPunktY/=2;
            mittelPunktY-=v.getStartX();
            mittelPunktY=350-mittelPunktY+10;
            v.setPosition(new Point2D.Double(mittelPunktX,mittelPunktY));
was soll man dazu groß sagen außer dass der aktuelle Wert von zoom anscheinend unbekannt ist, vielleicht 1,
gibt es neben zoomX auch zoomY?
schaue dir genau an, was in jeder einzelnen Zeile berechnet wird,

ohne Programm, ohne Ausprobieren wiederum unnötig schwere Kopfarbeit
 
Danke für deine Antwort.

zoomX und zoomY sind die Skalierungen des Koordinatensystems. Wenn ich ein Koordinatensystem haben möchte, das von x=+-10 geht, wird der Betrag genommen und es findet eine Berechnung statt. Dabei wird die Größe der Achsenabschnitte in Pixeln durch diesen Betrag geteilt. Als Code:
Code:
setZoomX(350/x-3);
. Es wird noch -3 gerechnet, da man sonst den Wert 10 in diesem Falle nicht sehen würde, da er genau am Rand des Panels liegt. Ich habe mein Programm nun auf das geringste runtergebrochen und hoffe, dass es jetzt besser ist.

Java:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.util.ArrayList;
import java.awt.event.MouseEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Line2D;

/** 
 * @author Vladislav Schmidt
 */

public final class Koordinatensystem extends JPanel implements MouseListener , MouseMotionListener{
    
    private int zoomX; 
    private int zoomY;
    private Font font;
    private boolean bTouche;
    private boolean bDragged;
    private FontMetrics fm;
    private ArrayList<Vektor> vektoren;
    
    public Koordinatensystem(){
        vektoren = new ArrayList<Vektor>();
        vektoren.add(new Vektor(0,0,2,3,"v1"));
        vektoren.add(new Vektor(-5,5,-3,3,"v2"));

        zoomX=33;
        zoomY=33;
        font = new Font("Arial", Font.BOLD,10);
        bTouche=false;
        bDragged=false;
        fm = getFontMetrics(font);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }
     
    public void mouseClicked(MouseEvent arg0) {}
    public void mouseEntered(MouseEvent arg0) {}
    public void mouseExited(MouseEvent arg0) {}
    
    
    private int touchedI;
    private int xOld = -1;
    private int yOld = -1;
    public void mousePressed(MouseEvent evt) {
        bDragged = false;
        Point mousePoint = evt.getPoint();
        for(Vektor v:vektoren){
            int width = fm.stringWidth(v.getName());
            int height = fm.getHeight();
            Rectangle rec = new Rectangle((int) v.getPosition().getX(),(int) v.getPosition().getX()-height,width,height);
            v.setRectangle(rec);
        }
        bTouche=false;
        for(int i=0;i<vektoren.size();i++){
            Rectangle rec = vektoren.get(i).getRectangle();
            if(rec.contains(mousePoint)){         
                bTouche = true;
                touchedI=i;
            }
        }
    }
    public void mouseReleased(MouseEvent evt) {
        if (bDragged){
            double xPos=vektoren.get(touchedI).getPosition().getX();
            double yPos=vektoren.get(touchedI).getPosition().getY();
            Point mousePoint = evt.getPoint(); 
            Graphics2D g = (Graphics2D) this.getGraphics();
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
                vektoren.get(touchedI).setPosition(new Point2D.Double(xPos,yPos));
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            this.repaint();
        }
    }
    public void mouseDragged(MouseEvent evt){
        if (bTouche){        
            double xPos=vektoren.get(touchedI).getPosition().getX();
            double yPos=vektoren.get(touchedI).getPosition().getY();
            Point mousePoint = evt.getPoint();        
            if((xOld != -1)&&(yOld!= -1)){
                int dx = xOld - mousePoint.x;
                int dy = yOld - mousePoint.y;
                xPos -= dx;
                yPos -= dy;
                vektoren.get(touchedI).setPosition(new Point2D.Double(xPos,yPos));
            }
            xOld = mousePoint.x;
            yOld = mousePoint.y;
            bDragged=true;  
            this.repaint();
        }      
    }
    public void mouseMoved(MouseEvent arg0){
        xOld = -1;
        yOld = -1;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        
        g.drawLine(350, 0, 350, 700);
        g.drawLine(0,350,700,350);
        
        koordinatenSystemStriche(g);
        vektorenZeichnen(g);
    }

    public void koordinatenSystemStriche(Graphics g){
        for(int i=1; i<=(350/zoomX); i++){
            //positiv Striche  X
            g.drawLine(350+(i*zoomX), 350-5, 350+(i*zoomX), 350+5);
        }
        for(int i=((350/zoomX)*-1); i<=-1; i++){
            //negativ Striche X
            g.drawLine(350+(i*zoomX), 350+5, 350+(i*zoomX), 350-5);
        }
        for(int i=1; i<=(350/zoomY); i++){
            //positiv Striche Y
            g.drawLine(350-5, 350-(i*zoomY), 350+5, 350-(i*zoomY));
        }
        for(int i=((350/zoomY)*-1); i<=-1; i++){
            //negativ Striche Y
            g.drawLine(350-5, 350-(i*zoomY), 350+5, 350-(i*zoomY));
        }
    }
    public void vektorenZeichnen(Graphics g){
        for(Vektor v:vektoren){
            double[] werte=vektorBerechnen(v); 
            Graphics2D g2d = (Graphics2D) g;
            Shape shape = new Line2D.Double(werte[0], werte[1], werte[2], werte[3]);
            g2d.draw(shape);
            vektorBeschriftung(v,g2d);
        }
    }
    private double[] vektorBerechnen(Vektor v){
        double tempEndX, tempEndY, tempStartX, tempStartY;
        tempEndX=v.getEndX();
        tempEndY=v.getEndY();
        tempStartX=v.getStartX();
        tempStartY=v.getStartY();
        tempEndX*=zoomX;
        tempEndY*=zoomY;
        tempStartX*=zoomX;
        tempStartY*=zoomY;
        tempEndX+=tempStartX;
        tempEndY+=tempStartY;
        tempEndY*=-1;
        tempStartY*=-1;
        tempEndX+=350;
        tempEndY+=350;
        tempStartX+=350;
        tempStartY+=350;
        double[] werte={tempStartX,tempStartY,tempEndX,tempEndY};
        
        return werte;
    }
    private void vektorBeschriftung(Vektor v, Graphics2D g2d){
        g2d.setFont(font);
        
        double mittelPunktX = (v.getEndX()*zoomX+350)-(v.getStartX()*zoomX+350);
        mittelPunktX/=2;
        mittelPunktX+=v.getStartX();
        mittelPunktX+=350+10;
         
        double mittelPunktY = (v.getEndY()*zoomX+350)-(v.getStartY()*zoomX+350);
            
        mittelPunktY/=2;
        mittelPunktY-=v.getStartX();
        mittelPunktY=350-mittelPunktY+10;
        v.setPosition(new Point2D.Double(mittelPunktX,mittelPunktY));
        g2d.drawString(v.getName(), (int) v.getPosition().getX(), (int) v.getPosition().getY());
            
    }
    
    public static void main(String[] args){
        JFrame frame = new JFrame();
        JPanel koordinatensystem = new Koordinatensystem();
        koordinatensystem.setSize(700,700);
        frame.setSize(700,700);
        frame.add(koordinatensystem);
        frame.setVisible(true);
    }


    private class Vektor {
        private String name;
        private double endX; 
        private double endY;
        private double startX;
        private double startY;
        private Point2D position;
        private Rectangle rectangle;
    
        public Vektor(double startX, double startY, double endX, double endY, String name){
            this.startX=startX;
            this.startY=startY;
            this.endX=endX;
            this.endY=endY;
            this.name= name;
            position = new Point2D.Double(startX*33+350, startY*33+350);
        }
        public double getEndX(){ return endX;}
        public double getEndY(){ return endY;}
        public double getStartX(){ return startX;}
        public double getStartY(){ return startY;}
        public String getName(){ return name;}
        public Point2D getPosition(){ return position;}
        public Rectangle getRectangle(){ return rectangle;}
    
        public void setName(String name){
            this.name=name;
        }
        public void setEndX(double x){
            endX=x;
        }
        public void setEndY(double y){
            endY=y;
        }
        public void setPosition(Point2D position){
            this.position=position;
        }
        public void setRectangle(Rectangle rec){
            rectangle=rec;
        }
    }
}

Wenn man in der Methode
Code:
vektorBeschriftung()
die Zeile
Code:
v.setPosition(new Point2D.Double(mittelPunktX,mittelPunktY));
auskommentiert, lässt sich v1 problemlos bewegen. Aber nur einmal.
 
> Rectangle rec = new Rectangle((int) v.getPosition().getX(),(int) v.getPosition().getX()-height,width,height);

hier musst du auch mal getY() verwenden,

Tipp: das Rectangle zentral(er) berechnen/ speichern, ausgeben, und auch gleich malen lassen,
dann siehst du eher, wohin du klicken darfst

alles mit einem fertigen Programm schnell gemacht im Fehlerfall

-------

danach ist hinderlich, dass jedes vektorBeschriftung() beim Zeichnen die Position gleich wieder überschreibt,
anderenfalls kann man nun die Beschriftung verschieben, der Vector selber reagiert darauf nicht,
Arbeit an Arbeit
 
Ach, was ein blöder Fehler! Natürlich muss man getY() verwenden. Das habe ich wahrscheinlich im Eifer des Gefechts falsch getippt. Jetzt kann man auch beliebig oft verschieben.

Das Setzen der Beschriftung muss ich noch mal überarbeiten und anders lösen. Dennoch danke ich dir vielmals, auch wenn es schwer mit mir ist!

Falls ich weitere Fragen habe, werde ich mich wieder melden.
 

Zurück
Oben