Problem mit Koordinaten - Objekte werden nicht an gewünschter Stelle gezeichnet

Marco7757

Aktives Mitglied
Ich arbeite an einem Graph-System für eines meiner Projekte. Sehr wahrscheinlich gibt es das schon, doch es stellt eine Herausforderung dar, die ich gerne bestehen würde.

Allerdings tun sich mir im Moment Rätsel auf, die ich weder logisch noch mathematisch nachvollziehen kann.

In folgendem Bild seht ihr mein bisheriges Programm mit der GraphArea (schwarz), dem GraphHintergrund (weiss, rechts und unten bündigmit dem schwarzen Rechteck), auf dem die Daten angezeigt werden, sowie die x/y-Achse und ein Rahmen oben und rechts (grau), nicht zu verwechseln mit dem jFrame-grau im Hintergrund.

graphat.png


Die Rechtecke und Linien werden mit folgendem Code gezeichnet:
Java:
g2.fill(new Rectangle2D.Double(graphArea[0], graphArea[1], graphArea[2], graphArea[3])); //schwarzer hintergrund
g2.fill(new Rectangle2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
//weiss, über diesem Hintergrund sollen mal die Daten stehen, er ist etwas kleiner, damit man Titel und Beschriftungen anzeigen kann
Sys("x: "+(graphArea[2]-leftSpace)+" y: "+(graphArea[3]-leftSpace));
//Ausgabe in der Konsole:
//x: 515 y: 380

g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[0]+leftSpace, graphArea[3]-leftSpace));
g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[3]-leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
g2.draw(new Line2D.Double(graphArea[2]-leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[1]+leftSpace));
Sys("x: "+(graphArea[2]-leftSpace)+" y: "+(graphArea[3]-leftSpace));
//Ausgabe in der Konsole:
//x: 515 y: 380
//Diese vier Linien bilden den Rahmen, die kleinen Striche sowie die Zahlen, die auf dem Bild zu sehen sind, werden erst später hinzugefügt. Sie zeigen die Pixel jedes Striches von oben her an.

public static void Sys(String text) {
	System.out.println(text);
}

Wer sich den Code nun etwas aufmerksam angeschaut wird feststellen, dass die Linien GENAU DIE GLEICHEN Koordinaten haben wie das Rechteck für den GraphAreaHintergrund. Wie kommt es aber, dass dieses Rechteck grösser ist, sowohl in der Breite als auch in der Höhe?
Der Array
Code:
graphArea[0-3]
wird am Anfang vom User festgelegt und danach NICHT mehr verändert.
Java:
jC.setGraphArea(X1, Y1, X2, Y2);
jC.setGraphArea(10, 10, 500, 410);
Code:
leftSpace
legt den Abstand zwischen dem inneren zum äusseren Rechteck fest. Im Beispiel ist
Code:
leftSpace = 30
, was dann 30 Pixeln entspricht / enstsprecheh sollte.
Da leftSpace bei der Angabe von grösseren Werten bei der Y-Achse nicht reicht, werden sämtliche X-Werte schon beim festlegen des GraphArea-Arrays um den gewüscnhten Platz nach rechts verschoben, in meinem Beispiel 45 Pixel.

Daraus folgt:
Grosses Rechteck (schwarz) (55, 10) bis (545, 410)
Kleines Rechteck (weiss) (85, 40) bis (515, 380)
Linien (grau)
y-Achse (85, 40) bis (85, 380)
x-Achse (85, 380) bis (515, 380)


Wieso sind die Achsen nicht gleich lang wie das innere Rechteck, bzw. wieso wird das weisse Rechteck nicht schön innerhalb der Achsen und der Rahmenlinien gezeichnet?
 
Zuletzt bearbeitet:
Schwer nachzuvollziehen. Poste mal ein KSKB. Im Moment klingt das, als könnten irgendwo Koordinaten und eine Breite durcheinandergekommen sein (grawLine(x0,y0,x1,y1) vs. drawRect(x,y,w,h)), oder beim Rechteck ein Abstand nicht (doppelt) einberechnet sein
g.drawLine(x0+space,y, x1-space,y); vs
g.drawRect(x0+space,y, w-2*space,h);
aber sicher bin ich da nicht....
 
Ich hoffe es ist nicht zu ausführlich geraten, aber hier ist mein KSKB.

Java:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

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


public class jChart extends JPanel {

    private static final long serialVersionUID = 1L;
    
    private int[] graphArea = new int[4];
    private int plusSpaceForWriting = 45;
    private int leftSpace = 30;
    private Graphics2D g2;
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        jChart jC = new jChart();
        jC.setGraphArea(10, 10, 500, 410);
        JFrame jF = new JFrame();
        JPanel graphicPanel = new JPanel();
        graphicPanel.add(jC);
        jF.add(graphicPanel);
        jF.setVisible(true);
        jF.setSize(800, 600);
    }
    
    public void setGraphArea(int X1, int Y1, int X2, int Y2) {
        this.graphArea[0] = X1+plusSpaceForWriting;
        this.graphArea[1] = Y1;
        this.graphArea[2] = X2+plusSpaceForWriting;
        this.graphArea[3] = Y2;
    }
    
    public void drawGraphArea(int r, int g, int b) {
        g2.setPaint(new Color(r, g, b));
        g2.fill(new Rectangle2D.Double(this.graphArea[0], this.graphArea[1], this.graphArea[2], this.graphArea[3]));
    }
    
    public void paintComponent(Graphics g) {
        g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        setSize(660, 460);
        setBackground(new Color(250, 250, 250));
        drawGraphArea(0, 0, 0);
        drawScale("SCALE_NORMAL", 150, 150, 150, 10);
    }

    public void drawScale(String scaleMode, int r, int g, int b, double yAxisRows) {
        g2.setPaint(new Color(255, 255, 255));
        g2.fill(new Rectangle2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
        if(scaleMode=="SCALE_NORMAL") {
            g2.setPaint(new Color(r, g, b));
            g2.setFont(new Font("Helvetica", 0, 15));
            g2.drawString("test", (graphArea[2]-graphArea[0])/2, graphArea[1]+(leftSpace/2));
            //y-axis
            double difBetweenRenderY1Y2 = (graphArea[3]-leftSpace)-(graphArea[1]+leftSpace);
            double difBetweenRenderY1Y2MinusScaleLines = difBetweenRenderY1Y2-yAxisRows;
            while((difBetweenRenderY1Y2MinusScaleLines%yAxisRows)!=0) {
                graphArea[3]++;
                difBetweenRenderY1Y2 = (graphArea[3]-leftSpace)-(graphArea[1]+leftSpace);
                difBetweenRenderY1Y2MinusScaleLines = difBetweenRenderY1Y2-yAxisRows;
            }
            double difPixel = Math.abs(difBetweenRenderY1Y2/yAxisRows); //abs = absolute value, betrag
            
            g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[0]+leftSpace, graphArea[3]-leftSpace));
            g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[3]-leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
            g2.setPaint(new Color(226, 226, 226));
            g2.draw(new Line2D.Double(graphArea[2]-leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
            g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[1]+leftSpace));
            g2.setPaint(new Color(r, g, b));
            
            g2.setFont(new Font("Helvetica", 0, 10));
            
            for(int i=0;i<yAxisRows;i++) {
                g2.draw(new Line2D.Double(graphArea[0]+leftSpace-5, graphArea[1]+leftSpace+i*difPixel, graphArea[0]+leftSpace-1, graphArea[1]+leftSpace+i*difPixel));
                g2.drawString(""+(graphArea[1]+leftSpace+i*difPixel), graphArea[0]-plusSpaceForWriting, (int) (graphArea[1]+leftSpace+i*difPixel+4));
            }
        
        }
    }
}

Ich hoffe es hilft bei der Problemlösung!
 
Meine beiden Vermutungen waren richtig. Und was man mit Sicherheit sagen kann: So wird das nix :noe: Versuch' mal das ganze einen Hauch übersichtlicher zu machen... ( difBetweenRenderY1Y2MinusScaleLines :autsch: ?! )

Java:
// From [url]http://www.java-forum.org/java-basics-anfaenger-themen/106370-problem-koordinaten-objekte-gewuenschter-stelle-gezeichnet.html#post679651[/url]
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

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


public class jChart extends JPanel {

    private static final long serialVersionUID = 1L;

    private int[] graphArea = new int[4];
    private int plusSpaceForWriting = 45;
    private int leftSpace = 30;
    private Graphics2D g2;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        jChart jC = new jChart();
        jC.setGraphArea(10, 10, 500, 410);
        JFrame jF = new JFrame();
        JPanel graphicPanel = new JPanel(new GridLayout(1,1));
        graphicPanel.add(jC);
        jF.getContentPane().setLayout(new GridLayout(1,1));
        jF.getContentPane().add(graphicPanel);
        jF.setSize(800, 600);
        jF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jF.setVisible(true);
    }

    public void setGraphArea(int X1, int Y1, int X2, int Y2) {
        this.graphArea[0] = X1+plusSpaceForWriting;
        this.graphArea[1] = Y1;
        this.graphArea[2] = X2+plusSpaceForWriting;
        this.graphArea[3] = Y2;
    }

    public void drawGraphArea(int r, int g, int b) {
        g2.setPaint(new Color(r, g, b));
        g2.fill(new Rectangle2D.Double(this.graphArea[0], this.graphArea[1], this.graphArea[2], this.graphArea[3]));
    }

    public void paintComponent(Graphics g) {
        g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //setSize(660, 460);
        setBackground(new Color(250, 250, 250));
        drawGraphArea(0, 0, 0);
        drawScale("SCALE_NORMAL", 150, 150, 150, 10);
    }

    public void drawScale(String scaleMode, int r, int g, int b, double yAxisRows) {
        g2.setPaint(new Color(255, 255, 255));

        // Das besagte *2 am Ende...
        g2.fill(new Rectangle2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace*2, graphArea[3]-leftSpace*2));

        System.out.println("Fill "+new Rectangle2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace*2, graphArea[3]-leftSpace*2));

        if(scaleMode.equals("SCALE_NORMAL")) {
            g2.setPaint(new Color(r, g, b));
            g2.setFont(new Font("Helvetica", 0, 15));
            g2.drawString("test", (graphArea[2]-graphArea[0])/2, graphArea[1]+(leftSpace/2));
            //y-axis
            double difBetweenRenderY1Y2 = (graphArea[3]-leftSpace)-(graphArea[1]+leftSpace);
            double difBetweenRenderY1Y2MinusScaleLines = difBetweenRenderY1Y2-yAxisRows;
            while((difBetweenRenderY1Y2MinusScaleLines%yAxisRows)!=0) {
                graphArea[3]++;
                difBetweenRenderY1Y2 = (graphArea[3]-leftSpace)-(graphArea[1]+leftSpace);
                difBetweenRenderY1Y2MinusScaleLines = difBetweenRenderY1Y2-yAxisRows;
            }
            double difPixel = Math.abs(difBetweenRenderY1Y2/yAxisRows); //abs = absolute value, betrag

            g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[0]+leftSpace, graphArea[3]-leftSpace));
            g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[3]-leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace));
            g2.setPaint(new Color(255, 126, 126));

            // Bogus:
            Line2D.Double xxx = new Line2D.Double(graphArea[2]-leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[3]-leftSpace);
            System.out.println("Draw "+xxx.getP1()+" "+xxx.getP2());
            g2.draw(xxx);

            g2.draw(new Line2D.Double(graphArea[0]+leftSpace, graphArea[1]+leftSpace, graphArea[2]-leftSpace, graphArea[1]+leftSpace));
            g2.setPaint(new Color(r, g, b));

            g2.setFont(new Font("Helvetica", 0, 10));

            for(int i=0;i<yAxisRows;i++) {
                g2.draw(new Line2D.Double(graphArea[0]+leftSpace-5, graphArea[1]+leftSpace+i*difPixel, graphArea[0]+leftSpace-1, graphArea[1]+leftSpace+i*difPixel));
                g2.drawString(""+(graphArea[1]+leftSpace+i*difPixel), graphArea[0]-plusSpaceForWriting, (int) (graphArea[1]+leftSpace+i*difPixel+4));
            }

        }
    }
}
 
Verstehe ich überhaupt nicht ...
Über die Übersichtlichkeit lässt sich natürlich streiten, aber wenn man so schnell schnell ein kleines Programm zusammenkopiert geht diese halt verloren ...

In meinem ganzen Code habe ich kein
Code:
leftSpace*2
. Woher hast du denn das?
Wenn ich den von dir bearbeitetn Code ausführe, stimmt das weisse Rechteck noch immer nicht mit den Achsen überein?
Wieso hast du die
Code:
setSize();
beim JPanel rausgelöscht?

Ist es besser
Code:
equals();
zu benutzen statt
Code:
==
? Wenn ja, warum?
 
Verstehe ich überhaupt nicht ...
Über die Übersichtlichkeit lässt sich natürlich streiten, aber wenn man so schnell schnell ein kleines Programm zusammenkopiert geht diese halt verloren ...

Aus eigener leidlicher Erfahrung: Mach' es übersichtlicher. Wenn man Code immer nur weiter""entwickelt"", aber nie aufräumt, dann verrottet(!) er. Die Folge sind Code-Smells, und im schlimmsten Fall ein Ja... äh...Lava Flow.

In meinem ganzen Code habe ich kein
Code:
leftSpace*2
. Woher hast du denn das?
Das weiß ich auch nicht genau. Irgendwo aus meinem Kopf. Wenn man ein Rechteck hat, das 'w' Breit ist, und dort ein weiteres Rechteck reinzeichnen will, so dass man links und rechts einen 'x' cm breiten Rand hat, dann zeichnet man dieses innere Rechteck an der Position 'x', mit einer Breite von 'w-2*x'.

Wenn ich den von dir bearbeitetn Code ausführe, stimmt das weisse Rechteck noch immer nicht mit den Achsen überein?
Da du selbst nicht weißt, was der Code macht, finde ich es etwas zu viel verlangt, dass ICH jetzt versuchen soll, den so weit nachzuvollziehen, dass ich den Fehler finde....

Wieso hast du die
Code:
setSize();
beim JPanel rausgelöscht?
Weil man in der paint-Methode keine Methoden aufrufen sollte, die die Component verändern (diese Veränderung könnte ggf. sogar ein Neuzeichnen auslösen :autsch: ). setSize braucht man nur selten, wenn man ein null-Layout verwendet. Meistens sollte man die bevorzugte Größe mit setPreferredSize setzen, und den Rest dem LayoutManager überlassen.

Ist es besser
Code:
equals();
zu benutzen statt
Code:
==
? Wenn ja, warum?

Man sollte sich insbesondere über den Unterschied zwischen beidem im Klaren sein! (Grundlagenbuch...). Speziell auf Strings bezogen: http://www.java-forum.org/top-fragen/1350-vergleichen-strings.html
 
Leider kann ich mir der Antwort nichts anfangen.

Die Koordinaten x1 und y1 an dem das Rechteck startet stimmen ja mit dem Rahmen überein. Wieso jedoch wird der Rest zu lang gezeichnet?

Sonst noch jemand eine Idee? Ich habe alles versucht, ich bin gescheitert ...
 

Zurück
Oben