# JMenuBar sowie Buttons nach repaint auf JPanel



## Bootenks (15. Apr 2006)

Schönen guten Tag an euch alle!

Ich habe ein Problem mit meiner kleinen Ampelanimation.

Erklärung:

Ich habe 3 Threads die jeweils eine Ampel simulieren sollen. Jede Ampel ist ein JPanel und wird mit dieser Klasse instanziert:


```
package Control;

import java.awt.*;
import javax.swing.*;

public class Ampel extends JPanel implements Runnable
{
    private Color[] ampelcolors = { Color.red, Color.yellow, Color.green };
    private Color aus = new Color(64, 64, 64);
    private Color[] ampelbelegung = { aus, aus, aus };
    private Thread th;
    private int ampelid;
    private int startcolor;
    
    public Ampel(int startcolor, int id)
    {
        this.setBounds(0, 0, 450, 400);

        this.ampelid = id;
        this.startcolor = startcolor;
        ampelbelegung[startcolor] = ampelcolors[startcolor];
        
        th = new Thread(this);
        th.start();
    }

    public void run()
    {
        while ( true )
        {
            for ( int i = 0; i<3; ++i)
            {
                setColor(i);
                repaint();
                
                try
                {
                    th.sleep(1000);
                } catch ( InterruptedException e ) {}
            }
        }
    }
    
    public void setColor(int newcolor)
    {
        if ( newcolor == 0 )
        {
            ampelbelegung[0] = ampelcolors[0];
            ampelbelegung[1] = aus;
            ampelbelegung[2] = aus;
        }
        else if ( newcolor == 1 )
        {
            ampelbelegung[0] = aus;
            ampelbelegung[1] = ampelcolors[1];
            ampelbelegung[2] = aus;
        }
        else if ( newcolor == 2 )
        {
            ampelbelegung[0] = aus;
            ampelbelegung[1] = aus;
            ampelbelegung[2] = ampelcolors[2];
        }
    }
    
    public Color getColorSetting(int position)
    {
        return ampelbelegung[position];
    }

    public void paintComponent(Graphics g)
    {
        if ( this.ampelid == 0 )
        {
            g.setColor(new Color(100, 100, 100));
            g.fillRect(155, 85, 40, 20);
            g.setColor(this.getColorSetting(0));
            g.fillOval(182, 90, 10, 10);
            g.setColor(this.getColorSetting(1));
            g.fillOval(170, 90, 10, 10);
            g.setColor(this.getColorSetting(2));
            g.fillOval(158, 90, 10, 10);
        }
        else if ( this.ampelid == 1 )
        {
            g.setColor(new Color(100, 100, 100));
            g.fillRect(255, 85, 20, 40);
            g.setColor(this.getColorSetting(0));
            g.fillOval(260, 88, 10, 10);
            g.setColor(this.getColorSetting(1));
            g.fillOval(260, 100, 10, 10);
            g.setColor(this.getColorSetting(2));
            g.fillOval(260, 112, 10, 10);
        }
        else if ( this.ampelid == 2 )
        {
            g.setColor(new Color(100, 100, 100));
            g.fillRect(255, 5, 40, 20);
            g.setColor(this.getColorSetting(0));
            g.fillOval(258, 10, 10, 10);
            g.setColor(this.getColorSetting(1));
            g.fillOval(270, 10, 10, 10);
            g.setColor(this.getColorSetting(2));
            g.fillOval(282, 10, 10, 10);
        }
    }
}
```

Ich möchte darauf hinweisen, dass der Code keinesfalls fertig ist da die eigentlich Logik fehlt!

Diese Ampeln werden auf ein anderes JPanel gelegt welches die Kreuzung zeichnet:


```
package View;

import java.awt.*;
import javax.swing.*;
import Control.Ampel;

class Kreuzung extends JPanel
{
    private Ampel autoampel1;
    private Ampel autoampel2;
    private Ampel autoampel3;
    private Image dbImage;
    private Graphics dbGraphics;
    
    public Kreuzung()
    {
        super();
        this.setBackground(Color.black);
        
        // Ampel Initialisierung
        autoampel1 = new Ampel(0, 0);
        autoampel2 = new Ampel(2, 1);
        autoampel3 = new Ampel(0, 2);
       
        setLayout(null);
        add(autoampel1);
        add(autoampel2);
        add(autoampel3);
    }
    
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if (dbImage == null)
        {
            dbImage = createImage((int) this.getSize().getWidth(), (int) this.getSize().getHeight());
            dbGraphics = dbImage.getGraphics();

            dbGraphics.setColor(getBackground());
            dbGraphics.fillRect(0,0,(int) this.getSize().getWidth(), (int) this.getSize().getWidth());
            dbGraphics.setColor(Color.gray);
            dbGraphics.fillRect(0, 30, 450, 50);
            dbGraphics.fillRect(200, 80, 50, 200);

            dbGraphics.setColor(Color.white);
            for ( int i = 0; i < 200; i += 20 )
            {
                    dbGraphics.drawLine(i, 55, i+10, 55);
            }

            for ( int i = 260; i < 440; i += 20 )
            {
                    dbGraphics.drawLine(i, 55, i+10, 55);
            }

            for ( int i = 85; i < 285; i += 20 )
            {
                    dbGraphics.drawLine(225, i, 225, i+10);
            }

            dbGraphics.drawLine(200, 55, 200, 80);
            dbGraphics.drawLine(250, 30, 250, 55);
            dbGraphics.drawLine(225, 80, 250, 80);
        }
        g.drawImage(dbImage, 0, 0, this);
    }
}
```

Die Kreuzung wiederum liegt auf einem JFrame, der die eigentlichen Controlelemente (Menü und Button's) beinhaltet.


```
package View;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import Control.Ampel;

public class Hauptfenster extends JFrame implements ActionListener
{
    // Variablen
    private JPanel aktionsbereich;
    private JLabel erklaerung;
    private Kreuzung kreuzung;
    private JButton startbutton;
    private Ueber_uns about = null;

    public Hauptfenster()
    {
        // Frame Einstellungen
        this.setcentralLocationSize(450, 450);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setTitle("Hauptfenster");
       
        initComponents();
    }
    
    private void initComponents()
    {
        JMenuBar menuleiste = new JMenuBar();
        this.setJMenuBar(menuleiste);

        Container cp = this.getContentPane();
        cp.setLayout(new BorderLayout());
        cp.setBackground(Color.black);
        
        aktionsbereich = new JPanel();
        aktionsbereich.setLayout(new BorderLayout());
        aktionsbereich.setBackground(Color.black);
        
        // Kreuzungsanimation wird hinzugefügt
        kreuzung = new Kreuzung();
        
        // Sensoren initialisieren
        JButton autosensor1 = new JButton("Kfz Sensor links");
        JButton autosensor2 = new JButton("Kfz Sensor unten");
        JButton autosensor3 = new JButton("Kfz Sensor rechts");

        JButton fussgaengersensor1 = new JButton("Fg Sensor links");
        JButton fussgaengersensor2 = new JButton("Fg Sensor unten");
        JButton fussgaengersensor3 = new JButton("Fg Sensor rechts");
        
        JPanel sensorenfeld = new JPanel();
        sensorenfeld.setLayout(new GridLayout(2, 3, 2, 2));
        sensorenfeld.setBackground(Color.black);
        
        sensorenfeld.add(autosensor1);
        sensorenfeld.add(autosensor2);
        sensorenfeld.add(autosensor3);
        sensorenfeld.add(fussgaengersensor1);
        sensorenfeld.add(fussgaengersensor2);
        sensorenfeld.add(fussgaengersensor3);
        
        // obere Elemente werden dem Aktionsbereich hinzugefügt
        aktionsbereich.add(kreuzung, BorderLayout.CENTER);
        aktionsbereich.add(sensorenfeld, BorderLayout.SOUTH);
        
        // kurze Erklärung wird definiert
        erklaerung = new JLabel();
        erklaerung.setText("Diese Software dient zur Ampelsimulation an einer T-Kreuzung!");
        erklaerung.setHorizontalAlignment(JLabel.CENTER);
        erklaerung.setForeground(Color.white);
        
        // Alle Elemente werden dem Hauptfenster hinzugefügt
        cp.add(aktionsbereich, BorderLayout.CENTER);
        cp.add(erklaerung, BorderLayout.SOUTH);
    }
    
    public void actionPerformed(ActionEvent e)
    {
        if ( e.getActionCommand().equals("BEENDEN") )
        {
            System.exit(0);
        }
        else if ( e.getActionCommand().equals("UEBERUNS") )
        {
            if ( about == null )
            {
                about = new Ueber_uns();
            }
            about.setVisible(true);
        }
    }
            
    public void setJMenuBar(JMenuBar jmenubar)
    {
        JMenu programm =  new JMenu("Programm");
        
        JMenuItem ueber_uns = new JMenuItem("Über uns");
        ueber_uns.setAccelerator(KeyStroke.getKeyStroke('U', InputEvent.CTRL_MASK));
        ueber_uns.setMnemonic('u');
        ueber_uns.setActionCommand("UEBERUNS");
        ueber_uns.addActionListener(this);
        
        JMenuItem beenden = new JMenuItem("Beenden");
        beenden.setAccelerator(KeyStroke.getKeyStroke('B', InputEvent.CTRL_MASK));
        beenden.setMnemonic('B');
        beenden.setActionCommand("BEENDEN");
        beenden.addActionListener(this);
        
        programm.add(ueber_uns);
        programm.addSeparator();
        programm.add(beenden);
        
        jmenubar.add(programm);
        super.setJMenuBar(jmenubar);
    }
    
    public void setcentralLocationSize(int width, int height)
    {
	int hoehe = (int) getToolkit().getScreenSize().getHeight();
	int breite = (int) getToolkit().getScreenSize().getWidth();
	hoehe = (int) ( hoehe - height ) / 2;
	breite = (int) ( breite - width ) / 2;
	setLocation(breite, hoehe);
	setSize(width, height);
    }
}
```

Das wärs auch schon.

Nun bekomme ich halt immer nach dem repaint der Ampelthreads im Kreuzungs-JPanel die JMenuBar mit angezeigt. (Sie ist aber korrekterweise auch im JFrame vorhanden!). Zudem sehe ich, wenn ich über einen JButton mit der Maus fahre oben links auch diesen Button in dem Kreuzungs-JPanel. Durch die falsche Menuleiste verschiebt sich die Kreuzung und die Ampellämpchen leuchten an der falschen Stelle.

Noch eine Merkwürdigkeit geschieht wenn ich ein Fenster über das Ampelfenster legen und dann ein bissel hin und herschiebe, dann verschmiert das Bild dermaßen das man kaum noch was erkennt... Das repaint versucht scheinbar noch das korrekte Bild anzuzeigen, schafft es aber nicht... Allerdings wenn ich es Minimiere und dann wieder Maximieren dann sieht alles so aus wie vor dem repaint()! Bis dann wieder das repaint() der Threads aktiv wird und das gleiche Spiel von vorne beginnt...

Woran kann das liegen? Ich hoffe ich habe es euch deutlich genug geschildert.

Vielen Dank jetzt schon einmal für eure Unterstützung.


----------



## Beni (15. Apr 2006)

Entweder solltest du auf deinen Panels den _gesammten_ Hintergrund zeichnen, oder du rufst im Konstruktor "setOpaque( false )" auf, um die Optimierungen abzuschalten.


----------



## Bootenks (15. Apr 2006)

Ja es funkioniert!! Dankeschön! ^^ Habe es in den Ampelkonstruktor gepackt und alles läuft tadelos ^^ Wegen so einer Kleinigkeit!!

Nochmal großes Dankeschön an dich BENI! ^^


----------

