# Zeichnen in Swing



## biker126 (4. Jun 2006)

hallöchen

hab n problem und zwar weiss ich nicht genau, wie ich in Swing in nem JFrame was zeichnen kann und gleichzeitig Komponenten anzeigen kann.

hab hier schon bisl rumgesucht und gesehn, dass ich in der paintComponent (vom JFrame nehm ich mal an) zeichnen müsste (ich will images mit g.drawImage() zeichnen). das klappt aber nicht so ganz, da meine JLabel's und JButton's dann nicht mehr richtig angezeigt werden...

wär nett wenn mir jmd sagen könnte wie man da vorgeht!

was vl auch noch relevant ist: ich hab nen Thread, in dessen run() methode ich alle 20ms (also immer ein Thread.sleep(20) die repaint() methode aufrufe (weil sich die images, bzw. deren positionen etc ändern).


----------



## 8ull23y3 (4. Jun 2006)

Hm ich weiß nicht genau was du da vor hast... Liegen die Bildchen hinter den Labels usw?

Wenn ja würde ich vielleicht für für die Componenten selbst ein JLayeredPane vorschlagen was du deinem Panel übergibst.


----------



## biker126 (4. Jun 2006)

jo das problem ist, dass ich quasi auf dem ganzen screen verstreut bilder zeichnen will und darüber dann buttons/labels etc.

das heisst das zeugs wird irgendwie immer wieder übermalt oder so... gibt auf jeden fall komische effekte...

mit AWT war das ganze kein problem, da konnt ich einfach die paint() methode (bzw. die update() für double-buffering) implementieren und die komponenten wurden trotzdem ganz normal angezeigt. aber in Swing klappt das offenbar nicht.

hat noch jmd ne idee?


----------



## Beni (4. Jun 2006)

In Swing sollte man die "paintComponent"-Methode überschreiben, IMHO reicht dies bereits. Vielleicht noch einige Componenten mit "setOpaque( false )" durchsichtig machen, damit die Bilder auch durchscheinen.


----------



## biker126 (4. Jun 2006)

offenbar drück ich mich ungenau aus... ich probiers nochmal:

ich hab mir jetzt eine neue klasse gemacht:

```
class PaintScreen extends JPanel
{
    protected void paintComponent( Graphics g )
    {
        super.paintComponent(g);
        setBackground(new Color(0,128,0));
        GM.spieler[0].drawDeck(g, Hearts.wnd);
        GM.spieler[1].drawDeck(g, Hearts.wnd);
        GM.spieler[2].drawDeck(g, Hearts.wnd);
        GM.spieler[3].drawDeck(g, Hearts.wnd);
        GM.drawCards(g, Hearts.wnd);
    }
}
```

als lokale klasse meines fensters. in *.drawDeck() werden mittels g.drawImage() Bilder irgendwo im fenster gezeichnet.

mein fenster konstruktor startet einen thread, und in dessen run() methode werden mit folgender funktion die komponenten hinzugefügt:


```
private void addGUIElements()
{
    screen = new PaintScreen();
    screen.setBounds(0,0,height, width);
    contentPane.add(screen);
    // labels für die player names
    player[0] = new JLabel(GM.spieler[0].getPlayerName(), JLabel.CENTER);  
    player[0].setFont(new Font("serif", Font.BOLD, 12));
    player[0].setBounds(100,height-60, 80, 20);
    contentPane.add(player[0]);
    ...
```

danach wird in der run() methode eine while(true)-loop gestartet die ein Thread.sleep(20); und ein repaint(); macht.

also in etwa so:

```
public void run()
{
    addGUIElements();
    while (true)
    {
        repaint();
        try
        {
            Thread.sleep(50);
        }
        catch (InterruptedException e){}
    }	
}
```

das problem ist jetzt, das die JLabels zb. (hat noch andere komponenten) nicht angezeigt werden. evtl. weil sie vom PaintScreen-Panel überdeckt werden?


----------



## André Uhres (5. Jun 2006)

biker126 hat gesagt.:
			
		

> ..das problem ist jetzt, das die JLabels zb. (hat noch andere komponenten) nicht angezeigt werden. evtl. weil sie vom PaintScreen-Panel überdeckt werden?


Dann setzt sie einfach direkt in das PaintScreen-Panel. 
Jedenfalls können sie dann nicht mehr von ihm überdeckt werden.
"paintComponent(..)" stört dabei überhaupt nicht


----------



## biker126 (5. Jun 2006)

dann muss ich einfach anstatt:


```
player[0] = new JLabel(GM.spieler[0].getPlayerName(), JLabel.CENTER);  
player[0].setFont(new Font("serif", Font.BOLD, 12)); 
player[0].setBounds(100,height-60, 80, 20); 
contentPane.add(player[0]);
```

das label dem panel hinzufügen? mit 
	
	
	
	





```
screen.add(player[0]);
```
 richtig?

noch ne kurze frage:

wenn ich in AWT was gezeichnet hab, dann war die ausrichtung ja immer zur ganz linken oberen ecke des frames. aber wenn ich jetzt in Swing was in der paintComponent() eines Panels zeichne, dann is die ausrichtung immer zur linken oberen ecke der CONTENTPANE, richtig? und die fängt ja erst nach dem frame-rahmen und dem menu an..?


----------



## André Uhres (5. Jun 2006)

biker126 hat gesagt.:
			
		

> dann muss ich einfach..das label dem panel hinzufügen? ..richtig?


Ja, genau. So einfach ist es.



			
				biker126 hat gesagt.:
			
		

> ..wenn ich jetzt in Swing was in der paintComponent() eines Panels zeichne,
> dann is die ausrichtung immer zur linken oberen ecke der CONTENTPANE, richtig?
> und die fängt ja erst nach dem frame-rahmen und dem menu an..?


Naja, in deinem Fall vielleicht, weil der Panel genau ins contentPane reinpasst.
Aber eigentlich stellen die Koordinaten (0,0) die obere linke Ecke des *JPanels *dar
(oder irgendeiner anderen JComponent die du mit paintComponent(..) malst).


----------



## biker126 (5. Jun 2006)

hab gleich das nächste problem:

wenn ich in meine while-loop mit dem repaint() komme (siehe oben), dann stimmt die position der Labels nicht mehr. muss ich die bei jedem neuzeichnen quasi neu setzen? ich weiss nicht genau wann ein repaint aufgerufen wird. aber zB. wenn ich auf nen Knopf drück, der mir den text eines labels ändert passiert das gleiche...

(alle Komponenten springen an die obere kante des Panels und sind dort zentriert hintereinander aufgereiht... oO)

EDIT:

ich hab grad gemerkt, dass ich die Komponten sogar innerhalb der paintComponent() vom Panel ausrichten kann, damit bleiben sie jetzt wo sie sind (weiss aber nicht, ob das die beste variante ist...). 

bin aber schon beim nächsten Problem:

dialogboxen, die ich über mein menu öffne werden nicht richtig (neu)gezeichnet... woran liegt das jetzt wieder???


----------



## biker126 (5. Jun 2006)

hat niemand eine idee warum meine Dialogboxen nicht richtig gezeichnet werden?

ich vermute mal, das es was mit dem JPanel zu tun hat.

weil als mein Frame noch ein Frame war (und kein JFrame, ich musste das auf wunsch umbauen... :/ ) ging das alles noch einwandfrei...

und auch jetzt werden Dialoge, die angezeigt werden bevor mein JPanel (das zum zeichnen) erstellt wird, ganz normal dargestellt...

der ablauf is momentan folgender:

- JFrame konstruktor startet einen Thread
- Thread startet run()
- run() ruft einen Dialog auf, dieser wird richtig gezeichnet
- nach beenden dieses dialogs wird mein JPanel inkl. aller Komponenten erstellt
- eine while-loop in der run() startet; mit Thread.sleep(20) und repaint()
- wird jetzt ein Dialog geöffnet wird dieser nicht vollständig gezeichnet (buttons zB. erst wenn man mit der Maus drüberfährt. labels sieht man gar nicht, borders auch nicht usw.)

wär echt froh wenn mir jmd ein paar tipps geben könnte, worauf man achten muss und was alles probleme gibt.

hab schon in mehreren online-büchern gesucht aber da steht das ganze immer nur sehr knapp (so a la: "man überschreibe die paintComponent() und gut ist"). aber offensichtlich mach ich noch irgendwas ziemlich falsch... :/


----------



## André Uhres (5. Jun 2006)

http://www.java-forum.org/de/viewtopic.php?p=192212#192212


----------



## biker126 (5. Jun 2006)

oke, hab mal probiert ein einigermassen anständiges KSKB zu machen (wie gewünscht möglichst alles unnötige rausgeschmissen).

das programm startet man mit der hearts.class. das "anschauungs-fehler-objekt" wäre der "anmeldung" dialog. anfangs sieht der wie schon gesagt normal aus, danach nicht mehr (wenn man ihn im menu-->neu aufruft). das menu alleine macht auch schon probleme, wenn mans auf und zu klappt hat man nachher so nen grauen rand in den ecken...

wär wirklich nett wenn sich jmd das angucken könnte... falls gewünscht könnt ich auch einfach den code hier posten, sind aber immer noch 500+ zeilen. wollt nich das ganze forum zuspammen 

KSKB


----------



## André Uhres (5. Jun 2006)

biker126 hat gesagt.:
			
		

> oke, hab mal probiert ein einigermassen anständiges KSKB zu machen..


Super!

Ich hoffe ich hab nichts vergessen, probier's mal so:

Dem screen --> null Layout verpassen damit die setBounds richtig greifen
paintComponent: die JComponents wieder rausnehmen
Menu-->Swing, JMenuBar, setJMenuBar(..)

```
//package kskb;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainMenu extends JMenuBar {
    private JMenu m;
    private JMenuItem mi;
    public static CheckboxMenuItem miMerker, miInGameStats;
        /* **************
         * Konstruktor	*
         ****************/
    public MainMenu(ActionListener listener) {
        // Menu "Spiel"
        m = new JMenu("Spiel");
        // "Datei Neu"
        mi = new JMenuItem("Neu");
        mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0));//InputEvent.CTRL_MASK
        mi.setActionCommand("Neu");
        mi.addActionListener(listener);
        m.add(mi);
        m.addSeparator();
        // "Beenden"
        mi = new JMenuItem("Beenden");
        mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, 0));//InputEvent.CTRL_MASK
        mi.setActionCommand("Beenden");
        mi.addActionListener(listener);
        m.add(mi);
        add(m);
    }
}
```
Achja das noch:

```
private void addGUIElements() {
        // Zeichen-Panel erstellen
..
        screen.setBackground(new Color(0,128,0));//<----gehört nicht ins paintComponent !
        screen.setLayout(null);//<--sonst greifen deine setBounds nicht richtig!
```


----------



## Gast (5. Jun 2006)

Hallo, ich hab ein kleines Problem:

Ich muss eine mathematiche Figur in ein Frame zeichnen.
Ich habe es geschafft,dass ich die Punkte bestimmte,
aber ich kann tun was ich will ich kann diese Punkte einfach nicht zu einer Figur durch Linien verbinden
!
Ich hab es mit der Funktion drawLine(x1, y1, x2, y2) probiert,
aber es wird einfach nichts gezeichnet!
Ich habe es auch mit anderen Klassen probiert, die richtig waren, und es kommt trotzdem nichts raus.

Ich bin noch Anfängerin, wenn ihr eine passende Lösung habt, dann hilft mir BITTE.

Ein Problem hätte ich noch und zwar wie muss ich vorgehen, 
wenn ich eine Figur in ein Frame habe, dass wenn ich das Fenster vergrößere das ganze Bild größer wird?

Bitte hilft mir, 
es geht um Leben oder Tot.

Danke für eure bemühungen

LG


----------



## André Uhres (5. Jun 2006)

http://www.galileocomputing.de/open...el_14_009.htm#Rxx365java14009040004C91F02A100


----------



## biker126 (5. Jun 2006)

danke schonmal, hab die änderungen vorgenommen 

aber das problem mit der Dialogbox besteht immer noch 

hast du das programm mal laufen lassen und die dialogbox mal mit menu->neu gestartet? die wird leider immer noch ned richtig gezeichnet :/


----------



## André Uhres (5. Jun 2006)

biker126 hat gesagt.:
			
		

> ..aber das problem mit der Dialogbox besteht immer noch..


Hast du auch in paintComponent() schön aufgeräumt?  :wink: 

```
protected void paintComponent( Graphics g ) {
            super.paintComponent(g);
            g.drawImage(Hearts.wnd.herz[2],50,50,null);
            g.setColor(new Color(232,232,232));
            g.fillRect(0,panelHeight-20,panelWidth,20);
        }
```


----------



## biker126 (5. Jun 2006)

haha, hau mich bitte ned aber:

ich hab die korrekturen bei meinem hauptprojekt gemacht aber natürlich das unkorrigierte KSKB getested (jaja ecplise und die projekte ).
das korrigierte projekt funktioniert soweit wunderbar! 

dank dir viel mals!!


----------

