# einfache Frage:warum ist Hintergrund grau ?



## ernst (15. Feb 2010)

Hallo allerseits,
in einem Demo-Programm (mit Netbeans erstellt und dem zugehörigen grafischen Editor) lasse ich zu Testzwecken immer wieder 2 selbstgebastelte Autos (also keine Autos aus Grafikdateien) sich von von links nach rechts bewegen.
Das einfache Demo-Programm funktioniert. Nur gibt es ein kleines Problem:
Den Hintergrund habe ich im Visual-Editor (VE) in SpielJFrame rot und in SpielJPanel grün gemacht.
Warum erscheint der Hintergrund aber grau ??
Wo ist mein Fehler ?
Habe schon alles Mögliche probiert, hat aber nichts geholfen.

mfg
Ernst


[Java]
package pack30;

public class SpielJFrame extends javax.swing.JFrame {
    private SpielJPanel spielJPanel;
    /** Creates new form SpielJFrame */
    public SpielJFrame() {
        initComponents();
        spielJPanel = new SpielJPanel();
        jPanel1.add(spielJPanel, "Center");
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.setBackground(new java.awt.Color(255, 204, 153));
        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setLayout(new java.awt.BorderLayout());

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 217, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(85, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new SpielJFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JPanel jPanel1;
    // End of variables declaration                   

}

[/Java]

[Java]
package pack30;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class SpielJPanel extends javax.swing.JPanel {
    private Timer t;
    private Auto  auto1;
    private Auto  auto2;
    private Image bild;
    /** Creates new form SpielJPanel */
    public SpielJPanel() {
        initComponents();
        auto1 = new Auto(this, Color.RED, 0, 0, 100);
        auto2 = new Auto(this, Color.BLUE, 50, 80, 100);
        auto1.setSchritt(10);
        auto2.setSchritt(20);
        t = new Timer(20,
                new ActionListener() {
                    public void actionPerformed(ActionEvent ae) {
                        myupdate();
                        maleInsBild();
                        repaint();
                    }
                });

        t.start();

    }

    public void setTimer(int millis) {
        t.setDelay(millis);
    }

    public int getTimerTime() {
        return t.getDelay();
    }

    public void myupdate() {
        System.out.println("this.getWidth()="+this.getWidth()+"this.getHeight="+this.getHeight());
        auto1.berechnePos();
        auto2.berechnePos();
    }

    public void maleInsBild(){
        int sx, sy;
        Graphics graphics=null;
        sx = this.getSize().width;
        sy = this.getSize().height;
        bild = createImage(sx, sy);
        graphics = bild.getGraphics();
        auto1.zeichneAuto(graphics);
        auto2.zeichneAuto(graphics);
    }


    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    	g.drawImage(bild,0,0,null);
    }



    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        setBackground(new java.awt.Color(204, 255, 153));
        setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        setLayout(new java.awt.BorderLayout());
    }// </editor-fold>                        


    // Variables declaration - do not modify                     
    // End of variables declaration                   

}
[/Java]


[Java]
package pack30;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;

public class Auto {
    private SpielJPanel spielJPanel;
    private Color farbe;
    private int x;
    private int y;
    private int groesse;
    private int schritt;
    private static int strassenlaenge;

    public Auto(SpielJPanel pSpielJPanel, Color pFarbe, int pOrtX, int pOrtY, int pGroesse){
        spielJPanel = pSpielJPanel;
        farbe = pFarbe;
        x = pOrtX;
        y = pOrtY;
        groesse = pGroesse;
        schritt = 0;
    }

    public void setX(int pX){
        x = pX;
    }

    public int getX(){
        return x;
    }

    public void setY(int pY){
        y = pY;
    }

    public int getY(){
        return y;
    }

    public void setFarbe(Color pFarbe){
        farbe = pFarbe;
    }

    public Color getFarbe(){
        return farbe;
    }

    void berechnePos(){
        if(x <= spielJPanel.getWidth()){
            x = x + schritt;
        }
        else{
            x=0;
        }
    }

    public Point getPos() {
       return new Point(x, y);
    }


    void setSchritt(int pSchritt){
        schritt = pSchritt;
    }



    void zeichneAuto(Graphics g){
        // Linker oberer Eckpunkt des Wagens
        int x1 = x;
        int y1 = y;
        // Rechter unterer Eckpunkt des Wagens
        int x2 = x1 + groesse;    // Größe = Länge = x2-ortX
        int y2 = y1 + groesse/2;  // Höhe = y2-ortY

        // Linker oberer Eckpunkt des Fensters
        int x3 = x2 - groesse/4;    // Fenster
        int y3 = y1;
        // Rechter unterer Eckpunkt des Fensters
        int x4 = x3 + groesse/4;    // Fenster
        int y4 = y3 + groesse/4;

        int r = groesse/8;            // RadRadius
        int x5 = x1 + 19 + r/2;     // Hinterrad
        int x6 = x2 - 19 - r/2;       // Vorderrad

        // Karosserie
        g.setColor(farbe);
        g.drawRect(x1, y1, x2-x1, y2-y1);
        g.fillRect(x1, y1, x2-x1, y2-y1);

        // Fenster
        g.setColor(Color.BLACK);
        g.drawRect(x3-1, y3-1, x4-x3+1, y4-y3+1);
        g.setColor(Color.WHITE);
        g.fillRect(x3, y3, x4-x3, y4-y3);

        // Hinterrad
        g.setColor(Color.BLACK);
        g.fillOval(x1, y2-r, 2*r, 2*r);

        // Vorderrad
        g.fillOval(x2-2*r, y2-r, 2*r, 2*r);

    }
}

[/Java]


----------



## Marco13 (15. Feb 2010)

Hach, ich vergess' immer wieder welche Components standardmäßig Opaque sind und welche nicht. Kannst mal in die erste Zeile der initComponents
setOpaque(true);
einfügen - und wenn's hilft, schauen, wo man in diesem Visual Dingsda die "Opaque"-Checkbox anklicken kann... wenn nicht... muss man nochmal genauer schauen...


----------



## ernst (15. Feb 2010)

Marco13 hat gesagt.:


> Hach, ich vergess' immer wieder welche Components standardmäßig Opaque sind und welche nicht. Kannst mal in die erste Zeile der initComponents
> setOpaque(true);
> einfügen - und wenn's hilft, schauen, wo man in diesem Visual Dingsda die "Opaque"-Checkbox anklicken kann... wenn nicht... muss man nochmal genauer schauen...


In den generierten Quellcode läßt mich der Visual-Editor (VE) nicht einfügen. Ich kann also _in_ der Methode initComponents nichts einfügen.
Alternativ habe ich folgendes gemacht.
1) _Vor_ die Anweisung
initComponents();
habe ich in SpielJPanel
eingefügt:
setOpaque(true);

(In SpielJFrame läßt mich vor initComponents(); der Compiler kein setOpaque(true); einfügen; er gibt mir eine Fehlermeldung)  

2)
In SpielJPanel hat der VE bei
opaque 
einen Haken gemacht. Egal ob ich den Haken wegmache oder dranlasse, bekomme ich wieder einen grauen Hintergrund.

mfg
Ernst


----------



## Marco13 (15. Feb 2010)

Ahja, hab' nochmal genauer nachgesehen: Dass der eigentliche Mal-Bereich grau ist, liegt daran, dass dort dieses Bild gemalt wird... und das ist erstmal grau. In die maleInBild-Methode

```
graphics = bild.getGraphics();
[b]
        graphics.setColor(getBackground());
        graphics.fillRect(0,0,sx,sy);
[/b]
        auto1.zeichneAuto(graphics);
```
behebt das schon mal, wobei es eigentlich ziemlich unschön ist, dort immer ein neues Bild zu erstellen... Besser wäre es, EINmal das Bild zu erstellen (wenn es noch null ist), und es nur neu zu erzeugen, wenn sich die Höhe oder Breite geändert hat.

Wo man das rote Panel sehen soll, erschließt sich mir aber nicht ganz... Wenn man das
jPanel1.setBackground(new java.awt.Color(255, 204, 153));
ändert in
getContentPane().setBackground(new java.awt.Color(255, 204, 153));
malt er den ganzen Hintergrund rot - kannst ja mal schauen, ob man das mit diesem Visual-Editor auch machen kann. Notfalls kann man diese Zeile aber auch im Konstruktor vom SpielJFrame einfügen.


----------



## ernst (15. Feb 2010)

Marco13 hat gesagt.:


> Ahja, hab' nochmal genauer nachgesehen: Dass der eigentliche Mal-Bereich grau ist, liegt daran, dass dort dieses Bild gemalt wird... und das ist erstmal grau. In die maleInBild-Methode
> 
> ```
> graphics = bild.getGraphics();
> ...



I)
Danke für den Tipp. Wenn ich diese Dinge mache:
graphics.setColor(getBackground());
graphics.fillRect(0,0,sx,sy);
und
getContentPane().setBackground(new java.awt.Color(255, 204, 153));
habe ich den roten Hintergrund im Fenster und den gelben Hintergrund auf der Zeichenfläche.
Alles funktioniert, so wie du es beschrieben hast..
II)
Um eure Geduld nicht zu strapazieren, habe ich in meinem letzten Posting aber nur das abgespeckte Problemprogramm gesendet.
In meinem wirköichen, nicht abgespeckten Problemprogram (siehe unten), habe ich den Tipp von dir auch berücksichtigt, doch bekomme ich leider nicht den entsprechenden Hintergrund auf meiner Zeichenfläche. Auch sind die Schieberegler immer noch grau.
Warum ?

PS:
Da der Quelltext sehr groß ist, schicke ich ihn in 2 Postings

[Java]

package pack1;

import java.awt.Color;
import java.util.Hashtable;
import javax.swing.JLabel;
import javax.swing.JSlider;

public class ZeichnungJFrame extends javax.swing.JFrame {
    private ZeichnungJPanel zeichnungJPanel;

    public ZeichnungJFrame() {
        String s1, s2, s3;
        initComponents();
        getContentPane().setBackground(new java.awt.Color(255, 204, 153));
        s1="Sekantensteigung und Tangentensteigung: ";
        s2="deltaX, x-Wert des Festpunktes (mit Schieberegler) und Laufpunkt ";
        s3="(mit der Maus) veränderbar";
        setTitle(s1+s2+s3);
        int slidermin = -100;
        int slidermax = 100;
        this.setSize(1000, 700);

        zeichnungJPanel = new ZeichnungJPanel(this);

        jPanel1.add(zeichnungJPanel, "Center");
        // Maximaler Wert, den der Slider (Schieberegöler ganz links) zurückgibt
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // Kaum zu glauben, aber laut Debugger ruft setMinimum() die
        // Methode jSlider1.changeEvent() auf
        jSlider1.setMinimum(slidermin);
        jSlider1.setMaximum(slidermax);
        jSlider1.setOrientation(JSlider.HORIZONTAL);
        jSlider1.setPaintLabels(true);
        jSlider1.setPaintTicks(true);
        jSlider1.setMajorTickSpacing(10 );
        Hashtable labelTable = new Hashtable();
        labelTable.put(new Integer(slidermin), new JLabel(Integer.toString(slidermin/10)));
        labelTable.put(new Integer(0), new JLabel("0"));
        labelTable.put(new Integer(slidermax), new JLabel(Integer.toString(slidermax/10)));
        jSlider1.setLabelTable(labelTable);

        // Maximaler Wert, den der Slider (Schieberegöler ganz links) zurückgibt
        jSlider2.setMinimum(slidermin);
        jSlider2.setMaximum(slidermax);
        jSlider2.setOrientation(JSlider.HORIZONTAL);
        jSlider2.setPaintLabels(true);
        jSlider2.setPaintTicks(true);
        jSlider2.setMajorTickSpacing(10 );
        Hashtable labelTable2 = new Hashtable();
        labelTable2.put(new Integer(slidermin), new JLabel(Integer.toString(slidermin/10)));
        labelTable2.put(new Integer(0), new JLabel("0"));
        labelTable2.put(new Integer(slidermax), new JLabel(Integer.toString(slidermax/10)));
        jSlider2.setLabelTable(labelTable2);

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jSlider1 = new javax.swing.JSlider();
        jSlider2 = new javax.swing.JSlider();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        tx1 = new javax.swing.JTextField();
        tx2 = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        tx3 = new javax.swing.JTextField();
        tx4 = new javax.swing.JTextField();
        tx5 = new javax.swing.JTextField();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        tx6 = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.setBackground(new java.awt.Color(204, 255, 204));
        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setLayout(new java.awt.BorderLayout());

        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider1StateChanged(evt);
            }
        });

        jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider2StateChanged(evt);
            }
        });

        jLabel1.setText("delta x verändern");

        jLabel2.setText("x-Wert des Festpunktes verändern");

        jLabel3.setText("x-Koordinate Festpunkt");

        jLabel4.setText("y-Koordinate Festpunkt");

        tx1.setText("jTextField1");
        tx1.setEnabled(false);

        tx2.setText("jTextField2");
        tx2.setEnabled(false);

        jLabel5.setForeground(new java.awt.Color(255, 51, 51));
        jLabel5.setText("delta y");

        jLabel6.setText("--------");

        jLabel7.setForeground(new java.awt.Color(0, 51, 255));
        jLabel7.setText("delta x");

        jLabel8.setText("=");

        tx3.setForeground(new java.awt.Color(255, 51, 51));
        tx3.setText("jTextField3");
        tx3.setEnabled(false);

        tx4.setForeground(new java.awt.Color(51, 51, 255));
        tx4.setText("jTextField4");
        tx4.setEnabled(false);

        tx5.setText("jTextField5");
        tx5.setEnabled(false);

        jLabel9.setText("=");

        jLabel10.setText("---------------------------------");

        jLabel11.setText("-");

        tx6.setText("jTextField6");
        tx6.setEnabled(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 543, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel3)
                                .addGap(18, 18, 18)
                                .addComponent(tx1, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addComponent(jLabel5)
                                            .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addComponent(jLabel7))
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jLabel8)
                                        .addGap(12, 12, 12)
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addGroup(layout.createSequentialGroup()
                                                .addGap(14, 14, 14)
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                        .addComponent(jLabel10, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                        .addGap(18, 18, 18)
                                                        .addComponent(jLabel9)
                                                        .addGap(18, 18, 18)
                                                        .addComponent(tx6, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
                                                    .addGroup(layout.createSequentialGroup()
                                                        .addComponent(tx3, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                                        .addComponent(jLabel11, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                        .addComponent(tx4, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))))
                                            .addGroup(layout.createSequentialGroup()
                                                .addGap(60, 60, 60)
                                                .addComponent(tx5, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))))
                                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                        .addComponent(jLabel4)
                                        .addGap(18, 18, 18)
                                        .addComponent(tx2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                .addGap(221, 221, 221)))
                        .addGap(60, 60, 60))
                    .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, 399, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, 390, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(532, 532, 532))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addGap(5, 5, 5)
                .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(30, 30, 30)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 45, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel3)
                            .addComponent(tx1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel4)
                            .addComponent(tx2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(39, 39, 39)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(tx3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel5)
                            .addComponent(jLabel11)
                            .addComponent(tx4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel10)
                            .addComponent(jLabel9)
                            .addComponent(jLabel6)
                            .addComponent(jLabel8)
                            .addComponent(tx6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel7))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(tx5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(2, 2, 2)))
                .addGap(43, 43, 43))
        );

        pack();
    }// </editor-fold>                        

    private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {                                      
        String str;
        int wert;
        double dWert;
        wert = jSlider1.getValue();
        dWert = wert / 10.0;
        zeichnungJPanel.setParameterDeltaX(dWert);
        zeichnungJPanel.allesUpdaten();
        zeichnungJPanel.maleKomplettesFenster();

    }                                     

    private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt) {                                      
        String str;
        int wert;
        double dWert;
        wert = jSlider2.getValue();
        dWert = wert / 10.0;

        zeichnungJPanel.setParameterXFestpunkt(dWert);
        zeichnungJPanel.allesUpdaten();
        zeichnungJPanel.maleKomplettesFenster();

    }                                     


    public void maleRestZeichnungJFrame(){
        String str;
        float ergebnis;
        double xFestpunkt, yFestpunkt, xLaufpunkt, yLaufpunkt, erg;
        xFestpunkt = zeichnungJPanel.getTangente().getFestPunkt().x;
        yFestpunkt = zeichnungJPanel.getTangente().getFestPunkt().y;
        xLaufpunkt = zeichnungJPanel.getTangente().getLaufPunkt().x;
        yLaufpunkt = zeichnungJPanel.getTangente().getLaufPunkt().y;

        int sliderwert;
        /* A C H T U N G:
        sliderwert=(int)((xLaufpunkt-xFestpunkt)*10);
        lieferte
        xLaufpunkt-xFestpunkt==2.9999999999999996 und damit
        sliderwert=29
        D E S W E G EN   die folgende Konstruktion
        */
        ergebnis=(float)((xLaufpunkt-xFestpunkt)*10);
        sliderwert=Math.round(ergebnis);
        jSlider1.setValue(sliderwert);

        sliderwert=(int)(xFestpunkt*10);
        jSlider2.setValue(sliderwert);

        str = new String(String.valueOf(xFestpunkt));
        tx1.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(yFestpunkt));
        tx2.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(yLaufpunkt));
        tx3.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(yFestpunkt));
        tx4.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(xLaufpunkt-xFestpunkt));
        tx5.setText(str.substring(0,str.length()<6?str.length():5));

        String s;
        if (xLaufpunkt-xFestpunkt==0)
            s="nicht definiert";
        else{
            erg = (yLaufpunkt-yFestpunkt)/(xLaufpunkt-xFestpunkt);
            str = new String(String.valueOf(erg));
            s = str.substring(0,str.length()<6?str.length():5);
        }
        tx6.setText(s);
    }


    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                ZeichnungJFrame zeichnungJFrame = new ZeichnungJFrame();
                zeichnungJFrame.setVisible(true);
                zeichnungJFrame.zeichnungJPanel.setParameterDeltaX(3);
                zeichnungJFrame.zeichnungJPanel.setParameterXFestpunkt(1);
                zeichnungJFrame.zeichnungJPanel.allesUpdaten();
                zeichnungJFrame.zeichnungJPanel.maleKomplettesFenster();


            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSlider jSlider2;
    private javax.swing.JTextField tx1;
    private javax.swing.JTextField tx2;
    private javax.swing.JTextField tx3;
    private javax.swing.JTextField tx4;
    private javax.swing.JTextField tx5;
    private javax.swing.JTextField tx6;
    // End of variables declaration                   

}
[/Java]



mfg
Ernst


----------



## ernst (15. Feb 2010)

Marco13 hat gesagt.:


> Ahja, hab' nochmal genauer nachgesehen: Dass der eigentliche Mal-Bereich grau ist, liegt daran, dass dort dieses Bild gemalt wird... und das ist erstmal grau. In die maleInBild-Methode
> 
> ```
> graphics = bild.getGraphics();
> ...



Hier ist der Rest:

[Java]
package pack1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;


public class ZeichnungJPanel extends javax.swing.JPanel implements MouseListener, MouseMotionListener {
    ZeichnungJFrame zeichnungJFrame;
    private Image bild;
    private Tangente tangente;
    private double parameterDeltaX;
    private double parameterxFestpunkt;
    private Graphics graphicsNormalparabel;
    private Image bildNormalparabel;
    private int flag = 0;

    private int mausBewegt;


    public ZeichnungJPanel(ZeichnungJFrame pZeichnungJFrame) {
        initComponents();
        zeichnungJFrame = pZeichnungJFrame;
        mausBewegt = 0;
        tangente = new Tangente(this);
        addMouseMotionListener(this);
        addMouseListener(this);
        parameterDeltaX=3;
        parameterxFestpunkt=1;

    }

    public Tangente getTangente(){
        return tangente;
    }

    public void setParameterXFestpunkt(double pParameterxFestpunkt){
        parameterxFestpunkt = pParameterxFestpunkt;
    }

    public double getParameterXFestpunkt(){
        return parameterxFestpunkt;
    }

    public void setParameterDeltaX(double pDeltaX){
        parameterDeltaX = pDeltaX;
    }

    public double getParameterDeltaX(){
        return parameterDeltaX;
    }

    public void allesUpdaten() {
        tangente.berechnePos();
    }

    public void maleKomplettesFenster(){
        maleZeichnungJPanelOffscreen();
        zeichnungJFrame.maleRestZeichnungJFrame();
        repaint();
    }


    public void maleZeichnungJPanelOffscreen(){
        int sx, sy;
        Graphics graphics=null;

        sx = this.getSize().width;
        sy = this.getSize().height;
        if(sx!=0 && sy!=0){
            bild = createImage(sx, sy);
            graphics = bild.getGraphics();
            graphics.setColor(getBackground());
            graphics.fillRect(0,0,sx,sy);


            Transformation.setBreite(sx);
            Transformation.setHoehe(sy);
            tangente.zeichneNormalparabel(graphics, Color.black);
            tangente.zeichneSekante(graphics, Color.green);
            tangente.zeichneTangente(graphics, Color.cyan);
            tangente.zeichneAchsenkreuz(graphics, Color.black);
        }
    }


    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    	g.drawImage(bild,0,0,Color.white,null);

    }    

	public void mouseClicked(MouseEvent arg0) {
    }

	public void mousePressed(MouseEvent arg0) {
	}

	public void mouseEntered(MouseEvent arg0) {
	}

	public void mouseExited(MouseEvent arg0) {
	}

	public void mouseMoved(MouseEvent arg0) {
	}

    public void mouseDragged(MouseEvent ev) {
        boolean b;
		Point klick = new Point();
        klick = ev.getPoint();
        b = tangente.istInnerhalb(klick, tangente.getLaufPunkt());
        if(b==true){
            if(mausBewegt==0){
                mausBewegt=1;
            }

        }
	}

	public void mouseReleased(MouseEvent ev) {
        boolean b;
		Point javaklick = new Point();
        Point2DDouble p2D;


        javaklick = ev.getPoint();

        if(mausBewegt==1){
            mausBewegt=0;
            b = tangente.punktAufKurve(javaklick);

            if(b==true){
                p2D = Transformation.transformJavaTo2D(javaklick.x, javaklick.y);
                setParameterDeltaX(p2D.x-tangente.getFestPunkt().x);
                allesUpdaten();
                maleKomplettesFenster();
            }

        }
	}


    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        setBackground(new java.awt.Color(255, 255, 204));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 523, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 312, Short.MAX_VALUE)
        );
    }// </editor-fold>                        


    // Variables declaration - do not modify                     
    // End of variables declaration                   

}
[/Java]

[Java]
package pack1;

public class Point2DDouble {
    public double x;
    public double y;

    public Point2DDouble(double px, double py) {
        x = px;
        y = py;
    }
}

[/Java]

[Java]
package pack1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JLabel;

public class Tangente{
    private ZeichnungJPanel zeichnungJPanel;
    private Point2DDouble festPunkt;
    private Point2DDouble laufPunkt;
    private Image bildNormalparabel;
    private int flag;
    // Halbe Dicke eines Punktes auf dem Bildschirm
    private double abstand;

    public Tangente(ZeichnungJPanel pZeichnungJPanel){
        zeichnungJPanel = pZeichnungJPanel;
        festPunkt = new Point2DDouble(0,0);
        laufPunkt = new Point2DDouble(0,0);
        flag = 0;
        abstand = 0.1;
    }

    public void setFestPunkt(double px, double py){
        festPunkt.x = px;
        festPunkt.y = py;
    }

    public Point2DDouble getFestPunkt(){
        return(festPunkt);
    }

    public void setLaufPunkt(double px, double py){
        laufPunkt.x = px;
        laufPunkt.y = py;
    }

    public Point2DDouble getLaufPunkt(){
        return(laufPunkt);
    }

    public void berechnePos(){
        double parameterDeltaX, parameterXFestpunkt;
        parameterDeltaX = zeichnungJPanel.getParameterDeltaX();
        parameterXFestpunkt = zeichnungJPanel.getParameterXFestpunkt();
        festPunkt.x =  parameterXFestpunkt;
        festPunkt.y =  festPunkt.x * festPunkt.x;

        laufPunkt.x =  festPunkt.x + parameterDeltaX;
        laufPunkt.y =  laufPunkt.x * laufPunkt.x;

    }

    public void zeichneSekante(Graphics g, Color farbe){
        double x1, y1, x2, y2;

        x1 = laufPunkt.x;
        y1 = laufPunkt.y;
        x2 = laufPunkt.x;
        y2 = festPunkt.y;
        g.setColor(Color.red);
        drawLineReal(g, x1, y1, x2, y2);
        drawPunktReal(g, Color.magenta, festPunkt.x, festPunkt.y);
        drawPunktReal(g, Color.pink, laufPunkt.x, laufPunkt.y);


        x1 = festPunkt.x;
        y1 = festPunkt.y;
        x2 = laufPunkt.x;
        y2 = festPunkt.y;
        g.setColor(Color.blue);
        drawLineReal(g, x1, y1, x2, y2);



        x1=Transformation.minX;
        y1=(laufPunkt.y-festPunkt.y)/(laufPunkt.x-festPunkt.x)*(x1-festPunkt.x)+festPunkt.y;

        x2=Transformation.maxX;
        y2=(laufPunkt.y-festPunkt.y)/(laufPunkt.x-festPunkt.x)*(x2-festPunkt.x)+festPunkt.y;
        g.setColor(farbe);
        drawLineReal(g, x1, y1, x2, y2);
    }

    public void zeichneTangente(Graphics g, Color farbe){
        double xBeginn, xEnde, yBeginn, yEnde;
        g.setColor(farbe);
        xBeginn = Transformation.minX;
        xEnde = Transformation.maxX;
        yBeginn = 2*festPunkt.x*(xBeginn-festPunkt.x)+  festPunkt.y;
        yEnde = 2*festPunkt.x*(xEnde-festPunkt.x)+  festPunkt.y;
        drawLineReal(g, xBeginn, yBeginn, xEnde, yEnde);
    }

    public void zeichneAchsenkreuz(Graphics g, Color farbe){
        Point2DDouble A2D = new Point2DDouble(0,0);
        Point2DDouble B2D = new Point2DDouble(0,0);

        g.setColor(farbe);
        A2D.x = Transformation.minX;
        A2D.y = 0;
        B2D.x = Transformation.maxX;;
        B2D.y = 0;
        drawLineReal(g, A2D.x, A2D.y, B2D.x, B2D.y);
        drawDreieckReal(g, Color.black, B2D.x, B2D.y, B2D.x-0.2, B2D.y+0.2, B2D.x-0.2, B2D.y-0.2);
        beschrifteAchsenkreuz(g, farbe);

        A2D.x = 0;
        A2D.y = Transformation.minY;
        B2D.x=0;
        B2D.y=Transformation.maxY;
        drawLineReal(g, A2D.x, A2D.y, B2D.x, B2D.y);
        drawDreieckReal(g, Color.black, B2D.x, B2D.y, B2D.x-0.2, B2D.y-0.2, B2D.x+0.2, B2D.y-0.2);
    }

    public void beschrifteAchsenkreuz(Graphics g, Color farbe){
        double min, max, x, y;
        min = Transformation.minX;
        max = Transformation.maxX;
        x=0;
        do{
            drawLineReal(g, x, 0.1, x, -0.1);
            x=x+1;
        }
        while (x<=max);

        x=0;
        do{
            drawLineReal(g, x, 0.1, x, -0.1);
            x=x-1;
        }
        while (x>=min);

        min = Transformation.minY;
        max = Transformation.maxY;
        y=0;
        do{
            drawLineReal(g, -0.1, y, 0.1, y);
            y=y+1;
        }
        while (y<=max);

        do{
            drawLineReal(g, -0.1, y, 0.1, y);
            y=y-1;
        }
        while (y>=min);


    }




    public void zeichneNormalparabel(Graphics g, Color farbe){
        int sx, sy;
        Graphics graphicsNormalparabel = null;
        Point2DDouble P = new Point2DDouble(0,0);
        Point PJava;
        double schrittbreite;

        g.setColor(farbe);
        sx = zeichnungJPanel.getSize().width;
        sy = zeichnungJPanel.getSize().height;

        if(flag==0){
            while (sx==0 && sy==0){
            }
            flag=1;
            bildNormalparabel = zeichnungJPanel.createImage(sx, sy);
            graphicsNormalparabel = bildNormalparabel.getGraphics();
            schrittbreite = (Transformation.maxX-Transformation.minX)/10000;

            P.x = Transformation.minX;
            while(P.x<Transformation.maxX){
                PJava = Transformation.transform2DToJava(P.x, P.y);
                graphicsNormalparabel.drawLine(PJava.x, PJava.y, PJava.x+0, PJava.y+0);
                P.x = P.x+ schrittbreite;
                P.y=P.x*P.x;
            }
        }
        g.drawImage(bildNormalparabel,0,0,null);
    }


    public void drawLineReal(Graphics g, double x1, double y1, double x2, double y2){
        Point A2DJava, B2DJava;
        A2DJava = Transformation.transform2DToJava(x1, y1);
        B2DJava = Transformation.transform2DToJava(x2, y2);
        g.drawLine(A2DJava.x, A2DJava.y, B2DJava.x, B2DJava.y);
    }


    public void drawDreieckReal(Graphics g, Color farbe, double x1, double y1, double x2, double y2, double x3, double y3){
        Point A2DJava, B2DJava, C2DJava;
        g.setColor(farbe);
        A2DJava = Transformation.transform2DToJava(x1, y1);
        B2DJava = Transformation.transform2DToJava(x2, y2);
        C2DJava = Transformation.transform2DToJava(x3, y3);

        int[] xPoints = new int[3];
        int[] yPoints = new int[3];
        xPoints[0]=A2DJava.x;
        xPoints[1]=B2DJava.x;;
        xPoints[2]=C2DJava.x;
        yPoints[0]=A2DJava.y;
        yPoints[1]=B2DJava.y;
        yPoints[2]=C2DJava.y;


        g.fillPolygon(xPoints, yPoints, 3);
    }

    public void drawPunktReal(Graphics g, Color farbe, double x, double y){
        int javaAbstand;
        double xobenlinks, yobenlinks, xuntenrechts, yuntenrechts;
        Point A2DJava, B2DJava;
        g.setColor(farbe);

        xobenlinks = x - abstand;
        yobenlinks = y + abstand;
        xuntenrechts = x + abstand;
        yuntenrechts = y - abstand;

        A2DJava = Transformation.transform2DToJava(xobenlinks, yobenlinks);
        B2DJava = Transformation.transform2DToJava(xuntenrechts, yuntenrechts);
        javaAbstand = B2DJava.x -A2DJava.x;

        g.fillOval(A2DJava.x, A2DJava.y,javaAbstand, javaAbstand );
    }




    public boolean istInnerhalb(Point pJavaklick, Point2DDouble p2D){
        boolean b;
        double x,y;
        int javaAbstand;
        double xobenlinks, yobenlinks, xuntenrechts, yuntenrechts;
        int xobenlinksJava, yobenlinksJava, xuntenrechtsJava, yuntenrechtsJava;        
        Point A2DJava, B2DJava;
        x = p2D.x;
        y = p2D.y;

        xobenlinks = x - abstand;
        yobenlinks = y + abstand;
        xuntenrechts = x + abstand;
        yuntenrechts = y - abstand;

        A2DJava = Transformation.transform2DToJava(xobenlinks, yobenlinks);
        B2DJava = Transformation.transform2DToJava(xuntenrechts, yuntenrechts);
        xobenlinksJava = A2DJava.x;
        yobenlinksJava = A2DJava.y;
        xuntenrechtsJava = B2DJava.x;
        yuntenrechtsJava = B2DJava.y;

        b=pJavaklick.x>xobenlinksJava && pJavaklick.x<xuntenrechtsJava && pJavaklick.y>yobenlinksJava && pJavaklick.y<yuntenrechtsJava;
        return b;

    }


    public boolean punktAufKurve(Point pJavaklick){
        boolean b;
        int genauigkeit;
        Point2DDouble p2D;
        double x2DExakt, y2DExakt;

        genauigkeit = 3;
        p2D = Transformation.transformJavaTo2D(pJavaklick.x, pJavaklick.y);
        x2DExakt = p2D.x;
        y2DExakt = p2D.x*p2D.x;
        System.out.println("x2DExakt="+x2DExakt+"y2DExakt="+y2DExakt);
        b = p2D.y > y2DExakt - genauigkeit && p2D.y < y2DExakt + genauigkeit;
        return b;
    }


}
[/Java]

[Java]
package pack1;

import java.awt.Point;

public class Transformation {
    private static double hoehe;
    private static double breite;
    public static double maxX;
    public static double maxY;
    public static double minX;
    public static double minY;

    public static double e;

    // statischer Konstruktor
    static {
        // Anzahl der Pixel für den Einheitswert
        e=30;
    }

    public static void setBreite(double pb){
        breite = pb;
        maxX = 0.75*breite/e;
        minX = -0.25*breite/e;        
    }

    public static void setHoehe(double ph){
        hoehe = ph;
        maxY = 0.95*hoehe/e;
        minY = -0.05*hoehe/e;
    }


    public static Point transform2DToJava(double x, double y){
        double xJava, yJava;
        xJava = breite/4.0 + x*e;
        yJava = 0.95*hoehe - y*e;
        return(new Point((int)xJava, (int)yJava));
    }


    public static Point2DDouble transformJavaTo2D(int xJava, int yJava){
        double x, y;
        x = (xJava - breite/4.0)/e;
        y =  (0.95*hoehe - yJava)/e;
        return(new Point2DDouble(x, y));
    }
}
[/Java]

mfg
Ernst


----------



## Marco13 (15. Feb 2010)

Ich mag ja diese GUI-Builder nicht... Und als ich den Code so stückchenweise rauskopiert habe, wurde mir wieder klar, warum... bei einigen Codestellen hab' ich mir dann gedacht ... "Ohje..." :noe: (und denke das teilweise immernoch) aber....

... wenn man das dann startet, sieht's richtig cool aus :toll:

Meine ... Verwirrung in bzeug auf "setOpaque" hatte einen Grund: JSlider SIND opak, d.h. man muss an einer geeigneten Stelle noch

```
jSlider1.setOpaque(false);
        jSlider2.setOpaque(false);
```
aufrufen.


Dass der Hintergrund der Parabel grau ist, liegt wieder an einem Bild, das den eigentlichen Hintergrund übermalt... diesmal in der Methode "zeichneNormalparabel"... dort muss noch sowas wie

```
graphicsNormalparabel.setColor(zeichnungJPanel.getBackground());
            graphicsNormalparabel.fillRect(0,0,sx,sy);
            graphicsNormalparabel.setColor(farbe);
```
rein...

Nochmal: Insgesamt schon ein hübsches Programm :applaus: (... von "überflüssigen" Images, die erzeugt werden, dem GUI-Builder-Quälcode und solchen "magischen" Zeilen wie [c]y =  (0.95*hoehe - yJava)/e;[/c] mal abgesehen...  )


----------



## ernst (15. Feb 2010)

Marco13 hat gesagt.:


> Ich mag ja diese GUI-Builder nicht... Und als ich den Code so stückchenweise rauskopiert habe, wurde mir wieder klar, warum... bei einigen Codestellen hab' ich mir dann gedacht ... "Ohje..." :noe: (und denke das teilweise immernoch) aber....
> 
> ... wenn man das dann startet, sieht's richtig cool aus :toll:
> 
> ...



Danke für deine Mühe, Aufwand und Hilfe.
Es funktioniert jetzt, so wie du es gesagt hast.

1) 
jSlider1.setOpaque(false);
jSlider2.setOpaque(false);
bedeutet doch optisch (im Gegenbsatz zu jSlider1.setOpaque(true); jSlider2.setOpaque(true)
mache jSlider1 und jSlider2 nicht opak, also nicht undurchsichtig, also transparent.
Ich habe das gemacht. Optisch heißt das, daß alles direkt um den "eigentlichen" Slider herum die Hintergrundfarbe annimmt.
Nur der eigentliche Slider selbst behält seine Farbe.
Wie ist das allgemein, wenn man opak auf false setzt. Wer legt genau fest, wie das dann konkret auszusehen hat?

2) 
Ich habe den Hintgrund jetzt mit VE auf weiß gesetzt (255,255,255).
Aber mir kommt es nicht ganz 100% weiß vor:
Ich meine, daß das weiß im Windows-Malprogramm paint etwas weißer ist. Aber ich kann mich auch täuschen (optische Täuschung).
Was meinst du dazu ?

mfg
Ernst


----------



## Marco13 (16. Feb 2010)

_
Nur der eigentliche Slider selbst behält seine Farbe.
Wie ist das allgemein, wenn man opak auf false setzt. Wer legt genau fest, wie das dann konkret auszusehen hat?
_

Das genaue Aussehen wird vom Look-And-Feel bestimmt (siehe z.B. auch How to Set the Look and Feel (The Java™ Tutorials > Creating a GUI With JFC/Swing > Modifying the Look and Feel) ). Teilweise kann man auch noch die Farben von einzelnen Elementen (wie etwa dem Slider-Knopf) festlegen, aber das ist alles nich offiziell Teil der API, und könnte bei anderen L&Fs nicht funktionieren...


_
Ich habe den Hintgrund jetzt mit VE auf weiß gesetzt (255,255,255).
Aber mir kommt es nicht ganz 100% weiß vor:
Ich meine, daß das weiß im Windows-Malprogramm paint etwas weißer ist. _

Warum muss ich gerade an Waschmittelwerbung denken?  Im Zweifelsfall kannst du ja einen Screenshot machen, und es in einem Malprogramm vergleichen....


----------



## ernst (16. Feb 2010)

Marco13 hat gesagt.:


> ```
> graphics = bild.getGraphics();
> [b]
> graphics.setColor(getBackground());
> ...


1)
Ich erstelle das Bild immer neu, weil bei jeder Veränderung durch die Slider bzw.das Verschieben des Laufpunkts sich auch die Zeichnung (Tangente, Sekante, Laufpunkt, Festpunkt) ändern muss.
Habe ich da einen Denkfehler?

2)
Ausnahme: Die Normalparabel. Diese lasse ich genau einmal in ein Image zeichnen, das ich dann immer wieder benutze (und nicht neu erstelle). Der Grund dafür, ist dass die Normalparabel nicht geändert wird und weil es sehr viel Zeit braucht, diese immer wieder neu zu zeichnen.
Habe ich da einen Denkfehler?

3)
Allerdings habe ich schon Programme gesehen, bei denen mit dem Schieberegler ein Parameter verändert wird und dann sofort die neue Kurve gezeichnet wird:
Beispiel: f(x) = a*x^2
Frage: Wie kann ich das in Java machen, ohne dass ich Laufzeitprobleme bekomme, dh. dass ich zwar den Schieberegler verändere, aber auch die Zeichnung sofort aktualisiert wird (dem aktuelle Parameter angepassst wird) ?

mfg
Ernst


----------



## Marco13 (16. Feb 2010)

_Ich erstelle das Bild immer neu, weil bei jeder Veränderung durch die Slider bzw.das Verschieben des Laufpunkts sich auch die Zeichnung (Tangente, Sekante, Laufpunkt, Festpunkt) ändern muss.
Habe ich da einen Denkfehler?_

Jein. Ein Bild zu erstellen ist vegleichsweise aufwändig - da muss Speicher allokiert und gecleart werden und so - und wenn es dann einmal verwendet wurde, wird es ja jetzt auf den Müll geworfen. OB man sich überhaupt die Arbeit mit diesem Offscreen-Bild machen sollte, und ob man nicht einfach das zeichnen sollte, was man zeichnen will (und zwar in das Graphics, das an die paintComponent übergeben wird) sollte man sich auch überlegen. Es gibt nicht sooo viele Fälle, wo so ein Offscreen-Bild Sinn macht. Aber WENN man eins verwendet, wäre es eben sinnvoller (und effizienter) GROB sowas zu machen wie

```
private BufferedImage offscreenImage = null;

public void paintStuff(...)
{

    // NUR wenn das Image noch nicht existiert, oder sich
    // die Größe geändert hat, wird ein neues angelegt
    if (offscreenImage == null || 
        offscreenImage.getWidth() != getWidth() 
        offscreenImage.getHeight() != getHeight() 
    {
        offscreenImage = ... erstellen ...
    }

    // Hier wird nur der Bildhintergrund gelöscht
    Graphics g = offscreenImage.getGraphics();
    g.setColor(Color.GREEN);
    g.fillRect(0,0,getWidth(),getHeight());
    ....
}
```

Wenn man eine Mischung hat, d.h. ein Teil, der aufwändig zu zeichnen ist, und der in einem Offscreen-Bild liegen soll, und einen anderen Teil, der einfach zu zeichnen ist, und NICHT in einem Offscreen-Bild liegen soll, kann es etwas kniffliger werden, das vernünftig zu "verwalten"... In diesem Fall wäre das aber IMHO eigentlich auch nicht nötig...:

_
Ausnahme: Die Normalparabel. Diese lasse ich genau einmal in ein Image zeichnen, das ich dann immer wieder benutze (und nicht neu erstelle). Der Grund dafür, ist dass die Normalparabel nicht geändert wird und weil es sehr viel Zeit braucht, diese immer wieder neu zu zeichnen.
Habe ich da einen Denkfehler?
_

Jein. So eine Parabel/Funktion kann relativ viel Zeit beanspruchen. Wichtig sind dabei die Worte "kann" und "relativ". Wenn man komplexere Funktionen zeichnen will, und sich vorstellt, man hätte z.B. eine Funktion wie

```
f(x) = sin(x)+tan(x)*cos(cos(cos(x))) + ackermann(x,3) + factorial(x) + busyBeaver(sin(x)*pow(10,x));
```
wo allein eine _Auswertung_ der Funktion 10 Minuten dauert, dann wollte man das natürlich nicht bei jedem Neuzeichnen 1000000 mal machen - insbesondere, wenn sich nichts ändert. Spätestens, wenn man die Funktion durch verschieben eines Sliders ändern will, muss man sie aber sowieso schnell ausrechnen können. Ob man sich DANN noch unterschiedliche Behandlungen für die Fälle überlegt...
- es wird die Funktion geändert
- es wird nur eine Tangente (oder so) geändert
... müßte man sich noch überlegen.

Ganz allgemein dürfte ein Problem bei der aktuellen Implementierung aber in dieser Zeile stecken:

```
schrittbreite = (Transformation.maxX-Transformation.minX)/10000;
```
Diese 10000 ist ja vollkommen willkürlich gewählt. Und wenn man z.B. den Bereich zwischen -1000000 und +1000000 plotten wollte, wäre der Wert auch vollkommen "falsch". 

Sinnvoller wäre es, genau das zu machen, was gemacht werden muss: Man kann ja nicht mehr Punkte (in x-Richtung) haben, als es Pixel auf dem Bildschirm gibt  In diesem Fall könnte man also sowas machen wie

```
int xs = 0; // Position in Screen-Koordinaten
int ys = 0; // Position in Screen-Koordinaten
double xw = 0; // Position in "Weltkoordinaten"
double yw = 0; // Position in "Weltkoordinaten"
// (Die Umrechnungen zwischen diesen Koordinatensystemen
// sind ja schon schön in der Transformation-Klasse gekapselt -
// wobei ich DRINGENDST empfehlen würde, zu versuchen, dort
// diese magischen Konstanten wie 30 und 0.95 und so rauszunehmen...)

for (xs=0; xs<breiteInPixeln; xs++)
{
    xw = Transoformation.screeenToWorldX(xs);
    yw = funktionAuswerten(xw); // Die Parabel oder sonstwas...
    ys = Transoformation.worldToScreenY(yw);

    drawLineTo(xs,ys);
}
```

Das ist nur Pseudocode - man müßte die Positionen für x=0 speichern dann die Schleife bei 1 loslaufen lassen, und immer sowas wie

```
drawLine(previousX, previousY, xs,ys);
previousX = xs;
previousY = ys;
```
machen... aber vom Ansatz her: Man rechnet die (sehr wenigen!) Pixel in Weltkoordinaten um, berechnet den Funktionswert dafür, und DEN rechnet man dann wieder zurück in Pixelkoordinaten.

Hier wäre auch ein Ansatzpunkt für eine Optimierung, FALLS das Auswerten der Funktion extrem aufwändig wäre: Man könnte einen

```
double yWorldValues[] = new double[bildBreiteInPixeln];

// oder int yScreenValues[] = new int[bildBreiteInPixeln];
// oder Point screenPoints[] = ...
// oder Point2D worldPoints[] = ...
```
erstellen, der die EINmal ausgrechneten Funktionswerte (als Welt- oder Screenkoordinaten) speichert, und beim Zeichnen nurnoch durch den Array läuft und den Graph für die vorberechneten Werte malt.

Genaugenommen "sollte" man sowas auch machen, weil man in der paint-Methode eigentlich so wenig wie möglich _rechnen_, sondern eigentlich NUR zeichnen sollte - aber man muss sich erstmal geeignete Strukturen und update-Mechanismen für diesen Werte-Array überlegen - für die Normalparabel kann man eine Berechnung in der paint-Methode wohl noch vertreten, aber du kannst ja mal weiter drüber nachdenken... Speziell auch in bezug auf den nächsten Punkt:


_
Allerdings habe ich schon Programme gesehen, bei denen mit dem Schieberegler ein Parameter verändert wird und dann sofort die neue Kurve gezeichnet wird:
Beispiel: f(x) = a*x^2
Frage: Wie kann ich das in Java machen, ohne dass ich Laufzeitprobleme bekomme, dh. dass ich zwar den Schieberegler verändere, aber auch die Zeichnung sofort aktualisiert wird (dem aktuelle Parameter angepassst wird) ?
_

Das ist ja oben schon angedeutet  Ich glaube, einer der wichtigsten Punkte ist, die Funktion nur an den (Welt)koordinaten auszuwerten, die den Pixelpositionen entsprechen. Damit geht das ganze schon sehr flott. (Eigentlich auch für komplizierte Funktionen - dass man in der paint-Methode nicht so viel rechnen sollte, könnte man da schon fast als eine "Prinzipsache" bezeichnen...)


----------



## ernst (17. Feb 2010)

Marco13 hat gesagt.:


> Ich glaube, einer der wichtigsten Punkte ist, die Funktion nur an den (Welt)koordinaten auszuwerten, die den Pixelpositionen entsprechen. Damit geht das ganze schon sehr flott. (Eigentlich auch für komplizierte Funktionen - dass man in der paint-Methode nicht so viel rechnen sollte, könnte man da schon fast als eine "Prinzipsache" bezeichnen...)



Habe deine wertvollen Tipps berücksichtigt (siehe Programm unten)

1) Wenn ich BufferedImage benutzte (statt Image) sagt mir der Compiler, dass er createImage nicht kennt.
Was kann ich machen, damit  er das kennt?

2) Kann ich statt BufferedImage auch Image benutzen (so wie in meinem Programm), oder welche Nachteile hole ich mir mit Image statt BuffereImage ?

3) 
Wenn ich die Parabel nur einmal zeichne, unten öfters mal das Fenster verkleiner und vergrößere und dabei den unteren Schieberegler verstelle, wird meine Parabel manchmal etwas verschoben.
An was liegt das?
Wie kann ich es ändern (ohne dass ich die Parabel jedesmal neu zeichne) ?

4)
Ist deiner Meinung nach der Hintergrund wirklich weiss?

Bem: Rest des Programm ist im nächsten Posting

mfg
Ernst

[Java]
package pack1;

public class Point2DDouble {
    public double x;
    public double y;

    public Point2DDouble(double px, double py) {
        x = px;
        y = py;
    }
}
[/Java]


[Java]
package pack1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JLabel;

public class Tangente{
    private ZeichnungJPanel zeichnungJPanel;
    private Point2DDouble festPunkt;
    private Point2DDouble laufPunkt;
    private Image bildNormalparabel;
    private int flag;
    // Halbe Dicke eines Punktes auf dem Bildschirm
    private double abstand;

    public Tangente(ZeichnungJPanel pZeichnungJPanel){
        zeichnungJPanel = pZeichnungJPanel;
        festPunkt = new Point2DDouble(0,0);
        laufPunkt = new Point2DDouble(0,0);
        flag = 0;
        abstand = 0.1;
    }

    public void setFestPunkt(double px, double py){
        festPunkt.x = px;
        festPunkt.y = py;
    }

    public Point2DDouble getFestPunkt(){
        return(festPunkt);
    }

    public void setLaufPunkt(double px, double py){
        laufPunkt.x = px;
        laufPunkt.y = py;
    }

    public Point2DDouble getLaufPunkt(){
        return(laufPunkt);
    }

    public void berechnePos(){
        // Parameter deltaX holen
        double parameterDeltaX, parameterXFestpunkt;
        parameterDeltaX = zeichnungJPanel.getParameterDeltaX();
        //System.out.println("parameterDeltaX=="+parameterDeltaX);
        parameterXFestpunkt = zeichnungJPanel.getParameterXFestpunkt();
        festPunkt.x =  parameterXFestpunkt;
        //System.out.println("festPunkt.x=="+festPunkt.x);
        festPunkt.y =  festPunkt.x * festPunkt.x;
        //System.out.println("festPunkt.x="+festPunkt.x);

        laufPunkt.x =  festPunkt.x + parameterDeltaX;
        laufPunkt.y =  laufPunkt.x * laufPunkt.x;
        //System.out.println("laufPunkt.x="+laufPunkt.x+" laufPunkt.y"+laufPunkt.y);
    }

    public void zeichneSekante(Graphics g, Color farbe){
        //Java-Koordinaten Festpunkt und Laufpunkt
        //Einheitswert:
        double x1, y1, x2, y2;
        // Zeichne delta y
        x1 = laufPunkt.x;
        y1 = laufPunkt.y;
        x2 = laufPunkt.x;
        y2 = festPunkt.y;
        //g.drawLine(anfangPunktJava.x, anfangPunktJava.y, endPunktJava.x, endPunktJava.y);
        g.setColor(Color.red);
        drawLineReal(g, x1, y1, x2, y2);
        drawPunktReal(g, Color.magenta, festPunkt.x, festPunkt.y);
        drawPunktReal(g, Color.darkGray, laufPunkt.x, laufPunkt.y);

        // Zeichne delta x
        x1 = festPunkt.x;
        y1 = festPunkt.y;
        x2 = laufPunkt.x;
        y2 = festPunkt.y;
        g.setColor(Color.blue);
        drawLineReal(g, x1, y1, x2, y2);


        /* Sekandengleichung berechnen:
        y = (yL-yF)/(xL-xF)*(x-xF)+yF
        */
        // Zeichne Gerade
        x1=Transformation.wMinX;
        y1=(laufPunkt.y-festPunkt.y)/(laufPunkt.x-festPunkt.x)*(x1-festPunkt.x)+festPunkt.y;

        x2=Transformation.wMaxX;
        y2=(laufPunkt.y-festPunkt.y)/(laufPunkt.x-festPunkt.x)*(x2-festPunkt.x)+festPunkt.y;
        g.setColor(farbe);
        drawLineReal(g, x1, y1, x2, y2);
    }

    public void zeichneTangente(Graphics g, Color farbe){
        /* Tangentengleichung t:
        y = 2*(x-festpunkt.x)+  festpunkt.y
        */
        double xBeginn, xEnde, yBeginn, yEnde;
        g.setColor(farbe);
        xBeginn = Transformation.wMinX;
        xEnde = Transformation.wMaxX;
        yBeginn = 2*festPunkt.x*(xBeginn-festPunkt.x)+  festPunkt.y;
        yEnde = 2*festPunkt.x*(xEnde-festPunkt.x)+  festPunkt.y;
        drawLineReal(g, xBeginn, yBeginn, xEnde, yEnde);
    }

    public void zeichneAchsenkreuz(Graphics g, Color farbe){
        Point2DDouble A2D = new Point2DDouble(0,0);
        Point2DDouble B2D = new Point2DDouble(0,0);

        g.setColor(farbe);
        // x-Achse zeichnen
        A2D.x = Transformation.wMinX;
        A2D.y = 0;
        B2D.x = Transformation.wMaxX;;
        B2D.y = 0;
        drawLineReal(g, A2D.x, A2D.y, B2D.x, B2D.y);
        // Pfeilspitze zeichnen
        drawDreieckReal(g, Color.black, B2D.x, B2D.y, B2D.x-0.2, B2D.y+0.2, B2D.x-0.2, B2D.y-0.2);
        beschrifteAchsenkreuz(g, farbe);

        // y-Achse zeichnen
        A2D.x = 0;
        A2D.y = Transformation.wMinY;
        B2D.x=0;
        B2D.y=Transformation.wMaxY;
        drawLineReal(g, A2D.x, A2D.y, B2D.x, B2D.y);
        // Pfeilspitze zeichnen
        drawDreieckReal(g, Color.black, B2D.x, B2D.y, B2D.x-0.2, B2D.y-0.2, B2D.x+0.2, B2D.y-0.2);
    }

    public void beschrifteAchsenkreuz(Graphics g, Color farbe){
        double min, max, x, y;
        //x-Achse beschriften
        min = Transformation.wMinX;
        max = Transformation.wMaxX;
        x=0;
        do{
            //System.out.println(" min="+min+" max="+max+" x="+x);
            drawLineReal(g, x, 0.1, x, -0.1);
            x=x+1;
        }
        while (x<=max);

        x=0;
        do{
            //System.out.println(" min="+min+" max="+max+" x="+x);
            drawLineReal(g, x, 0.1, x, -0.1);
            x=x-1;
        }
        while (x>=min);

        //y-Achse beschriften
        min = Transformation.wMinY;
        max = Transformation.wMaxY;
        y=0;
        do{
            //System.out.println(" min="+min+" max="+max+" x="+x);
            drawLineReal(g, -0.1, y, 0.1, y);
            y=y+1;
        }
        while (y<=max);

        do{
            //System.out.println(" min="+min+" max="+max+" x="+x);
            drawLineReal(g, -0.1, y, 0.1, y);
            y=y-1;
        }
        while (y>=min);


    }


    public void zeichneNormalparabel(Graphics g, Color farbe){
        int sx, sy;
        Graphics graphicsNormalparabel = null;
        // Bereich der x-Werte D = [a, b]
        double a, b;
        int breiteInPixel;
        int xScreenAlt, yScreenAlt, xScreen, yScreen;
        double xwAlt, ywAlt, xw, yw;
        int i;
        a = Transformation.wMinX;
        b = Transformation.wMaxX;
        // Anzahl der Pixel berechnen zwischen A(-4,5|0) und B(4,5|0)
        breiteInPixel = Transformation.transform2DWeltToScreenX(b)-
                                Transformation.transform2DWeltToScreenX(a);
        //System.out.println("Anzahl der Pixel="+breiteInPixel);
        //System.out.println("Transformation.getScreenBreite()="+Transformation.getScreenBreite()+"Transformation.getScreenHoehe()="+Transformation.getScreenHoehe());

        g.setColor(farbe);
        sx = zeichnungJPanel.getSize().width;
        sy = zeichnungJPanel.getSize().height;
        //System.out.println("sx="+sx+"=sy="+sy);

        if(flag==0){
            while (sx==0 && sy==0){
            }
            flag=1;
            bildNormalparabel = zeichnungJPanel.createImage(sx, sy);
            // Erzeuge den zu dem Grafikobjekt bild zugehörigen Grafikkontext,
            // d.h. eine Leinwand, in die gemalt wird.
            graphicsNormalparabel = bildNormalparabel.getGraphics();
            // mit den 2 Anweisungen wird der Hintergrund ausgegeben
            // unbedingt nötig
            //graphics.setColor(getBackground());
            graphicsNormalparabel.setColor(zeichnungJPanel.getBackground());
            graphicsNormalparabel.fillRect(0,0,sx,sy);

            graphicsNormalparabel.setColor(farbe);

            //System.out.println("schrittbreite"+schrittbreite);
            xScreenAlt = Transformation.transform2DWeltToScreenX(a);
            yScreenAlt = Transformation.transform2DWeltToScreenY(a*a);
            xScreen = xScreenAlt;
            yScreen = yScreenAlt;
            for(i=1;i<breiteInPixel;i++){
                xScreen = xScreen + 1;
                xw = Transformation.transformScreenTo2DWeltX(xScreen);
                yw = xw*xw;
                //System.out.println("xw="+xw+" yw="+yw);
                yScreen = Transformation.transform2DWeltToScreenY(yw);
                //System.out.println("xScreen+i="+(xScreen+i)+" yScreen="+yScreen);
                //graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreen, yScreen);
                graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreenAlt, yScreenAlt);
                xScreenAlt = xScreen;
                yScreenAlt = yScreen;
            }
        }
        g.drawImage(bildNormalparabel,0,0,null);
    }


    public void drawLineReal(Graphics g, double x1, double y1, double x2, double y2){
        Point A2DScreen, B2DScreen;
        A2DScreen = Transformation.transform2DWeltToScreen(x1, y1);
        B2DScreen = Transformation.transform2DWeltToScreen(x2, y2);
        g.drawLine(A2DScreen.x, A2DScreen.y, B2DScreen.x, B2DScreen.y);
    }


    public void drawDreieckReal(Graphics g, Color farbe, double x1, double y1, double x2, double y2, double x3, double y3){
        Point A2DScreen, B2DScreen, C2DScreen;
        g.setColor(farbe);
        A2DScreen = Transformation.transform2DWeltToScreen(x1, y1);
        B2DScreen = Transformation.transform2DWeltToScreen(x2, y2);
        C2DScreen = Transformation.transform2DWeltToScreen(x3, y3);

        // Pfeil zeichnen
        int[] xPoints = new int[3];
        int[] yPoints = new int[3];
        xPoints[0]=A2DScreen.x;
        xPoints[1]=B2DScreen.x;;
        xPoints[2]=C2DScreen.x;
        yPoints[0]=A2DScreen.y;
        yPoints[1]=B2DScreen.y;
        yPoints[2]=C2DScreen.y;


        g.fillPolygon(xPoints, yPoints, 3);
    }

    public void drawPunktReal(Graphics g, Color farbe, double x, double y){
        int javaAbstand;
        double xobenlinks, yobenlinks, xuntenrechts, yuntenrechts;
        Point A2DScreen, B2DScreen;
        g.setColor(farbe);

        xobenlinks = x - abstand;
        yobenlinks = y + abstand;
        xuntenrechts = x + abstand;
        yuntenrechts = y - abstand;

        A2DScreen = Transformation.transform2DWeltToScreen(xobenlinks, yobenlinks);
        B2DScreen = Transformation.transform2DWeltToScreen(xuntenrechts, yuntenrechts);
        javaAbstand = B2DScreen.x -A2DScreen.x;

        g.fillOval(A2DScreen.x, A2DScreen.y,javaAbstand, javaAbstand );
    }




    public boolean istInnerhalb(Point pJavaklick, Point2DDouble p2D){
        boolean b;
        double x,y;
        int javaAbstand;
        double xobenlinks, yobenlinks, xuntenrechts, yuntenrechts;
        int xobenlinksScreen, yobenlinksScreen, xuntenrechtsScreen, yuntenrechtsScreen;
        Point A2DScreen, B2DScreen;
        x = p2D.x;
        y = p2D.y;

        xobenlinks = x - abstand;
        yobenlinks = y + abstand;
        xuntenrechts = x + abstand;
        yuntenrechts = y - abstand;

        A2DScreen = Transformation.transform2DWeltToScreen(xobenlinks, yobenlinks);
        B2DScreen = Transformation.transform2DWeltToScreen(xuntenrechts, yuntenrechts);
        xobenlinksScreen = A2DScreen.x;
        yobenlinksScreen = A2DScreen.y;
        xuntenrechtsScreen = B2DScreen.x;
        yuntenrechtsScreen = B2DScreen.y;

        b=pJavaklick.x>xobenlinksScreen && pJavaklick.x<xuntenrechtsScreen && pJavaklick.y>yobenlinksScreen && pJavaklick.y<yuntenrechtsScreen;
/*
        System.out.println("pJavaklick.x="+pJavaklick.x+"xobenlinksJava"+xobenlinksJava);
        System.out.println("pJavaklick.x="+pJavaklick.x+"xobenlinksJava"+xobenlinksJava);
*/
        return b;

    }


    public boolean punktAufKurve(Point pJavaklick){
        boolean b;
        int genauigkeit;
        Point2DDouble p2D;
        double x2DExakt, y2DExakt;

        genauigkeit = 3;
        p2D = Transformation.transformScreenTo2DWelt(pJavaklick.x, pJavaklick.y);
        x2DExakt = p2D.x;
        y2DExakt = p2D.x*p2D.x;
        System.out.println("x2DExakt="+x2DExakt+"y2DExakt="+y2DExakt);
        b = p2D.y > y2DExakt - genauigkeit && p2D.y < y2DExakt + genauigkeit;
        return b;
/*
        System.out.println("pJavaklick.x="+pJavaklick.x+"xobenlinksJava"+xobenlinksJava);
        System.out.println("pJavaklick.x="+pJavaklick.x+"xobenlinksJava"+xobenlinksJava);
*/
    }


}

[/Java]


----------



## ernst (17. Feb 2010)

Marco13 hat gesagt.:


> _
> Wenn man eine Mischung hat, d.h. ein Teil, der aufwändig zu zeichnen ist, und der in einem Offscreen-Bild liegen soll, und einen anderen Teil, der einfach zu zeichnen ist, und NICHT in einem Offscreen-Bild liegen soll, kann es etwas kniffliger werden, das vernünftig zu "verwalten"... In diesem Fall wäre das aber IMHO eigentlich auch nicht nötig...:
> _


_
Hier ist der 2. Rest:

[Java]
package pack1;

import java.awt.Point;

public class Transformation {
    // Höhe des Sreen
    private static int sHoehe;
    // Breite des Screen
    private static int sBreite;
    // Maximale x-Koordinate im Welt-Koordinatensystem
    public static double wMaxX;
    // Maximale y-Koordinate im Welt-Koordinatensystem
    public static double wMaxY;
    // Minimale x-Koordinate im Welt-Koordinatensystem
    public static double wMinX;
    // Minimale y-Koordinate im Welt-Koordinatensystem
    public static double wMinY;


    // statischer Konstruktor
    static {


    }

    public static void setScreenBreite(int psb){
        sBreite = psb;
    }

    public static void setScreenHoehe(int psh){
        sHoehe = psh;
    }

    public static int getScreenBreite(){
        return sBreite;
    }


    public static int getScreenHoehe(){
        return sHoehe;
    }

    public static void setWeltMinMax(double pwMinX, double pwMinY, double pwMaxX, double pwMaxY){
        wMinX=pwMinX;
        wMinY=pwMinY;
        wMaxX=pwMaxX;
        wMaxY=pwMaxY;
    }

    public static Point transform2DWeltToScreen(double pxw, double pyw){
        int xs, ys;
        xs = (int)(sBreite/(wMaxX-wMinX) * (pxw-wMinX));
        ys = (int) (sHoehe - sHoehe/(wMaxY-wMinY) * (pyw-wMinY));
        return(new Point(xs, ys));
    }


    public static int transform2DWeltToScreenX(double pxw){
        int xs;
        xs = (int)(sBreite/(wMaxX-wMinX) * (pxw-wMinX));
        return(xs);
    }

    public static int transform2DWeltToScreenY(double pyw){
        int ys;
        ys = (int) (sHoehe - sHoehe/(wMaxY-wMinY) * (pyw-wMinY));
        return(ys);
    }


    public static Point2DDouble transformScreenTo2DWelt(int pxs, int pys){
        double xw, yw;
        xw = (wMaxX-wMinX)/sBreite *pxs + wMinX;
        yw = (wMaxY-wMinY)/sHoehe * (sHoehe-pys) + wMinY;
        return(new Point2DDouble(xw, yw));
    }

    public static double transformScreenTo2DWeltX(int pxs){
        double xw;
        xw = (wMaxX-wMinX)/sBreite *pxs + wMinX;
        return(xw);
    }

    public static double transformScreenTo2DWeltY(int pys){
        double yw;
        yw = (wMaxY-wMinY)/sHoehe * (sHoehe-pys) + wMinY;
        return(yw);
    }


}







[/Java]

[Java]
package pack1;

import java.awt.Color;
import java.util.Hashtable;
import javax.swing.JLabel;
import javax.swing.JSlider;

public class ZeichnungJFrame extends javax.swing.JFrame {
    private ZeichnungJPanel zeichnungJPanel;

    public ZeichnungJFrame() {
        String s1, s2, s3;
        initComponents();
        //getContentPane().setBackground(new java.awt.Color(255, 204, 153));
        getContentPane().setBackground(Color.green);
        s1="Sekantensteigung und Tangentensteigung: ";
        s2="deltaX, x-Wert des Festpunktes (mit Schieberegler) und Laufpunkt ";
        s3="(mit der Maus) veränderbar";
        setTitle(s1+s2+s3);
        int slidermin = -100;
        int slidermax = 100;
        this.setSize(1000, 700);

        zeichnungJPanel = new ZeichnungJPanel(this);
        // An die Zeichenfläche muss das SpielJFrame montiert werden.
        jPanel1.add(zeichnungJPanel, "Center");
        // Maximaler Wert, den der Slider (Schieberegöler ganz links) zurückgibt
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // Kaum zu glauben, aber laut Debugger ruft setMinimum() die
        // Methode jSlider1.changeEvent() auf
        jSlider1.setMinimum(slidermin);
        jSlider1.setMaximum(slidermax);
        jSlider1.setOrientation(JSlider.HORIZONTAL);
        jSlider1.setPaintLabels(true);
        jSlider1.setPaintTicks(true);
        jSlider1.setMajorTickSpacing(10 );
        Hashtable labelTable = new Hashtable();
        labelTable.put(new Integer(slidermin), new JLabel(Integer.toString(slidermin/10)));
        labelTable.put(new Integer(0), new JLabel("0"));
        labelTable.put(new Integer(slidermax), new JLabel(Integer.toString(slidermax/10)));
        jSlider1.setLabelTable(labelTable);

        // Maximaler Wert, den der Slider (Schieberegöler ganz links) zurückgibt
        jSlider2.setMinimum(slidermin);
        jSlider2.setMaximum(slidermax);
        jSlider2.setOrientation(JSlider.HORIZONTAL);
        jSlider2.setPaintLabels(true);
        jSlider2.setPaintTicks(true);
        jSlider2.setMajorTickSpacing(10 );
        Hashtable labelTable2 = new Hashtable();
        labelTable2.put(new Integer(slidermin), new JLabel(Integer.toString(slidermin/10)));
        labelTable2.put(new Integer(0), new JLabel("0"));
        labelTable2.put(new Integer(slidermax), new JLabel(Integer.toString(slidermax/10)));
        jSlider2.setLabelTable(labelTable2);

        jSlider1.setOpaque(false);
        jSlider2.setOpaque(false);

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jSlider1 = new javax.swing.JSlider();
        jSlider2 = new javax.swing.JSlider();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        tx1 = new javax.swing.JTextField();
        tx2 = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        tx3 = new javax.swing.JTextField();
        tx4 = new javax.swing.JTextField();
        tx5 = new javax.swing.JTextField();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        tx6 = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.setBackground(new java.awt.Color(204, 255, 204));
        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setLayout(new java.awt.BorderLayout());

        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider1StateChanged(evt);
            }
        });

        jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider2StateChanged(evt);
            }
        });

        jLabel1.setText("delta x verändern");

        jLabel2.setText("x-Wert des Festpunktes verändern");

        jLabel3.setText("x-Koordinate Festpunkt");

        jLabel4.setText("y-Koordinate Festpunkt");

        tx1.setText("jTextField1");
        tx1.setEnabled(false);

        tx2.setText("jTextField2");
        tx2.setEnabled(false);

        jLabel5.setForeground(new java.awt.Color(255, 51, 51));
        jLabel5.setText("deltaY");

        jLabel6.setText("--------");

        jLabel7.setForeground(new java.awt.Color(0, 51, 255));
        jLabel7.setText("deltaX");

        jLabel8.setText("=");

        tx3.setForeground(new java.awt.Color(255, 51, 51));
        tx3.setText("jTextField3");
        tx3.setEnabled(false);

        tx4.setForeground(new java.awt.Color(51, 51, 255));
        tx4.setText("jTextField4");
        tx4.setEnabled(false);

        tx5.setText("jTextField5");
        tx5.setEnabled(false);

        jLabel9.setText("=");

        jLabel10.setText("---------------------------------");

        jLabel11.setText("-");

        tx6.setText("jTextField6");
        tx6.setEnabled(false);

        jTextArea1.setColumns(20);
        jTextArea1.setEditable(false);
        jTextArea1.setRows(5);
        jTextArea1.setText("I) Beschreibung (Einführung in die Differentialrechnung):\nDurch den Laufpunkt und den Festpunkt ist die Sekante festgelegt.\nDer Laufpunkt kann durch die Maus oder den oberen Schiebregler verändert \nwerden.\nDer Festpunkt kann nur durch den unteren Schieberegler verändert werden.\nDurch den Laufpunkt und den Festpunkt ist die Sekantensteigung bestimmt.\nSekantensteigung = deltaY : deltaX\n\nII) Aufgaben:\n1) Berechnen Sie die Sekantensteigung für deltax=1, 2, 3, 4\n\n2) Bewegen Sie dann den Laufpunkt immer weiter gegen den Festpunkt\nund überprüfen Sie Ihre Ergebnisse mit denen des Programms.\nGegen welche Steigung strebt dann die Sekantensteigung ?\n\n3) Welche Steigung hat damit die Tangente ? ");
        jScrollPane1.setViewportView(jTextArea1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 543, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, 399, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, 390, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel3)
                                .addGap(18, 18, 18)
                                .addComponent(tx1, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(229, 229, 229))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel5)
                                    .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jLabel7))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel8)
                                .addGap(12, 12, 12)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addGap(14, 14, 14)
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                .addComponent(jLabel10, javax.swing.GroupLayout.DEFAULT_SIZE, 162, Short.MAX_VALUE)
                                                .addGap(18, 18, 18)
                                                .addComponent(jLabel9)
                                                .addGap(18, 18, 18)
                                                .addComponent(tx6, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE))
                                            .addGroup(layout.createSequentialGroup()
                                                .addComponent(tx3, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addGap(26, 26, 26)
                                                .addComponent(tx4, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))))
                                    .addGroup(layout.createSequentialGroup()
                                        .addGap(60, 60, 60)
                                        .addComponent(tx5, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel4)
                                .addGap(18, 18, 18)
                                .addComponent(tx2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(229, 229, 229)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel11, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(814, 814, 814))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 1250, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 109, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel11)
                        .addGap(92, 92, 92))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(jLabel3)
                                    .addComponent(tx1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(jLabel4)
                                    .addComponent(tx2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(tx3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jLabel5)
                                    .addComponent(tx4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(jLabel10)
                                    .addComponent(jLabel9)
                                    .addComponent(jLabel6)
                                    .addComponent(jLabel8)
                                    .addComponent(tx6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel7))
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addComponent(tx5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(2, 2, 2)))
                        .addContainerGap())))
        );

        pack();
    }// </editor-fold>                        

    private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {                                      
        String str;
        int wert;
        // double Wert
        double dWert;
        wert = jSlider1.getValue();
        // mache daraus einen doubel-Wert:
        dWert = wert / 10.0;
        zeichnungJPanel.setParameterDeltaX(dWert);
        zeichnungJPanel.allesUpdaten();
        zeichnungJPanel.maleKomplettesFenster();
        //System.out.println("jSlider1StateChanged wurde aufgerufen");
    }                                     

    private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt) {                                      
        String str;
        int wert;
        // double Wert
        double dWert;
        wert = jSlider2.getValue();
        // mache daraus einen doubel-Wert:
        dWert = wert / 10.0;

        zeichnungJPanel.setParameterXFestpunkt(dWert);
        zeichnungJPanel.allesUpdaten();
        zeichnungJPanel.maleKomplettesFenster();
        //System.out.println("jSlider2StateChanged wurde aufgerufen");
    }                                     


    public void maleRestZeichnungJFrame(){
        String str;
        float ergebnis;
        double xFestpunkt, yFestpunkt, xLaufpunkt, yLaufpunkt, erg;
        xFestpunkt = zeichnungJPanel.getTangente().getFestPunkt().x;
        yFestpunkt = zeichnungJPanel.getTangente().getFestPunkt().y;
        xLaufpunkt = zeichnungJPanel.getTangente().getLaufPunkt().x;
        yLaufpunkt = zeichnungJPanel.getTangente().getLaufPunkt().y;

        //System.out.println("_xFestpunkt="+xFestpunkt);
        //System.out.println("_xLaufpunkt=="+xLaufpunkt);

        int sliderwert;
        //System.out.println("xLaufpunkt-xFestpunkt=="+(xLaufpunkt-xFestpunkt)+" sliderwert="+sliderwert);
        /* A C H T U N G:
        sliderwert=(int)((xLaufpunkt-xFestpunkt)*10);
        lieferte
        xLaufpunkt-xFestpunkt==2.9999999999999996 und damit
        sliderwert=29
        D E S W E G EN   die folgende Konstruktion
        */
        ergebnis=(float)((xLaufpunkt-xFestpunkt)*10);
        sliderwert=Math.round(ergebnis);
        jSlider1.setValue(sliderwert);

        sliderwert=(int)(xFestpunkt*10);
        jSlider2.setValue(sliderwert);

        str = new String(String.valueOf(xFestpunkt));
        tx1.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(yFestpunkt));
        tx2.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(yLaufpunkt));
        tx3.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(yFestpunkt));
        tx4.setText(str.substring(0,str.length()<6?str.length():5));

        str = new String(String.valueOf(xLaufpunkt-xFestpunkt));
        tx5.setText(str.substring(0,str.length()<6?str.length():5));

        String s;
        if (xLaufpunkt-xFestpunkt==0)
            s="nicht definiert";
        else{
            erg = (yLaufpunkt-yFestpunkt)/(xLaufpunkt-xFestpunkt);
            str = new String(String.valueOf(erg));
            s = str.substring(0,str.length()<6?str.length():5);
        }
        tx6.setText(s);
    }


    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                // Orginal
                //new ZeichnungJFrame().setVisible(true);
                ZeichnungJFrame zeichnungJFrame = new ZeichnungJFrame();
                zeichnungJFrame.setVisible(true);
                zeichnungJFrame.zeichnungJPanel.setParameterDeltaX(3);
                zeichnungJFrame.zeichnungJPanel.setParameterXFestpunkt(1);
                zeichnungJFrame.zeichnungJPanel.allesUpdaten();
                zeichnungJFrame.zeichnungJPanel.maleKomplettesFenster();

            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSlider jSlider2;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextField tx1;
    private javax.swing.JTextField tx2;
    private javax.swing.JTextField tx3;
    private javax.swing.JTextField tx4;
    private javax.swing.JTextField tx5;
    private javax.swing.JTextField tx6;
    // End of variables declaration                   

}

[/Java]_


----------



## ernst (17. Feb 2010)

Marco13 hat gesagt.:


> Das ist ja oben schon angedeutet  Ich glaube, einer der wichtigsten Punkte ist, die Funktion nur an den (Welt)koordinaten auszuwerten, die den Pixelpositionen entsprechen. Damit geht das ganze schon sehr flott. (Eigentlich auch für komplizierte Funktionen - dass man in der paint-Methode nicht so viel rechnen sollte, könnte man da schon fast als eine "Prinzipsache" bezeichnen...)



Hier der 3. Rest

[Java]
package pack1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
//import java.awt.image.BufferedImage;


public class ZeichnungJPanel extends javax.swing.JPanel implements MouseListener, MouseMotionListener {
    ZeichnungJFrame zeichnungJFrame;
//  private BufferedImage bild;
    private Image bild;
    private Tangente tangente;
    // Parameter t der Geraden
    private double parameterDeltaX;
    private double parameterxFestpunkt;
    private Graphics graphicsNormalparabel;
//    private BufferedImage bildNormalparabel;
    private Image bildNormalparabel;
    private int anzahlMausImPunkt;
    private int flag = 0;



    public ZeichnungJPanel(ZeichnungJFrame pZeichnungJFrame) {
        initComponents();
        zeichnungJFrame = pZeichnungJFrame;
        // Welt-Koordinatensystem festlegen
        Transformation.setWeltMinMax(-4.5, -1, 4.5, 16);
        tangente = new Tangente(this);
        addMouseMotionListener(this);
        addMouseListener(this);
        parameterDeltaX=3;
        parameterxFestpunkt=1;
        anzahlMausImPunkt=0;

    }

	/**
	 * Gibt Tangente zurück.<br><br>
	 * <b>Beispiel:</b><br>
	 * tangente.getTangente();<br>
	 * @param pp1 (i) erster Punkt
	 * @param pp2 (i) zweiter Punkt
	 * @throws Throwable wenn die zwei Punkte identisch sind
	 */
    public Tangente getTangente(){
        return tangente;
    }

	/**
	 * legt Festpunkt auf Parabel fest.<br><br>
	 * @param pp1 (i) Festpunkt
	 */

    public void setParameterXFestpunkt(double pParameterxFestpunkt){
        parameterxFestpunkt = pParameterxFestpunkt;
    }

    public double getParameterXFestpunkt(){
        return parameterxFestpunkt;
    }

    public void setParameterDeltaX(double pDeltaX){
        parameterDeltaX = pDeltaX;
    }

    public double getParameterDeltaX(){
        return parameterDeltaX;
    }

    public void allesUpdaten() {
        //System.out.println("this.getWidth()="+this.getWidth()+"this.getHeight="+this.getHeight());
        tangente.berechnePos();
    }

    public void maleKomplettesFenster(){
        maleZeichnungJPanelOffscreen();
        zeichnungJFrame.maleRestZeichnungJFrame();
        repaint();
    }


    public void maleZeichnungJPanelOffscreen(){
        int sx, sy;
        Graphics graphics=null;

        sx = this.getSize().width;
        sy = this.getSize().height;

        /*
        Ein Bild zu erstellen ist aufwändig: es muss Speicher allokiert
        und gecleart werden. Deshalb sollte das nur einmal gemacht werden.
        */
        /* Da sx und sy erts nach der Anweisung
        zeichnungJFrame.setVisible(true);
        einen Wert != 0 haben, aber die folgenden Anweisungen schon vorher
        durchgeführt werden, muss sx und sy abgefragt werden
        */
        if(bild==null || bild.getWidth(this)!=sx || bild.getHeight(this)!=sy){
            if(sx!=0 && sy!=0){
                bild = createImage(sx, sy);
                Transformation.setScreenBreite(sx);
                Transformation.setScreenHoehe(sy);
                flag=1;
            }
        }
        if(flag==1){
            graphics = bild.getGraphics();
            // mit den 2 Anweisungen wird der Hintergrund ausgegeben
            // unbedingt nötig
            graphics.setColor(getBackground());
            graphics.fillRect(0,0,sx,sy);

            tangente.zeichneNormalparabel(graphics, Color.black);
            tangente.zeichneSekante(graphics, Color.green);
            //tangente.zeichneTangente(graphics, Color.cyan);
            tangente.zeichneTangente(graphics, Color.orange);
            tangente.zeichneAchsenkreuz(graphics, Color.black);
            /*
            Wenn dies jetzt erst gemacht wird, wird Sekante, usw
            nicht mehr angezeigt. Warum ?
            */
            // tangente.zeichneNormalparabel(graphics, Color.black);
      }
    }


    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //g.setColor(this.getBackground());
        //setBackground(Color.white);
        // Warum wird kein weißer Hintergrund gezeichnet ????
    	//g.drawImage(bild,0,0,Color.white,null);
    	g.drawImage(bild,0,0,null);

    }    

	public void mouseClicked(MouseEvent arg0) {
    }

	public void mousePressed(MouseEvent arg0) {
	}

	public void mouseEntered(MouseEvent arg0) {
	}

	public void mouseExited(MouseEvent arg0) {
	}

	public void mouseMoved(MouseEvent arg0) {
	}

    public void mouseDragged(MouseEvent ev) {
        boolean b=true;
        Point2DDouble p2D;
		Point javaklick = new Point();
        javaklick = ev.getPoint();
        // Der Mauszeiger befindet sich innerhalb des Laufpunkts
        if(anzahlMausImPunkt==0){
            b = tangente.istInnerhalb(javaklick, tangente.getLaufPunkt());
            if(b==true)
                anzahlMausImPunkt=1;
        }

        if(anzahlMausImPunkt==1){
            // Zeichne den Punkt an die Mauskoordinaten
            p2D = Transformation.transformScreenTo2DWelt(javaklick.x, javaklick.y);
            setParameterDeltaX(p2D.x-tangente.getFestPunkt().x);
            allesUpdaten();
            maleKomplettesFenster();
        }
	}


	public void mouseReleased(MouseEvent ev) {
        boolean b;
		Point javaklick = new Point();
        Point2DDouble p2D;

        javaklick = ev.getPoint();
        //System.out.println("javaklick.x="+javaklick.x+"javaklick.y"+javaklick.y);
        if(anzahlMausImPunkt==1){
            anzahlMausImPunkt=0;
        }
        //System.out.println("mouseReleased wurde aufgerufen");
	}


    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        setBackground(new java.awt.Color(255, 255, 255));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 523, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 312, Short.MAX_VALUE)
        );
    }// </editor-fold>


    // Variables declaration - do not modify
    // End of variables declaration

}

[/Java]


----------



## Marco13 (17. Feb 2010)

_1) Wenn ich BufferedImage benutzte (statt Image) sagt mir der Compiler, dass er createImage nicht kennt. Was kann ich machen, damit  er das kennt?
_

Bei BufferedImage macht man statt createImage(w,h) sowas wie

```
BufferedImage bufferedImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
```

_
2) Kann ich statt BufferedImage auch Image benutzen (so wie in meinem Programm), oder welche Nachteile hole ich mir mit Image statt BuffereImage ?
_

Neenaja... Image hat nicht direkt "Nachteile" - genaugenommen galt bis vor einiger Zeit auch die Empfehlung, "createImage" zu verwenden, weil damit schnellere Bilder erzeugt wurden, aber das ist obsolet. Ein ""Vorteil"" von BufferedImage ist, dass man bei getWidth/getHeight keinen ImageObserver übergeben muss, und ein paar mehr Möglichkeiten hat... die du aber wohl hier nicht brauchst...

_
3) 
Wenn ich die Parabel nur einmal zeichne, unten öfters mal das Fenster verkleiner und vergrößere und dabei den unteren Schieberegler verstelle, wird meine Parabel manchmal etwas verschoben.
An was liegt das?
Wie kann ich es ändern (ohne dass ich die Parabel jedesmal neu zeichne) ?
_
Naja... wenn man das Fenster größer zieht, dann MUSS die Parabel neu gezeichnet werden, weil der Teil, der durch die Vergrößerung dazu kommt, ja noch nicht (im Bild) existiert. Abgesehen davon hatte ich ja gesagt, dass das Bild (zwar nicht bei jedem Zeichnen, aber doch) bei jeder Größenänderung neu erstellt werden muss - wenn man denn nicht versucht, komplett auf das Image zu verzichten...

_
Ist deiner Meinung nach der Hintergrund wirklich weiss?
_

Meinungen sind Murks. Hab' einen Screenshot gemacht, und er zeigt mir für den Hintergrund als Farbe 255,255,255 an - das ist so weiß, wie es eben geht 

BTW: Wenn du die Zeile
graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreenAlt, yScreenAlt);
änderst in
graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreen, yScreen);
ist die Parabel auch wieder eine schön durchgezogene Linie...


----------



## ernst (17. Feb 2010)

Marco13 hat gesagt.:


> 3)
> Wenn ich die Parabel nur einmal zeichne, unten öfters mal das Fenster verkleiner und vergrößere und dabei den unteren Schieberegler verstelle, wird meine Parabel manchmal etwas verschoben.
> An was liegt das?
> Wie kann ich es ändern (ohne dass ich die Parabel jedesmal neu zeichne) ?
> ...


Ok, ich frage also immer vorher ab, ob das Fensters vergrößert oder verkleinert wurde.
Dies mache ich mit 
System.out.println("bild.getWidth(this)="+bild.getWidth(this)+" sx="+sx);
System.out.println("bild.getHeight(this)="+bild.getHeight(this)+" sy="+sy);
Allerdings sind die Werte immer gleich (Ausdruck auf Bildschirm):
run:
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=664 sy=664
Hallo wie oft bin ich hier?
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=664 sy=664
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=682 sy=682
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=703 sy=703

Wo ist mein Denkfehler ?

mfg
Ernst

Hier ein Programausschnitt:

[Java]
public void maleZeichnungJPanelOffscreen(){
...
System.out.println("bild.getWidth(this)="+bild.getWidth(this)+" sx="+sx);
System.out.println("bild.getHeight(this)="+bild.getHeight(this)+" sy="+sy);

if(bild.getWidth(this)!=sx || bild.getHeight(this)!=sy)
  // Neuzeichnen der Parabel
  tangente.zeichneNormalparabel(graphics, Color.black, 1);
else
  // Parabel muss nicht neu gezeichnet werden
  tangente.zeichneNormalparabel(graphics, Color.black, 0);
...
}

[/Java]


----------



## Marco13 (17. Feb 2010)

Hm. Der y-Wert ändert sich doch?! 

Aber ... ich habe jetzt das letzte, was du gepostet hattest, nochmal angesehen: Dass die Parabel nicht (oder verschoben) gezeichnet wurde, hängt wohl irgendwie mit dem "flag" zusammen... Ich hatte das mal so geändert....

```
public void zeichneNormalparabel(Graphics g, Color farbe)
    {
        int sx, sy;
        Graphics graphicsNormalparabel = null;
        // Bereich der x-Werte D = [a, b]
        double a, b;
        int breiteInPixel;
        int xScreenAlt, yScreenAlt, xScreen, yScreen;
        double xwAlt, ywAlt, xw, yw;
        int i;
        a = Transformation.wMinX;
        b = Transformation.wMaxX;
        // Anzahl der Pixel berechnen zwischen A(-4,5|0) und B(4,5|0)
        breiteInPixel = Transformation.transform2DWeltToScreenX(b) - Transformation.transform2DWeltToScreenX(a);
        // System.out.println("Anzahl der Pixel="+breiteInPixel);
        // System.out.println("Transformation.getScreenBreite()="+Transformation.getScreenBreite()+"Transformation.getScreenHoehe()="+Transformation.getScreenHoehe());

        g.setColor(farbe);
        sx = zeichnungJPanel.getSize().width;
        sy = zeichnungJPanel.getSize().height;
        // System.out.println("sx="+sx+"=sy="+sy);

        // if(flag==0)
        {
            while (sx == 0 && sy == 0)
            {}
            flag = 1;

            if (bildNormalparabel == null || bildNormalparabel.getWidth(zeichnungJPanel) != sx || bildNormalparabel.getHeight(zeichnungJPanel) != sy)
            {
                System.out.println("Zeichne Parabel neu!");
                bildNormalparabel = zeichnungJPanel.createImage(sx, sy);

                // Erzeuge den zu dem Grafikobjekt bild zugehörigen
                // Grafikkontext,
                // d.h. eine Leinwand, in die gemalt wird.
                graphicsNormalparabel = bildNormalparabel.getGraphics();
                // mit den 2 Anweisungen wird der Hintergrund ausgegeben
                // unbedingt nötig
                // graphics.setColor(getBackground());
                graphicsNormalparabel.setColor(zeichnungJPanel.getBackground());
                graphicsNormalparabel.fillRect(0, 0, sx, sy);

                graphicsNormalparabel.setColor(farbe);

                // System.out.println("schrittbreite"+schrittbreite);
                xScreenAlt = Transformation.transform2DWeltToScreenX(a);
                yScreenAlt = Transformation.transform2DWeltToScreenY(a * a);
                xScreen = xScreenAlt;
                yScreen = yScreenAlt;
                for (i = 1; i < breiteInPixel; i++)
                {
                    xScreen = xScreen + 1;
                    xw = Transformation.transformScreenTo2DWeltX(xScreen);
                    yw = xw * xw;
                    // System.out.println("xw="+xw+" yw="+yw);
                    yScreen = Transformation.transform2DWeltToScreenY(yw);
                    // System.out.println("xScreen+i="+(xScreen+i)+"
                    // yScreen="+yScreen);
                    // graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt,
                    // xScreen, yScreen);
                    graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreen, yScreen);
                    xScreenAlt = xScreen;
                    yScreenAlt = yScreen;
                }
            }
            else
            {
                System.out.println("Verwende alte Parabel");
            }
        }
        g.drawImage(bildNormalparabel, 0, 0, null);
    }
```

Und jetzt sagt er NUR bei Größenänderungen (EIN mal) dass er die Parabel neu zeichnet, und ansonsten die alte verwendet. Pass' auf dass du nicht versuchst, Fehler zu beheben, deren Ursache du nicht kennst - dadurch kann Code schnell chaotisch werden.

Das mit dem Zeichnen der Parabel hatte ich auch nochmal angesehen: Das

```
a = Transformation.wMinX;
        b = Transformation.wMaxX;
        // Anzahl der Pixel berechnen zwischen A(-4,5|0) und B(4,5|0)
        breiteInPixel = Transformation.transform2DWeltToScreenX(b) - Transformation.transform2DWeltToScreenX(a);
```
ist ein bißchen von Hinten durch die Brust ins Auge  Schau dir mal an, was bei den beiden transform-Aufrufen und der Breite dann am Ende so rauskommt


----------



## ernst (17. Feb 2010)

Marco13 hat gesagt.:


> Hm. Der y-Wert ändert sich doch?!



1)
Ich glaube, dass ich irgendwas mit dem getWidth bzw. getHeigh nicht verstanden habe (Bem: Ich benutze Image).
Ich habe in deinem Quellcode gefunden:
bildNormalparabel.getWidth(zeichnungJPanel) != sx 
sx = zeichnungJPanel.getSize().width;
Das kann ich nachvollziehen:
Du vergleichst die Breite der Zeichenfläche (die der User durch Ziehen abändern kann) mit der Breite, des Bildes das von der Zeichenfläche gemacht wurde. Und diese Bildbreite hat konstant den Wert, den sie beim Anlegen abgekriegt hat.

Bei mir ist es:
bild.getWidth(this)!=sx
sx = this.getSize().width;

Eigentlich will ich prüfen:
bild.getWidth(bild)!=sx
sx = this.getSize().width;
Aber das läßt der Compiler nicht zu: Er will einen Observer (was immer das auch sei).
Ich will aber die (konstante) Bildbreite, die beim Erzeugen des Bildes fest angelegt wurde (unveränderbar).

Siehe 2)

2)
Du hast recht. Es ändert sich etwas, z.B. eine Ausgabe für den Quellcode unten:
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=664 sy=664
NICHT Neuzeichnen der Parabel
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=526 sy=526  <----
NICHT Neuzeichnen der Parabel
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=526 sy=526
NICHT Neuzeichnen der Parabel
bild.getWidth(this)=541 sx=541
bild.getHeight(this)=526 sy=526

Deshalb (weil sich etwas ändert) verstehe ich nicht, warum die Parabel nicht neu gezeichnet wird. Es kommt immer die Ausgabe:
"NICHT Neuzeichnen der Parabel"
Vermutlich weil
bild.getWidth(this) eben nicht bild.getWidth(bild) als Ergebnis liefert.

Wo ist mein Denkfehler?

[Java]
    public void maleZeichnungJPanelOffscreen(){
        int sx, sy;
        Graphics graphics=null;

        sx = this.getSize().width;
        sy = this.getSize().height;

        if(bild==null || bild.getWidth(this)!=sx || bild.getHeight(this)!=sy){
            if(sx!=0 && sy!=0){
                bild = createImage(sx, sy);
                Transformation.setScreenBreite(sx);
                Transformation.setScreenHoehe(sy);
                flag=1;
            }
        }
        if(flag==1){
            graphics = bild.getGraphics();
            graphics.setColor(getBackground());
            graphics.fillRect(0,0,sx,sy);

            System.out.println("bild.getWidth(this)="+bild.getWidth(this)+" sx="+sx);
            System.out.println("bild.getHeight(this)="+bild.getHeight(this)+" sy="+sy);

            if(bild.getWidth(this)!=sx || bild.getHeight(this)!=sy){
                System.out.println("NEU-zeichnen der Parabel");
                tangente.zeichneNormalparabel(graphics, Color.black, 1);
            }
            else{

                System.out.println("NICHT Neuzeichnen der Parabel");
                tangente.zeichneNormalparabel(graphics, Color.black, 0);
            }
...
}
[/Java]


mfg
Ernst


----------



## Marco13 (18. Feb 2010)

_Bei mir ist es:
bild.getWidth(this)!=sx
sx = this.getSize().width;

Eigentlich will ich prüfen:
bild.getWidth(bild)!=sx
sx = this.getSize().width;
Aber das läßt der Compiler nicht zu: Er will einen Observer (was immer das auch sei).
_

Da ist er wieder, der ImageObserver, den man beim BufferedImage nicht bräuchte  
Man kann bei "getWidth" _irgendeine_ Component übergeben. 
bild.getWidth(zeichnungJPanel);
liefert (auch wenn das vielleicht verwirrend aussieht) die Breite des BILDES, und nicht die Breite des JPanels (theoretisch könnte man auch bild.getWidth(null); machen, aber das könnte manchmal nicht funktionieren).


_
Deshalb (weil sich etwas ändert) verstehe ich nicht, warum die Parabel nicht neu gezeichnet wird. Es kommt immer die Ausgabe:
"NICHT Neuzeichnen der Parabel"
Vermutlich weil
bild.getWidth(this) eben nicht bild.getWidth(bild) als Ergebnis liefert.
_

Ich glaube, es besteht allgemein ein bißchen Verwirrung wegen der beiden Offscreen-Bilder, und der Frage, wer die wann wo anlegt und wie man die Größe bestimmt, und insbesondere, wann was neu gezeichnet werden muss. Vielleicht habe ich auch deine Absicht falsch verstanden. Ich denke, du willst die Parabel nur EINmal in ein Bild zeichnen. (Und nur neu in ein neues Bild zeichnen, wenn sich die größe Ändert). Und ansonsten soll immer das fertige Parabelbild in das "Gesamtbild" gemalt werden?!


EDIT: Es kommt immer die "NICHT"-Ausgabe, weil ein paar Zeilen weiter oben schon sichergestellt wurde, dass das Bild dir größe sx/sy hat! Vollzieh' das nochmal in Ruhe nach, und schreib' dir vielleicht mal im Pseudocode mit klar benannten Variablen (und ggf. erstmal leeren "dummy-Funktionen") auf, was dort ablaufen muss....


----------



## ernst (18. Feb 2010)

Marco13 hat gesagt.:


> EDIT: Es kommt immer die "NICHT"-Ausgabe, weil ein paar Zeilen weiter oben schon sichergestellt wurde, dass das Bild dir größe sx/sy hat! Vollzieh' das nochmal in Ruhe nach, und schreib' dir vielleicht mal im Pseudocode mit klar benannten Variablen (und ggf. erstmal leeren "dummy-Funktionen") auf, was dort ablaufen muss....


1)
Danke für deine Geduld. Ich bin irgendwie ganz durcheinander gekommen und habe deshalb nochmals überlegt:
Den Flag brauche ich nicht: ich kann alles damit erledigen, daß ich die Bildgröße mit der Größe der Zeichenfläche vergleiche!
Jetzt klappt es!
Unten nochmals die 2 Methdeon.

2)
In dem Konstruktor 
public ZeichnungJFrame() {
kommt die Anweisung
jSlider1.setMinimum(slidermin);
vor.
Es istkaum zu glauben, aber laut Debugger ruft setMinimum() die Methode jSlider1.changeEvent() auf.
In dieser wird aber die Methode
maleZeichnungJPanelOffscreen()
aufegrufen, die u.a.
sx = this.getSize().width;
macht. Da dies aber alles noch vor setVisible(true) passiert, ist dort sx gleich 0.
Deswegen muß ich immer noch abfragen:
if(sx!=0 && sy!=0)
  ...
Ist das okay, bzw. was meinst du dazu? 

3) Noch eine Verständnisfrage (siehe unten public void maleZeichnungJPanelOffscreen())
Wenn ich die Normalparabel erst ganz am Schluss dieser Anweisungen mache, wird Sekante, Tangente, usw
nicht mehr angezeigt. Warum ?

//tangente.zeichneNormalparabel(graphics, Color.black);
tangente.zeichneSekante(graphics, Color.green);
tangente.zeichneTangente(graphics, Color.orange);
tangente.zeichneAchsenkreuz(graphics, Color.black);
tangente.zeichneNormalparabel(graphics, Color.black);

mfg
Ernst  


[Java]
    public void zeichneNormalparabel(Graphics g, Color farbe){
        int sx, sy;
        Graphics graphicsNormalparabel = null;
        double wMinX;
        int breiteInPixel;
        int xScreenAlt, yScreenAlt, xScreen, yScreen;
        double xwAlt, ywAlt, xw, yw;
        int i;

        breiteInPixel = Transformation.getScreenBreite();
        g.setColor(farbe);
        sx = zeichnungJPanel.getSize().width;
        sy = zeichnungJPanel.getSize().height;

        if(bildNormalparabel==null || bildNormalparabel.getWidth(null)!=sx || bildNormalparabel.getHeight(null)!=sy){
            if(sx!=0 && sy!=0){
                bildNormalparabel = zeichnungJPanel.createImage(sx, sy);
            }
        }

        if(sx!=0 && sy!=0){
            // Erzeuge den zu dem Grafikobjekt bild zugehörigen Grafikkontext,
            // d.h. eine Leinwand, in die gemalt wird.
            graphicsNormalparabel = bildNormalparabel.getGraphics();
            // mit den 2 Anweisungen wird der Hintergrund ausgegeben
            // unbedingt nötig
            graphicsNormalparabel.setColor(zeichnungJPanel.getBackground());
            graphicsNormalparabel.fillRect(0,0,sx,sy);
            graphicsNormalparabel.setColor(farbe);
            wMinX = Transformation.wMinX;
            xScreenAlt = Transformation.transform2DWeltToScreenX(wMinX);
            yScreenAlt = Transformation.transform2DWeltToScreenY(wMinX*wMinX);
            xScreen = xScreenAlt;
            yScreen = yScreenAlt;

            for(i=1;i<breiteInPixel;i++){
                xScreen = xScreen + 1;
                xw = Transformation.transformScreenTo2DWeltX(xScreen);
                yw = xw*xw;
                yScreen = Transformation.transform2DWeltToScreenY(yw);
                graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreen, yScreen);
                // Kurve als einzelne Punkte darstellen
                graphicsNormalparabel.drawLine(xScreenAlt, yScreenAlt, xScreenAlt, yScreenAlt);
                xScreenAlt = xScreen;
                yScreenAlt = yScreen;
            }
        }
        g.drawImage(bildNormalparabel,0,0,null);
    }

[/Java]
[Java]
    public void maleZeichnungJPanelOffscreen(){
        int sx, sy;
        Graphics graphics=null;

        sx = this.getSize().width;
        sy = this.getSize().height;

        if(bild==null || bild.getWidth(this)!=sx || bild.getHeight(this)!=sy){
            if(sx!=0 && sy!=0){
                bild = createImage(sx, sy);
                Transformation.setScreenBreite(sx);
                Transformation.setScreenHoehe(sy);
            }
        }


        if(sx!=0 && sy!=0){
            graphics = bild.getGraphics();
            // mit den 2 Anweisungen wird der Hintergrund ausgegeben
            // unbedingt nötig
            graphics.setColor(getBackground());
            graphics.fillRect(0,0,sx,sy);

            tangente.zeichneNormalparabel(graphics, Color.black);
            tangente.zeichneSekante(graphics, Color.green);
            tangente.zeichneTangente(graphics, Color.orange);
            tangente.zeichneAchsenkreuz(graphics, Color.black);
            /*
            Wenn dies jetzt erst gemacht wird, wird Sekante, usw
            nicht mehr angezeigt. Warum ?
            */
            // tangente.zeichneNormalparabel(graphics, Color.black);
        }

    }
[/Java]


----------



## Marco13 (18. Feb 2010)

Ein paar der Fragen hatte ich schon als Kommentare im Code gesehen 

_
In dem Konstruktor 
public ZeichnungJFrame() {
kommt die Anweisung
jSlider1.setMinimum(slidermin);
vor.
Es istkaum zu glauben, aber laut Debugger ruft setMinimum() die Methode jSlider1.changeEvent() auf.
_

(Das ist auch gut so ... das muss so sein  )

_
In dieser wird aber die Methode
maleZeichnungJPanelOffscreen()
aufegrufen, die u.a.
sx = this.getSize().width;
macht. Da dies aber alles noch vor setVisible(true) passiert, ist dort sx gleich 0.
Deswegen muß ich immer noch abfragen:
if(sx!=0 && sy!=0)
  ...
Ist das okay, bzw. was meinst du dazu? 
_

Joa, man könnte sich da jetzt eine Reihe möglicher Lösungen überlegen... aber im Endeffekt wird's immer auf so eine ähnliche Abfrage rauslaufen... 

EDIT: Eine einfache (und spontan würde ich sagen: Die beste) Abhilfe könnte sein, den ChangeListener erst an den Slider zu hängen, NACHDEM man das anfängliche setMinimum aufgerufen hat...)


_
3) Noch eine Verständnisfrage (siehe unten public void maleZeichnungJPanelOffscreen())
Wenn ich die Normalparabel erst ganz am Schluss dieser Anweisungen mache, wird Sekante, Tangente, usw
nicht mehr angezeigt. Warum ?
_

Weil die Normalparabel (bei dir) nicht eine Linie ist, die in das Graphics gemalt wird, sondern ein Bild - ein Bild, das hauptsächlich aus weißen Hintergrund besteht, und das Graphics voll ausfüllt (und alles übermalt, was vorher gemalt wurde). Solche Dinge meinte ich, als ich weiter oben was gebrabbelt habe von
"_Wenn man eine Mischung hat, d.h. ein Teil, der aufwändig zu zeichnen ist, und der in einem Offscreen-Bild liegen soll, und einen anderen Teil, der einfach zu zeichnen ist, und NICHT in einem Offscreen-Bild liegen soll, *kann es etwas kniffliger werden, das vernünftig zu "verwalten"... *In diesem Fall wäre das aber IMHO eigentlich auch nicht nötig...:_"

(NOCH kniffliger würde es eben werden, wenn man mehrerer solcer Buffer hätte, und keinen malen könnte, ohne potentiell einen anderen zu überdecken - dann könnte man zwar mit teilweise transparenten Bildern was machen, aber dadurch würde es dann wieder deutlich langsamer usw...)


----------



## ernst (18. Feb 2010)

Marco13 hat gesagt.:


> Es istkaum zu glauben, aber laut Debugger ruft setMinimum() die Methode jSlider1.changeEvent() auf.
> [/i]
> 
> (Das ist auch gut so ... das muss so sein  )


Warum?
Woher weiss man das?
(Ich bin bin erst mit Hilfe des Debuggers darauf gekommen)



Marco13 hat gesagt.:


> EDIT: Eine einfache (und spontan würde ich sagen: Die beste) Abhilfe könnte sein, den ChangeListener erst an den Slider zu hängen, NACHDEM man das anfängliche setMinimum aufgerufen hat...)


Das hat bei mir der Visual-Editor gemacht.
Wenn ich den weiter benutze, kann ich diese Lösung nicht verwenden.

mfg
Ernst


----------



## Marco13 (18. Feb 2010)

ernst hat gesagt.:


> Warum?
> Woher weiss man das?
> (Ich bin bin erst mit Hilfe des Debuggers darauf gekommen)



"Wissen" ist so eine Sache ... Man müßte es (wenn z.B. eine NullPointerException fliegt) am StackTrace sehen - und es steht auch in JSlider (Java Platform SE 6) ...

_
Das hat bei mir der Visual-Editor gemacht.
Wenn ich den weiter benutze, kann ich diese Lösung nicht verwenden.
_

Hmja, man stößt mit sowas eben manchmal en Grenzen. Die sind vielleicht praktisch, wenn man mal schnell ein "Mock-Up" oder irgendeinen Standard-Dialog zusammenklicken will, aber wenn's dann an solche Sachen geht, muss man aufpassen, dass die Einfachheit um Zeitersparnis, die man sich durch solche Editoren erhofft oder verspricht, nicht ins Gegenteil umschlägt...


----------



## ernst (18. Feb 2010)

Marco13 hat gesagt.:


> "Wissen" ist so eine Sache ... Man müßte es (wenn z.B. eine NullPointerException fliegt) am StackTrace sehen - und es steht auch in JSlider (Java Platform SE 6) ...


Du meinst damit:
If the new minimum value is different from the previous minimum value, all change listeners are notified. 
D.h. die Listener werden aufgerufen  



Marco13 hat gesagt.:


> Hmja, man stößt mit sowas eben manchmal en Grenzen. Die sind vielleicht praktisch, wenn man mal schnell ein "Mock-Up" oder irgendeinen Standard-Dialog zusammenklicken will, aber wenn's dann an solche Sachen geht, muss man aufpassen, dass die Einfachheit um Zeitersparnis, die man sich durch solche Editoren erhofft oder verspricht, nicht ins Gegenteil umschlägt...



Wenn man mit dem VE mal Probleme bekommt und sich nicht genau auskennt, dann hat man ein Problem...

mfg
Ernst


----------



## ernst (19. Feb 2010)

Marco13 hat gesagt.:


> "Wissen"
> Hmja, man stößt mit sowas eben manchmal en Grenzen. Die sind vielleicht praktisch, wenn man mal schnell ein "Mock-Up" oder irgendeinen Standard-Dialog zusammenklicken will, aber wenn's dann an solche Sachen geht, muss man aufpassen, dass die Einfachheit um Zeitersparnis, die man sich durch solche Editoren erhofft oder verspricht, nicht ins Gegenteil umschlägt...


Vielen Dank für deine Geduld und deinen wertvollen Tipps.
Für mich ist das Thema damit erst mal abgeschlossen.

mfg
Ernst


----------

