Graphen in JPanel malen

MEETyA

Mitglied
Hallo,
ich bin relativer Java-Neuling und stehe vor folgendem Problem. Ich entwickle ein Programm das Werte in ein Koordinatensystem überträgt. Für das Koordinatensystem habe ich fie folgende Vorlage:

Code:
    final int maxX = 4;
    final int maxY = 4;
    final int PAD = 20;
    final int SPAD = 3;
 
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        setBackground(new Color(255,255,255));
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        float xInc = (float)(w - 2*PAD)/(2*maxX);
        float yInc = (float)(h - 2*PAD)/(2*maxY);
        // Draw abcissa.
        g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
        // Draw ordinate.
        g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
        // Draw Axes Labels.
        Font font = g2.getFont().deriveFont(14f);
        g2.setFont(font);
        FontRenderContext frc = g2.getFontRenderContext();
        LineMetrics lm = font.getLineMetrics("0", frc);
        float ascent = lm.getAscent();
        // Abcissa.
        for(int j = 0; j <= 2*maxX; j++) {
            String s = String.valueOf(j);
            float width = (float)font.getStringBounds(s, frc).getWidth();
            float sx = PAD + j*xInc - width/2;
            float sy = h-PAD + lm.getAscent() + SPAD;
            g2.drawString(s, sx, sy);
        }
        // Ordinate.
        int j2 = 2*maxY+1;
        for(int j = 0; j <= 2*maxY; j++) {
            j2--;
            String s = String.valueOf(j);
            float sx = SPAD;
            float sy = PAD + j2*yInc + ascent/2;
            g2.drawString(s, sx, sy);
        }
        g2.setPaint(Color.blue);
        
        // Y-Kooirdinate = PAD + (maxY*2 - WERT)*yInc;
        // X-Koordinate  = WERT*xInc + PAD;
        
        double y1 = PAD + (maxY*2 - 0)*yInc;
        double y2 = PAD + (maxY*2 - 6)*yInc;
        double x1 = 0*xInc + PAD;
        double x2 = 4*xInc + PAD;
        g2.draw(new Line2D.Double(x1,y1,x2,y2));
    }

Mein JPanel heist canvas. Wenn ich nun den Befehl "super.paintComponent(g);" - welcher eine Fehlermeldung ausspuckt - durch canvas.paintComponents(g); ersetze, passiert nichts. Was mache ich falsch?

Danke für eure Hilfe
 
Und was für eine Fehlermeldung wird da wo produziert?
Ich habe deinen Code wie du in ein JPanel gepackt und es klappt ohne Probleme...
Code:
/*
 * Test.java
 *
 * Created on 17. September 2007, 16:47
 */

/**
 *
 * @author  jweckbach
 */
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import java.awt.Dimension;
import javax.swing.JScrollPane;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.Line2D;

public class Test extends JPanel{
    final int maxX = 4;
    final int maxY = 4;
    final int PAD = 20;
    final int SPAD = 3;
    /** Creates a new instance of Test */
    public Test() {
                
    }
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        setBackground(new Color(255,255,255));
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        float xInc = (float)(w - 2*PAD)/(2*maxX);
        float yInc = (float)(h - 2*PAD)/(2*maxY);
        // Draw abcissa.
        g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
        // Draw ordinate.
        g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
        // Draw Axes Labels.
        Font font = g2.getFont().deriveFont(14f);
        g2.setFont(font);
        FontRenderContext frc = g2.getFontRenderContext();
        LineMetrics lm = font.getLineMetrics("0", frc);
        float ascent = lm.getAscent();
        // Abcissa.
        for(int j = 0; j <= 2*maxX; j++) {
            String s = String.valueOf(j);
            float width = (float)font.getStringBounds(s, frc).getWidth();
            float sx = PAD + j*xInc - width/2;
            float sy = h-PAD + lm.getAscent() + SPAD;
            g2.drawString(s, sx, sy);
        }
        // Ordinate.
        int j2 = 2*maxY+1;
        for(int j = 0; j <= 2*maxY; j++) {
            j2--;
            String s = String.valueOf(j);
            float sx = SPAD;
            float sy = PAD + j2*yInc + ascent/2;
            g2.drawString(s, sx, sy);
        }
        g2.setPaint(Color.blue);
        
        // Y-Kooirdinate = PAD + (maxY*2 - WERT)*yInc;
        // X-Koordinate  = WERT*xInc + PAD;
        
        double y1 = PAD + (maxY*2 - 0)*yInc;
        double y2 = PAD + (maxY*2 - 6)*yInc;
        double x1 = 0*xInc + PAD;
        double x2 = 4*xInc + PAD;
        g2.draw(new Line2D.Double(x1,y1,x2,y2));
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        JFrame j = new JFrame();
        j.setSize(400,400);
        j.getContentPane().add(new Test());
        j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        j.setVisible(true);
    }
    
}

*grüssle*
MeinerEiner
 
Scheinbar habe ich die Funktionsweise von Graphic2D noch nicht allzu sehr verstanden.:confused:

Ich habe nun das Problem minimiert auf folgendes Mini-programm. Der Fehler lautet:
Code:
canvas\src\canvas\Main.java:13: cannot find symbol
symbol  : method paintComponent(java.awt.Graphics)
location: class javax.swing.JFrame
        super.paintComponent(g);
1 error
ERSTELLEN FEHLGESCHLAGEN (Gesamtzeit: 0 Minuten 0 Sekunden)

Was muss ich machen damit ich das Quadrat auf das JPanel und nicht auf den JFrame zeichnen kann?

Code:
package canvas;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;

public class Main extends JFrame{
    
    JPanel flaeche = new JPanel();

    protected void paintComponent(Graphics g) {
        flaeche.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawRect(5,5,10,10);
    }
    
    /** Creates a new instance of Main */
    public Main() {
        super("ZeichenTest");
        flaeche.setSize(300,300);
        JPanel pane = new JPanel();
        pane.add(flaeche);
        add(pane);
        setVisible(true);
    }
    
    public static void main(String[] args) {
        Main ausgabe = new Main();
        ausgabe.setSize(300,300);
    }
    
}
 
Hi,

Dazu musst du das Graphics-Objekt von dem entsprechenden JPannel holen und mit diesem arbeiten. Das Grapics-Objekt bekommst du mit :
Code:
MeinJPannel.getGraphics()
 
Okay. Danke an euch beide. Ich denke ich bin schon ein gutes Stück weitergekommen. Allerdings leider nicht ans Ziel.

Ich habe nun 2 .java Dateien. Die MainWindow.java:

Code:
package javaapplication22;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import javaapplication22.DrawPanel;
        
public class MainWindow extends JFrame implements ActionListener, ItemListener, WindowListener {
    DrawPanel canvas = new DrawPanel(); ....

und die Datei DrawPanel.java:

Code:
package javaapplication22;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;

public class DrawPanel extends JPanel {
    
    // Zeichenvariablen
    int maxX = 4;
    int maxY = 4;
    final int PAD = 20;
    final int SPAD = 3;
    
    private void paintComponent(Graphics g, Double x1, Double x2, Double y1, Double y2) {
        super.paintComponents(g);
        Graphics2D g2 = (Graphics2D)g;
        setBackground(new Color(255,255,255));
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        float xInc = (float)(w - 2*PAD)/(2*maxX);
        float yInc = (float)(h - 2*PAD)/(2*maxY);
        // Draw abcissa.
        g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
        // Draw ordinate.
        g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
        // Draw Axes Labels.
        Font font = g2.getFont().deriveFont(14f);
        g2.setFont(font);
        FontRenderContext frc = g2.getFontRenderContext();
        LineMetrics lm = font.getLineMetrics("0", frc);
        float ascent = lm.getAscent();
        // Abcissa.
        for(int j = 0; j <= 2*maxX; j++) {
            String s = String.valueOf(j);
            float width = (float)font.getStringBounds(s, frc).getWidth();
            float sx = PAD + j*xInc - width/2;
            float sy = h-PAD + lm.getAscent() + SPAD;
            g2.drawString(s, sx, sy);
        }
        // Ordinate.
        int j2 = 2*maxY+1;
        for(int j = 0; j <= 2*maxY; j++) {
            j2--;
            String s = String.valueOf(j);
            float sx = SPAD;
            float sy = PAD + j2*yInc + ascent/2;
            g2.drawString(s, sx, sy);
        }
        g2.setPaint(Color.blue);
        
        // Y-Kooirdinate = PAD + (maxY*2 - WERT)*yInc;
        // X-Koordinate  = WERT*xInc + PAD;
        // Beispiellinie:
                // double y1 = PAD + (maxY*2 - 0)*yInc;
                // double y2 = PAD + (maxY*2 - 6)*yInc;
                // double x1 = 0*xInc + PAD;
                // double x2 = 4*xInc + PAD;
    }
    
    void paintSomething(Graphics g, Double x1,Double x2,Double y1,Double y2) {
        Graphics2D g2 = (Graphics2D)g;
        int w = getWidth();
        int h = getHeight();
        float xInc = (float)(w - 2*PAD)/(2*maxX);
        float yInc = (float)(h - 2*PAD)/(2*maxY);
        y1 = PAD + (maxY*y1 - 0)*yInc;
        y2 = PAD + (maxY*y2 - 0)*yInc;
        x1 = x1 * xInc + PAD;
        x2 = x2 * xInc + PAD;
        g2.draw(new Line2D.Double(x1,y1,x2,y2));
    }
}

Das Panel wird in meinem Frame angezeigt, jedoch ohne Achsen oder sonstige Elemente.
 
private void paintComponent(Graphics g, Double x1, Double x2, Double y1, Double
Von wem wird diese Methode denn aufgerufen? Vom System jedenfalls nicht. Die Signatur der Methode paintComponent(), die automatisch aufgerufen wird, wenn das Panel neu gezeichnet werden sollen, lautet:
Code:
protected void paintComponent(Graphics g)

Wenn du dich daran werden u.a. die Achsen auch gezeichnet..

*grüssle*
MeinerEiner
 
Aber natürlich :rolleyes: *Hand vors Gesicht schlag*

Vielen vielen dank :)

Das funktiniert wunderbar. Nun müsste ich doch mit dem Befehl
Code:
        canvas.paintSomething(canvas.getGraphics(),0.0D,0.0D,3.0D,3.0D);

Eine Linie Zeichnen müssen oder? Nur kommt da der Fehler

Code:
Exception in thread "main" java.lang.NullPointerException
        at javaapplication22.DrawPanel.paintSomething(DrawPanel.java:74)
        at javaapplication22.MainWindow.itemStateChanged(MainWindow.java:165)
        at javax.swing.JComboBox.fireItemStateChanged(JComboBox.java:1207)
        at javax.swing.JComboBox.selectedItemChanged(JComboBox.java:1264)
        at javax.swing.JComboBox.contentsChanged(JComboBox.java:1311)
        at javax.swing.AbstractListModel.fireContentsChanged(AbstractListModel.java:100)
        at javax.swing.DefaultComboBoxModel.setSelectedItem(DefaultComboBoxModel.java:88)
        at javax.swing.DefaultComboBoxModel.addElement(DefaultComboBoxModel.java:126)
        at javax.swing.JComboBox.addItem(JComboBox.java:698)
        at javaapplication22.MainWindow.<init>(MainWindow.java:49)
        at javaapplication22.MainWindow.main(MainWindow.java:288)
Java Result: 1

Liegt es daran das canvas ein DrawPanel und keine Grafik ist?
 
Also ich habe nun mal eine Funktion in den Graphen gemalt (innerhalb des protect voids), was wunderbar klappt. Nur meine void paintSomething klappt nicht so recht.

Nach wie vor gibt er mir beim kompilieren den folgenden Fehler aus.

Code:
Exception in thread "main" java.lang.NullPointerException
        at javax.swing.JComponent.paintComponent(JComponent.java:766)
        at javaapplication22.DrawPanel.paintSomething(DrawPanel.java:90)
        at javaapplication22.MainWindow.itemStateChanged(MainWindow.java:167)
        at javax.swing.JComboBox.fireItemStateChanged(JComboBox.java:1207)
        at javax.swing.JComboBox.selectedItemChanged(JComboBox.java:1264)
        at javax.swing.JComboBox.contentsChanged(JComboBox.java:1311)
        at javax.swing.AbstractListModel.fireContentsChanged(AbstractListModel.java:100)
        at javax.swing.DefaultComboBoxModel.setSelectedItem(DefaultComboBoxModel.java:88)
        at javax.swing.DefaultComboBoxModel.addElement(DefaultComboBoxModel.java:126)
        at javax.swing.JComboBox.addItem(JComboBox.java:698)
        at javaapplication22.MainWindow.<init>(MainWindow.java:50)
        at javaapplication22.MainWindow.main(MainWindow.java:291)
Java Result: 1

Muss ich irgenteinen zusätzlichen Parameter übergeben? Bisher sieht die Methode wie gesagt ja nur so aus:

Code:
    void paintSomething(Double x1,Double x2,Double y1,Double y2) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        int w = getWidth();
        int h = getHeight();
        float xInc = (float)(w - 2*PAD)/(2*maxX);
        float yInc = (float)(h - 2*PAD)/(2*maxY);
        y1 = PAD + (maxY*y1 - 0)*yInc;
        y2 = PAD + (maxY*y2 - 0)*yInc;
        x1 = x1 * xInc + PAD;
        x2 = x2 * xInc + PAD;
        g2.setPaint(Color.blue);
        g2.draw(new Line2D.Double(x1,y1,x2,y2));
        this.getGraphics();
    }
 
Zurück