Zeichen auf mehrere JPanels

Jats

Aktives Mitglied
Hi,

ich arbeite momentan an einem Projekt zur Darstellung von gedämpften Schwingkreisen, in Form von einem Graph in einem Koordinatensystem. Das ganze funktioniert auch wunderbar, jedoch will ich nun versuchen alle Diagramme nacheinander zu zeichnen, und das in einer paint-Methode, auf vier verschiedenen JPanels welche nebeneinander angezeigt werden sollen.

Hier habe ich ein Umsezungsbeispiel, wobei ich den Großteil des Codes rausgenommen habe:

Java:
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

public class GUI extends JFrame implements ActionListener, ChangeListener {
    private String [] tNames = {"r","l","c","ende","w0","w","alpha"}, lNames = {"R:","C:","L:","w0:","w:","@:","Werte Insgesamt:"}, bNames = {"Berechnen","Zeichnen","Werte anzeigen"};/*W\ne\nr\nt\ne\n a\nn\nz\ne\ni\ng\ne\nn*/
    private JTextField [] textfields = new JTextField[tNames.length];
    private JLabel [] labels = new JLabel[lNames.length];
    private JButton [] buttons = new JButton[bNames.length];
    private WerteErzeugen werteErzeugen = new WerteErzeugen(2500);

    private Diagramm [] diagramme;

    private JPanel [] panels = new JPanel[4];
    
    private double [] xSkala,ySkala,xWerte,yWerte;
    private double [][] graphen;

    private boolean ausgeklappt = false;
    public GUI() {
        super("Schwingkreiss*****");
        setSize(1285,540);
        setLocation(2,100);
        setDefaultCloseOperation(3);
        setResizable(true);
        setLayout(null);

        werteErzeugen.berechnen();
        diagramme = werteErzeugen.getDiagramme();
        
        for(int i = 0; i<4; i++) {
            panels[i] = new JPanel();
            panels[i].setSize(300,200);
            add(panels[i]);
            panels[i].setVisible(true);
        }

        int buttonX = 30, buttonY = 450;
        for(int i=0; i<bNames.length-1; i++) {
            buttons[i] = new JButton(bNames[i]);
            buttons[i].setBounds(buttonX,buttonY,100,20);
            add(buttons[i]);
            buttons[i].addActionListener(this);
            buttonY+=20;
        }
        buttons[2] = new JButton(bNames[2]);
        buttons[2].setBounds(592,465,200,40);
        add(buttons[2]);
        buttons[2].addActionListener(this);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        Object o = e.getSource();
        if(o==buttons[0]) {
            werteErzeugen.berechnen();
        }
        if(o==buttons[1]) {
            paint(panels[0].getGraphics());
            paint(panels[1].getGraphics());
        }
        if(o==buttons[2]) {
            if(!ausgeklappt) {
                setSize(getWidth(),getHeight()+240);
                s.setBounds(0,505,1270,505);
                add(s);
                s.setVisible(true);
                ausgeklappt = true;
                extraInfo();
            }
            else {
                setSize(getWidth(),getHeight()-240);
                s.setVisible(false);
                ausgeklappt = false;
            }
        }
    }

    public void setSkalaUndPunkte(Diagramm d) {
        double [][] v = d.getWerte();
        xWerte = new double[v[0].length];
        yWerte = new double[v[1].length];
        xSkala = new double[v[2].length];
        ySkala = new double[v[3].length];

        xWerte = v[0];
        yWerte = v[1];
        xSkala = v[2];
        ySkala = v[3];
    }

    public void paint(Graphics g) {
        diagramme = werteErzeugen.getDiagramme();
        setSkalaUndPunkte(diagramme[0]);
        super.paint(g);
        //g = zeichenPanel.getGraphics();
        g = panels[0].getGraphics();
        g.clearRect(0,0,getWidth(),getHeight());

        int h = 300;    //(int) (getHeight() * 0.7);
        int w = 200;    //(int) (getWidth() * 0.6);
        int x0 = 40;    //(int) (0.1 * getWidth());          
        int y0 = 350;   //(int) (0.9 * getHeight());#
        diagrammNummer = 0;
        
        //while(diagrammNummer<=diagramme.length) {
            panels[diagrammNummer].setBounds(x0,50,270,400);
            g = panels[0].getGraphics();
           
            g.drawString(diagramme[diagrammNummer].getName(),x0+140,45);
            g.setColor(Color.BLACK);

            g.drawLine(x0,y0-h-15,x0,y0);            //y-Achse
            g.drawLine(x0-1,y0-h-15,x0-1,y0);

            g.drawLine(x0,y0,x0+w+15,y0);            //x-Achse
            g.drawLine(x0,y0+1,x0+w+15,y0+1);

            g.drawString("y",x0+5,y0-h-5);          //Achsenbeschreibung
            g.drawString("x",x0+w+7,y0-3);          //Achsenbeschreibung

            g.drawLine(x0-5,y0-h-15,x0+5,y0-h-15);  //y-Achse Pfeilgrund          
            g.drawLine(x0-5,y0-h-15,x0,y0-h-20);    //|
            g.drawLine(x0+5,y0-h-15,x0,y0-h-20);    //|     Pfeil
            g.drawLine(x0-4,y0-h-15,x0,y0-h-20);    //|
            g.drawLine(x0+4,y0-h-15,x0,y0-h-20);    //|

            g.drawLine(x0+w+15,y0-5,x0+w+15,y0+5);  //x-Achse Pfeilgrund 
            g.drawLine(x0+w+15,y0-5,x0+w+20,y0);    //|
            g.drawLine(x0+w+15,y0+5,x0+w+20,y0);    //|     Pfeil
            g.drawLine(x0+w+15,y0-4,x0+w+20,y0);    //|
            g.drawLine(x0+w+15,y0+4,x0+w+20,y0);    //|

            for (int i = 0;i<=xSkala[2];i++) {
                g.drawString("" + (xSkala[0]+i*((xSkala[1]-xSkala[0])/xSkala[2])),(int)(x0+i*w/xSkala[2]),y0+20);                //Beschriftung xAchse
            }
            for (int i = 0;i<=ySkala[2];i++) {
                g.drawString("" + (ySkala[0]+i*(ySkala[1]-ySkala[0])/ySkala[2]),x0-40,(int)(y0+4-i*h/ySkala[2]));              //Beschriftung yAchse
            }  
            g.setColor(Color.GRAY);
            for (int i = 0; i<=xSkala[2]; i++) {
                g.drawLine ((int)(x0+(i*w/xSkala[2])),y0,(int)(x0+(i*w/xSkala[2])),y0-h);                                                         //Gitternetz yAchse
            }
            for (int i = 0; i<=ySkala[2]; i++) {
                g.drawLine (x0,(int)(y0-(i*h/ySkala[2])),x0+w,(int)(y0-(i*h/ySkala[2])));                                                         //Gitternetz xAchse
            }
            g.setColor(Color.BLACK);
            for(int i = 0;i<xWerte.length;i++) {
                g.fillOval((int)(x0-1+w*(xWerte[i]-xSkala[0])/(xSkala[1]-xSkala[0])),(int)(y0-1-(h*(yWerte[i]-ySkala[0])/(ySkala[1]-ySkala[0]))),3,3);
            }
            x0 = w+x0+100;
            diagrammNummer++;
            if(diagrammNummer!=diagramme.length) {
                setSkalaUndPunkte(diagramme[diagrammNummer]);
            }
            else {
                break;
            }
            g = panels[diagrammNummer].getGraphics();
        }
    }
}

Problem ist momentan folgendes: Wenn ich repaint() aufrufe, wird zwar alles gezeichnet, das jedoch nur auf ein JPanel und ich weiß auch nicht welches. Es scheint also, als würde g = panels.getGraphics(); nicht so funktionieren, wie ich will. Ich habe auch schon versucht, an den Stellen an denen ich repaint() aufrufe einfach paint(panels.getGraphics()) zu machen, aber das ging auch nicht.

Meine Frage ist jetzt, ob meine Idee überhaupt möglich ist, oder nicht und wenn ja, wie. Bitte entschuldigt meine relativ unsaubere Programmierweise, die Feinarbeit folgt meist erst nachher.

Gruß,
Jats
 
imho ist das gerade vergebene Mühe, was du machst.

Du überschreibst die
Code:
 paint(Graphics g)
Methode des JFrames und rufst wild auf deine JPanels
Code:
getGraphics()
auf. Dass das irgendwann so funktioniert, wie du dir das vorstellst....kann ich mir nicht vorstellen.

Warum willst du denn überhaupt über mehrere Panels zeichnen? Und dann im Null-Layout? Während deine Panels zumindest laut dem geposteten Code das FlowLayout haben...!!! Da du die Klassen WerteErzeugen und Diagramm nicht gepostet hast, lässt sich dein prog leider nicht kompilieren.

paar Schlagwörter...: Null-Layout is Evil (ok, bei den Diagrammen lässt sich das evtl nicht umgehen)
niemals selbst paint() aufrufen...
niemals getGraphics() aufrufen, außer man weiß was man macht^^
 
imho ist das gerade vergebene Mühe, was du machst.

Du überschreibst die
Code:
 paint(Graphics g)
Methode des JFrames und rufst wild auf deine JPanels
Code:
getGraphics()[/C auf. Dass das irgendwann so funktioniert, wie du dir das vorstellst....kann ich mir nicht vorstellen.
[/QUOTE]

Schon klar, ich müsste mir dann erst sowas wie ne MyPanel Klasse machen und da dann paint(-Component) überschreiben, aber ich will das im JFrame haben und eigentlich nicht noch mehr Klassen machen.

[quote="jgh, post: 907536"]Warum willst du denn überhaupt über mehrere Panels zeichnen? Und dann im Null-Layout? Während deine Panels zumindest laut dem geposteten Code das FlowLayout haben...!!!  Da du die Klassen WerteErzeugen und Diagramm nicht gepostet hast, lässt sich dein prog leider nicht kompilieren.[/QUOTE]

Null-Layout habe ich deshalb gewählt, weil ich mit Flow-, Box- und irgendeinem anderen Layout noch nie wirklich gearbeitet habe und das ganze Projekt relativ schnell fertig werden sollte, weshalb ich eigentlich auf etwas Neues verzichten wollte.

EDIT: Paint direkt aufrufen war auch nur ein Versuch, in Verzweiflung, das war jetzt nicht wirklich als funktionierend geglaubt. Ich probiere halt viel rum, wenn was nicht auf Anhieb geht :D Zu getGraphics(): Macht doch nix anderes, als ein Graphics-Objekt von der Komponente zu erstellen, oder ist es doch nicht so einfach ?
Ich will deshalb auf mehrere JPanels zeichnen, weil ich den Zeichenprozess, also im Prinzip die Abnahme der Schwingung zeigen will, sprich mit nem Timer, dass die Kurve also beim entstehen gesehen wird und nicht einfach so da ist. Die Sache mit mehreren JPanels war die Idee vom Dozenten, ich wollte das nur mal so ausprobieren, wenn's nicht klappt würde ich auch was anderes versuchen.
 
Zuletzt bearbeitet:
Zu getGraphics(): Macht doch nix anderes, als ein Graphics-Objekt von der Komponente zu erstellen, oder ist es doch nicht so einfach ?
Nein so einfach ist das nicht. Rufst du getGraphics() auf bevor die Komponente sichtbar ist bekommst du bspw. null zurück. Auch wenns dann mal irgendwann klappen sollte ist es nicht sehr unwahrscheinlich dass dir immer mal Zeichenfehler auffallen.

Wann gezeichnet wird entscheidet ausschließlich Swing, das brauchst du nicht tun. Daher: In der paintComponent() vom JPanel deine Sachen zeichnen die du zeichnen willst. Per repaint() kannst du Java darum bitten nochmal alles neuzuzeichnen.
 
Nein so einfach ist das nicht. Rufst du getGraphics() auf bevor die Komponente sichtbar ist bekommst du bspw. null zurück. Auch wenns dann mal irgendwann klappen sollte ist es nicht sehr unwahrscheinlich dass dir immer mal Zeichenfehler auffallen.

Wann gezeichnet wird entscheidet ausschließlich Swing, das brauchst du nicht tun. Daher: In der paintComponent() vom JPanel deine Sachen zeichnen die du zeichnen willst. Per repaint() kannst du Java darum bitten nochmal alles neuzuzeichnen.

Alles klar, Ersteres wusste ich schon, aber Zweiteres hilft mir glaub ich weiter.
Jetzt ist nur die Frage, wie ich das mit der paintComponent() von JPanel machen soll, ich meine..wie soll ich die vom JPanel überschreiben ?
Soll ich ne neue Klasse die von JPanel erbt erstellen und die paintComponent() darin überschreiben oder was ?
 
Noch was: Anstatt mit Null Layout rumzuprobieren wärst du vermutlich sehr viel schneller, wenn du lernst mit einem Layoutmanager umzugehen.
 

Zurück
Oben