# Java Tetris-Umsetztungs Problem



## Developer_X (23. Feb 2009)

Ja hallo, wie ihr wisst hat mir "hdi" den Auftrag gegeben, eine Tetris Spiel zu erstellen, ich habe mich mal daran versucht, aber irgendwie bewegt sich nichts, kann  mir einer irgendwie weiterhelfen?
Wenn ich eine Taste drücke, bewegt sich nichts, wenn die Zeit nach 1 Sekunde geschehen ist, passiert immer noch nichts, wieso?

```
public class Tetrix extends Frame implements KeyListener
{	
	private int SteinX=0;
	private int SteinY=0;
		
	public Tetrix()
	{
		super("Tetrix-Developer_X's Art!");
		setSize(500,800); setLocation(500,0); 
		setVisible(true); setResizable(false);
		
		addKeyListener(this);

	}
	public void keyPressed(KeyEvent e)
	{
		if (e.getKeyCode()==KeyEvent.VK_UP){SteinY = SteinY +1;};
		if (e.getKeyCode()==KeyEvent.VK_LEFT){SteinX = SteinX -1;};
		if (e.getKeyCode()==KeyEvent.VK_RIGHT){SteinX = SteinX +1;};
		if (e.getKeyCode()==KeyEvent.VK_DOWN){SteinY = SteinY -1;};
	}
	public void keyReleased(KeyEvent e) {}
	public void keyTyped(KeyEvent e) {}
		
	public void paint(Graphics g)
	{
		g.setColor(Color.blue);
		g.drawRect(SteinX, SteinY, 100, 100);
		
		
		SteinY=100;
		
		warte(1000);
		
		SteinY=200;
		
	}
	public void update(Graphics g) {}

	public static void warte(long millis){try{Thread.sleep(millis);}catch(InterruptedException e){}}

	public static void main(String[]args){Tetrix x = new Tetrix();}
}
```


----------



## SlaterB (23. Feb 2009)

solange die paint-Methode wartet, ist auf dem Bildschirm nix neues zu sehen,
generell funktioniert das etwas anders, z.B.


```
class Tetrix
    extends Frame
    implements KeyListener
{
    private int SteinX = 0;
    private int SteinY = 0;

    public Tetrix()
    {
        super("Tetrix-Developer_X's Art!");
        setSize(300, 300);
        setLocation(200, 0);
        setVisible(true);
        setResizable(false);

        addKeyListener(this);

    }

    public void keyPressed(KeyEvent e)
    {
        if (e.getKeyCode() == KeyEvent.VK_UP)
        {
            SteinY = SteinY - 4;
        }
        if (e.getKeyCode() == KeyEvent.VK_LEFT)
        {
            SteinX = SteinX - 4;
        }
        if (e.getKeyCode() == KeyEvent.VK_RIGHT)
        {
            SteinX = SteinX + 4;
        }
        if (e.getKeyCode() == KeyEvent.VK_DOWN)
        {
            SteinY = SteinY + 4;
        }
    }

    public void keyReleased(KeyEvent e)
    {
    }

    public void keyTyped(KeyEvent e)
    {
    }

    public void paint(Graphics g)
    {
        g.setColor(Color.blue);
        g.drawRect(30 + SteinX, 30 + SteinY, 10, 10);
    }

    public static void warte(long millis)
    {
        try
        {
            Thread.sleep(millis);
        }
        catch (InterruptedException e)
        {
        }
    }

    public static void main(String[] args)
    {
        final Tetrix x = new Tetrix();
        new Thread()
            {
                public void run()
                {
                    while (true)
                    {
                        x.repaint();
                        warte(30);
                    }
                }
            }.start();
    }
}
```


----------



## Mostly_Harmless (23. Feb 2009)

hdi hat gesagt.:


> Ich wette mit dir er wird
> enormste Probleme haben, ein Tetris zu programmieren. Ohne Sound ohne Effekte einfach nur so n superbilliges Tetris. Da kommen hier 25 Threads weil er nix checkt.



Ich würd sagen, Wette gewonnen.


----------



## hdi (23. Feb 2009)

Lol.. @Developer: Das is nice das du dich hast besinnen lassen.
Da kommt noch einiges auf dich zu  Aber danach kannst du die Basics.


----------



## Spacerat (24. Feb 2009)

@Developer_X: Auch von mir, herzlichen Glückwunsch zum Sinneswandel. Wie du siehst unterscheidet sich dein Code von SlaterB's eigentlich nur noch in der Übersicht...

Übersicht macht aber nun noch keine gut durchdachte Anwendung aus. Eigentlich gibts bei vernünftigen Fragestellungen auch nichts zu Meckern. Geposteten Code einfach mal ein wenig Korregieren ist wohl die Macht der Gewohnheit von erfahrenen Forenbenutzern. Aber genau da fängts wieder an... So lernt er's nie. Bis auf die Tatsache das er an seinem Stil noch arbeiten muss, scheint er die trivialen Dinge ja mehr oder weniger verstanden zu haben. Was noch fehlt ist ein Konzept, denn wenn man einfach so drauf los programmiert, verhaspelt man sich selbst dann recht schnell, wenn der Code noch einigermassen durchschaubar ist. Worauf ich hinaus will, ist, das hier ein Spiel entwickelt werden soll. Also eine Anwendung mit einem permanenten "Loop", in welchem die Anzeige aktualisiert, die Eingabegeräte abgefragt und der Spielstand aktualisiert werden muss. Deswegen kommt man um Multi-Threading wohl nicht herum. Kleinigkeiten, wie ein "Thread.sleep(wielongauchimmer)" in der "paint"-Methode sollten also von Anfang an vermieden werden. Gut, ich habe bisher noch nie sowas triviales wie Tertris selbst programmiert (macht man sowas, wenn man Informatik studiert?). Ich habe, wie "gestern" noch Developer_X, mit "Java3D" angefangen und das auch nur hobbymässig (ist vllt. gut gegangen, weil ich schon zu C64-Zeiten Assembler programmierte... anders konnte man mit der Kiste ja nichts anfangen). Trotzdem würde ich von vorne herein im groben folgenden Weg vorschlagen:
1. Sich gedanken darüber machen, was zu welchem Zeitpunkt im Spiel geschehen muss (z.B. Bildschirmneuaufbau, Tastatur-Abfrage etc).
2. Dem Gedankengang folgend, einen "Thread-Pool" aufbauen, in welchem jedes der Ereignisse die zu verschiedenen Zeiten passieren sollen, einen eigenen Thread bekommt (dafür muss nicht unbedingt "java.concurrent.*" verwendet werden).
3. Kapselung der einzelnen Spielkomponenten (z.B. in Prozess- und Anzeige-Komponenten). Dabei kann man, wenn man will, sich auch darüber gedanken machen, wie man z.B. die "paint"-, KeyListener- und vor allem die "run"-Methode "versteckt", das sie nich von jedem unsinnig aufgerufen werden können. Am wichtigsten dabei ist jedoch der Aufbau der Klassen- und Paketstruktur.
4. Entwicklung der Spiel-Logik.
5. Entwicklung des Designs.
Entschliesst man sich bei 3. dafür, die genannten Methoden zu "verstecken", lernt man ganz beiläufig auch, was anonyme Klassen sind.
Naja... wenn jemand meint, anders geht's besser, einfacher... ist ja nur ein Vorschlag und jeder machts anders...
Hauptsache ist doch, das man sich an meine neue Signatur erinnert...


----------



## Quaxli (24. Feb 2009)

Spacerat hat gesagt.:


> ....Geposteten Code einfach mal ein wenig Korregieren ist wohl die Macht der Gewohnheit von erfahrenen Forenbenutzern. Aber genau da fängts wieder an... So lernt er's nie....



Das würde ich so nicht sagen. Letzten Endes kann man gerade beim Programmieren durch Abgucken eine Menge lernen. Und wenn man mit der Nase auf die richtige Herangehensweise gestoßen wird, kann das sehr hilfreich sein.
Ich lese sehr gerne fremden Code um zu sehen, wie etwas gelöst wurde. Die guten Dinge merkt man sich um sie ggf. mal selbst anzuwenden bzw. um bei ähnlichen Problemen einen guten Lösungsansatz zu finde und die schlechten Dinge verwirft man (und stellt vielleicht fest, daß man manches vor einigen Jahren auch so gelöst hätte).

Insofern kann ich an der Korrektur von geposteten Code nichts verwerfliches finden. Dieses Forum wäre sehr schlecht besucht, wenn nicht immer wieder jemand geposteten Code hier verbessern würde.


----------



## Spacerat (24. Feb 2009)

@Quaxli: So war's ja auch nicht gemeint. Was ich damit sagen wollte, ist eigentlich nur, das der Code den Developer_X hier gepostet hat eben (...und das wohl gewohnheitsmässig) nur korregiert wurde ohne Ihm zu sagen, das ein solcher Ansatz möglicherweise gar nicht der Richtige ist. Obwohl... Ich kanns ja nicht beurteilen. Ich kenne nur meine Konzeptionen und habe eigentlich nie richtig gelernt wie man solche Konzepte erstellt, weil ich eben nicht studiert habe. Mit der Zeit habe ich mir eben einige Ansätze selbst konzipiert, von denen ich heute sagen kann, das sie auch recht brauchbar sind. Bis dahin habe ich mich Aufgrund "richtig" falscher Ansätze auch oft genug verhaspelt. Aber deswegen müssen meine (so auch mein obiger) keineswegs die richtigen sein. Der Post in einem anderen Thread, wo diesbezüglich von mir der Vorschlag kam, JOGL statt Java3D zu verwenden, war aus meiner Sicht deswegen auch nicht soo falsch, denn ich habe so Java gelernt (OpenGL war dabei eine hübsche Zugabe).


----------



## Developer_X (24. Feb 2009)

So, ich hab jetzt mal noch die Methode  "Rotate" eingefügt, aber dabei dreht sich der Kasten viel mehr, als nur um 90 Grad, bei einem Tastendruck, außerdem wird er unsichtbar, und taucht nach meherem Tasten drücken woanders wieder auf, und er flackert, was mache ich schon wieder falsch?

```
class Tetrix
extends Frame
implements KeyListener
{
private int SteinX = 0;
private int SteinY = 0;

private int rot = 0;

public Tetrix()
{
    super("Tetrix-Developer_X's Art!");
    setSize(300, 300);
    setLocation(200, 0);
    setVisible(true);
    setResizable(false);

    addKeyListener(this);

}

public void keyPressed(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_UP)
    {
        rot = rot +90;
    }
    if (e.getKeyCode() == KeyEvent.VK_LEFT)
    {
        SteinX = SteinX - 4;
    }
    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
    {
        SteinX = SteinX + 4;
    }
    if (e.getKeyCode() == KeyEvent.VK_DOWN)
    {
    	rot = rot -90;
    }
}

public void keyReleased(KeyEvent e)
{
}

public void keyTyped(KeyEvent e)
{
}

public void paint(Graphics g2)
{
	Graphics2D g = (Graphics2D) g2;

    g.setColor(Color.blue);
    g.rotate(rot);
    g.fillRect(30 + SteinX, 30 + SteinY, 20, 20);
}
public static void warte(long millis)
{try{ Thread.sleep(millis);} catch (InterruptedException e) {}}

public static void main(String[] args)
{
    final Tetrix x = new Tetrix();
    new Thread()
        {
    	public void run() {while (true){x.repaint(); warte(30); }}}.start();
    	}
}
```

PS:
Hört mal, ich habe deinen Text, hdi, nicht einfach wild kopiert, ich habe ihn mir auch angeguckt, 
du verwendest also einen "Thread" um das bild oder "Tetrix" zu "repainten".
Selbst darauf zu kommen. wäre für mich unmöglich gewesen, aber da mir HDI geholfen hat, danke noch mal, habe ich wieder was dazu gelernt, wenn man Spiele, erstellt, mit Graphics g, oder Graphics2D g, dann brauch man, um die BIlder zu aktualisieren diesen Thread in der MAin Methode


----------



## SlaterB (24. Feb 2009)

rot sollte wahrscheinlich nicht in Grad 90 gemessen werden, sondern in Bogenmaß, PI/2 usw

das Rotieren ist dann eine komplizierte Sache, bei den drei anderen Stufen als 0 wird derzeit wahrscheinlich links oder oberhalb des Bildes gemalt, weil um den Ursprung 0,0 gedreht wird,
da könnte ich diesmal gar keine Verbesserung angeben, da ich die selber nicht so genau kenne,
mach dich zum Zeichnen in Java2D schlau, Transformation usw.

--------

was bringt es eigentlich, ein quadratisches Element um 90 Grad zu drehen?


----------



## Developer_X (24. Feb 2009)

später ist es ja nicht mehr quadratisch, nur so, bei tetrix dreht man Objekte, damit will ich mich schon jetzt vertraut machen, da es ja einer der Hauptsachen ist

also kann mir da einer mit dem Flackern weiterhelfen?
wenn ich ein gedrehtes objekt bewege flackert es


----------



## Developer_X (24. Feb 2009)

Ich habs Geändert, so, aber irgendwie klappt das auch niciht, gar nicht mehr:

```
class Tetrix
extends Frame
implements KeyListener
{
private int SteinX = 0;
private int SteinY = 0;

private int rot = 0;

public Tetrix()
{
    super("Tetrix-Developer_X's Art!");
    setSize(300, 300);
    setLocation(200, 0);
    setVisible(true);
    setResizable(false);

    addKeyListener(this);
    
}

public void keyPressed(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_UP)
    {
        rot = rot +90;
    }
    if (e.getKeyCode() == KeyEvent.VK_LEFT)
    {
        SteinX = SteinX - 20;
    }
    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
    {
        SteinX = SteinX + 20;
    }
    if (e.getKeyCode() == KeyEvent.VK_DOWN)
    {
    	rot = rot -90;
    }
}

public void keyReleased(KeyEvent e)
{
}

public void keyTyped(KeyEvent e)
{
}

public void paint1(Graphics g2)
{
	Graphics2D g = (Graphics2D) g2;  

    g.setColor(Color.blue);
    g.rotate(SteinX,SteinY,Math.toRadians(rot));
    g.fillRect(30 + SteinX, 30 + SteinY, 20, 20);    

}


public static void warte(long millis)
{try{ Thread.sleep(millis);} catch (InterruptedException e) {}}

public static void main(String[] args)
{
    final Tetrix x = new Tetrix();
    new Thread()
        {
    	public void run() {while (true){x.repaint(); warte(30); }}}.start();
    	}
}
```
Aber jetzt sieht man nichts mehr, ich weiß nicht was ich tun soll,


----------



## Spacerat (24. Feb 2009)

Klar doch: DoubleBuffering heisst der Zauber.

```
package gamepanels;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

public abstract class GamePanel
extends Component
{
  private BufferedImage dblBuffer;

  public final void paint(Graphics g)
  {
    if( dblBuffer == null
    || dblBuffer.getWidth() != getWidth()
    || dblBuffer.getHeight() != getHeight())
    {
      dblBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TRANSLUCENT);
    }
    paintComponent(dblBuffer.getGraphics());
    g.drawImage(dblBuffer, 0, 0, getWidth(), getHeight(), this);
  }

  public final void update(Graphics g)
  {
    paint(g); // die Zeile ward vergessen...
  }

  public final boolean isDoubleBuffered()
  {
    return true;
  }

  protected abstract void paintComponent(Graphics g);
}
```
Und um mal zu bekräftigen, was ich ober mit Methoden verstecken meinte, Hier mal die Gamepanel-Klasse meiner Engine.
@Edit: Wer macht denn da 'nen Doppelpost? Dieser hier bezog sich aufs flackern. BTW.: wenn du diesen "Panel" extendest, wirst du gezwungen sein, "paintComponent()" zu überschreiben. Solange es "protected" bleibt, wird kein Mensch jemals drauf kommen die Methode dort aufzurufen, wo es keinen Sinn macht.


----------



## Quaxli (24. Feb 2009)

Das Flackern entsteht durch die fehlende Doppelbufferung. Hier gibt es 2 Möglichkeiten:
1. DoppelBufferung einbauen -> einfach mal googeln oder hier im Forum suchen 
2. doppelt gepufferte Komponenten verwenden, z. B. ein JPanel als Zeichenfläche, anstelle eines Frames

<edit>
Spacerat war schneller.... 
</edit>


----------



## Ebenius (25. Feb 2009)

Ich hab das Thema grad nur überflogen, hab aber nicht gesehen, dass jemand das schon erwähnt hat...

Bitte gewöhn Dir gleich an (je eher desto besser) die Nomenklaturregeln sauber zu befolgen. Also *nicht*:
	
	
	
	





```
private int SteinX=0;
```
 Sondern: 
	
	
	
	





```
private int steinX=0;
```

Ebenius


----------



## hdi (25. Feb 2009)

Neulich wurde mir hier gesagt dass Swing Double Buffering automatisch hat.
Also bei Applications (bei Applets nicht). Was stimmt nun?

@Developer:
Neben dem einhalten an Nameskonventionen kannst du dir im Zusammenhang mit GUI auch 
gleich mal abgewöhnen, mit setSize() und setLocation() zu arbeiten.

Komponenten bekommen immer nur eine


```
setPreferredSize(Dimension)
```

und statt setLocation() nutzt man Layout-Manager. Bei JFrames nutzt man meist
ein setLocationRelativeTo(null), das wäre dann zentriert auf dem Desktop.

In deinem Fall hast du grob ein JFrame und 2 JPanels:

[HIGHLIGHT="Java"]
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.add(spielrasterPanel, BorderLayout.CENTER);  // spielraster.setPreferredSize(...)
f.add(punkteAnzeigePanel, BorderLayout.EAST);  // punkteAnzeigePanel.setPreferredSize()
f.pack()
f.setLocationRelativeTo(null);
f.setVisible(true);
[/HIGHLIGHT]


----------



## Developer_X (25. Feb 2009)

danke das hat mir geholfen, aber das mit dem rotieren hab ich immer noch nicht so richtig verstanden
ich verstehs net


----------



## Ebenius (25. Feb 2009)

hdi hat gesagt.:


> Neulich wurde mir hier gesagt dass Swing Double Buffering automatisch hat.
> Also bei Applications (bei Applets nicht). Was stimmt nun?


Lies nochmal Quaxli's Beitrag. AWT hat kein Double Buffering. Swing hat Double Buffering. Entsprechend wählt man also eine der beiden Möglichkeiten aus.

Ebenius


----------



## Fu3L (25. Feb 2009)

Developer_X hat gesagt.:


> danke das hat mir geholfen, aber das mit dem rotieren hab ich immer noch nicht so richtig verstanden
> ich verstehs net



Mit Rotation meinst du doch wahrscheinlich, dass du den herunterfallenden Stein drehen kannst? Beim tetris gibts ja nicht sooo viele Steine, vllt erstellst du am besten mehrere Grafiken für eine Steinform und zeigst dann die entsprechend gedrehte Form an?

Wenn du jezz irgendwas rundes hast, dass du um ein paar Grad pro GameLoop-Durchlauf drehen wolltest, wäre das schon schwieriger (da fiele mir jezz spontan nur ein, für das Zeichnen des Körpers den Koordinatenursprung in die Mitte dieses Körpers zu setzen und dann Graphics2D.rotate() einzusetzen...).



> Neulich wurde mir hier gesagt dass Swing Double Buffering automatisch hat.
> Also bei Applications (bei Applets nicht). Was stimmt nun?



Bei Applets wohl (denke ich). Wenn du von Swing redest, solltest du schließlich auch auf JApplet wechseln...


----------



## hdi (25. Feb 2009)

> vllt erstellst du am besten mehrere Grafiken für eine Steinform und zeigst dann die entsprechend gedrehte Form an?


Man kann das ja nicht rein mit einer Grafik lösen, vllt optisch aber nicht in der Logik, 
wegen der Kollisionsabfrage.

Also diese ganze "Rotations" Sache ist eig. nich so wild.
Da es in Tetris nur 6 Steine, und höchsten 4 versch. Ausrichtungen pro Stein gibt,
kann man das einfach so festlegen.

abstract void rotate()

und die einzelnen Steinchen (Block, Stange, ...) implementieren das halt so, dass sie die Position ihrer
Elemente ändern, mittels switch(rotationState) oder sowas.

Beim Block fällt das eh weg, und bei allen anderen Figuren muss man eh nie alle
verschiedenen Elemente bewegen, nur manche.

Ein Stein muss ja aus einzelnen Elementen bestehen, allein schon für eine leichte
Kollisionsabfrage.


----------



## Fu3L (25. Feb 2009)

hdi hat gesagt.:


> Ein Stein muss ja aus einzelnen Elementen bestehen, allein schon für eine leichte
> Kollisionsabfrage.



Stimmt, das ist natürlich sinnvoll, dass ein Stein aus den einzelnen kleinen Blöcken besteht und die beim Aufruf von rotate() einfach ihre Position ändern... 
Ich war jezz von einem Stein als kleinste Einheit ausgegangen (im Nachhinein gesehen etwas umständlich  )


----------



## hdi (25. Feb 2009)

Genau, um es deutlicher zu sagen: Nicht die einzelnen Steinchen bewegen ihre Position,
das können sie gar nicht berechnen. Sondern ein grosser Spielstein bewegt in seiner
rotate-Methode seine Kind-Steinchen.

Es gibt beim Tetris eig. nur 1 grosse Design-Frage (bzw. das ist eine der Design-Fragen):
Teile ich das Spielfeld in ein 2d-array von Zellen auf, und speichere in einer Zelle so einen kleinen Stein, 
oder hab ich einfach ne Liste von diesen kleinen Steinen, die jeweil ne x und y Position speichern?

Letzteres ist für die Kollisionsabfrage ein Kinderspiel, aber nicht besonders effizient.

Ersteres ist viel effizienter, aber es verkompliziert (leicht) das Bewegen/Drehen der Steine bzw. die Kollisionsabfrage. 
Weil man halt über die Zellen-Objekte gehen muss, zB 

[HIGHLIGHT="Java"]cell[2][7].setStein( cell[2][6].getStein() );
cell[2][6].setStein (null);[/HIGHLIGHT]

Etwas umständlich, aber wie gesagt die Kollisionsabfrage wird dadurch viel effizienter, 
weil man nicht die komplette Liste von Steinen durchgehen muss, wo 95% sowieso
nicht für eine Kollision in Frage kommen würden.
Mit den Zellen schaut man sich beim drop zB nur genau dei eine Zelle mit y = (stein.y) + 1 und x = stein.x an.


----------



## Developer_X (25. Feb 2009)

ok,
...
...


----------



## Ebenius (25. Feb 2009)

hdi hat gesagt.:


> Teile ich das Spielfeld in ein 2d-array von Zellen auf, und speichere in einer Zelle so einen kleinen Stein, oder hab ich einfach ne Liste von diesen kleinen Steinen, die jeweil ne x und y Position speichern?


Zum zweiten Vorschlag: Du kannst eigentlich das Spielfeld nicht als Liste von Vier-Segment-Steinen betrachten, da diese Steine ja zerhackt werden können, wenn eine Reihe verschwindet, weil sie voll ist. Oder meinst Du das anders?

Ebenius


----------



## hdi (25. Feb 2009)

mit "diesen kleinen Steinen" meine ich einen elementaren Stein, keinen kompletten Spielstein.

Während ein Tetris-Stein (jetzt: ein kompletter, zB ein block) noch im Spiel ist, im Sinne
von noch nicht abgelegt, steuert man den kompletten Vater-Stein: rotate, move, etc.

Sobald er kollidiert zerschiesst man ihn in seine Einzelteile (stein.getSteinchen()),
und speichert diese in der Liste.

So hab ich's früher zumindest gemacht. Aber wie gesagt, ne Liste ist eig. nich so geil,
ein 2d-array is sicher eleganter.


----------



## Spacerat (25. Feb 2009)

Um mal das mit dem DoubleBuffer zu klären: Lt. Konvention soll eine Komponente die doppelt gepuffert ist die Methode "isDoubleBuffered()" der Klasse "Component" überschreiben und "true" zurückgeben lassen. "java.awt.Applet" tut dies nicht und überschreibt auch die "paint()"-Methode nicht. Deswegen ist java.awt.Applet" auch nicht doublebuffered. Wenn mann sich "isDoubleBuffered()" der Klasse "JComponent" anschaut, kann man wohl daraus folgern, das bei Swing DoubleBuffering auch abschaltbar ist (irgendwie?).
@Edit: Ich werde meine Klasse oben auch mal dahingehend ändern, damit die Konvention wieder passt.


----------



## hdi (25. Feb 2009)

> Returns whether this component should use a buffer to paint.



Ich glaube das kann man nur leicht missverstehen: Es geht nicht darum, zu setzen,
ob das double buffered sein soll.
Es ist übliche Englisch-Sprech-Weise, das mit "should" zu beschreiben.
Ich denke es ist eher "shall" gemeint, was noch mehr andeutet, dass es halt so *ist*. 
Auf deutsch: Es gibt dafür keinen Setter 

... diese API's sind oft auch als Beschreibung für die Leute von Sun selbst zu verstehen,
da hat Kerl X dem Kerl Y gesagt "implementiere JComponent", und damit er weiss
was welcher Wert ist, gibt es für ihn eine Beschreibung zu double buffered.
Seine Antwort ist aber trotzdem "ja", soll so sein.

edit: Allerdings

[HIGHLIGHT="Java"]new JComponent(){
		@Override
		public boolean isDoubleBuffered(){
			return false;
		}
};[/HIGHLIGHT]


----------



## Spacerat (25. Feb 2009)

So... Ich hab' bei mir mal geändert, wie es sein sollte.
@hdi: "should", "shall"... Für uns (jene die diese API nutzen) müsste es "returns if this Component uses a buffer" heissen. Deine Implementation der JComponent schaltet allerdings irgendetwas ab.
	
	
	
	





```
... class JComponent
{
...

    /**
     * Returns whether this component should use a buffer to paint.
     *
     * @return true if this component is double buffered, otherwise false
     */
    public boolean isDoubleBuffered() {
        return getFlag(IS_DOUBLE_BUFFERED);
    }
...
}
```
Was immer das auch bedeutet (Möglicherweise geht ja "setFlags(IS_DOUBLE_BUFFERED)". Hab's nicht so mit Swing). Aber wenn mans überschreibt geht was verloren.


----------



## hdi (25. Feb 2009)

Naja wundert ja nich gross dass da was kaputt geht.
Kein setter in der API -> Nicht vorgesehen, dass man dort was ändert.
Also wenn du eine nicht-buffered nicht-AWT Komponente willst,
dann musste die dir wohl selber zusammenbauen.

PS:


> Für uns (jene die diese API nutzen) müsste es "returns if this Component uses a buffer" heissen.


Genau das wollte ich halt sagen: So, wie die es geschrieben haben, sagt man es oft in der englischen
Sprache. Es heisst aber genau das gleiche, was du geschrieben hast.
(Deine Version heisst wörtlich genommen übrigens eh wieder was ganz anderes)


----------



## Ebenius (25. Feb 2009)

Spacerat hat gesagt.:


> [...]kann man wohl daraus folgern, das bei Swing DoubleBuffering auch abschaltbar ist (irgendwie?).


*Räusper* JComponent.setDoubleBuffered(boolean).



hdi hat gesagt.:


> Ich glaube das kann man nur leicht missverstehen: [...]


... und ich glaube, Dir ist es genauso ergangen.  JComponent bringt DoubleBuffering mit, es ist ein- und ausschaltbar und die API-Doc ist recht aussagekräftig. 

Nachtrag: JComponent macht das DoubleBuffering also völlig selbständig, nach gewissen Kriterien. Siehe dazu JComponent.paint() [HIGHLIGHT="Java"]// ...

if (!printing
      && repaintManager.isDoubleBufferingEnabled()
      && !getFlag(ANCESTOR_USING_BUFFER)
      && isDoubleBuffered()) {
  repaintManager.beginPaint();
  try {
    repaintManager.paint(this, this, co, clipX, clipY, clipW, clipH);
  } finally {
    repaintManager.endPaint();
  }
} else {
  // Will ocassionaly happen in 1.2, especially when printing.
  if (clipRect == null) {
    co.setClip(clipX, clipY, clipW, clipH);
  }

  if (!rectangleIsObscured(clipX, clipY, clipW, clipH)) {
    if (!printing) {
      paintComponent(co);
      paintBorder(co);
    } else {
      printComponent(co);
      printBorder(co);
    }
  }
  if (!printing) {
    paintChildren(co);
  } else {
    printChildren(co);
  }
}

// ...[/HIGHLIGHT]
Das erklärt sicher auch ganz gut, warum man bei Swing-Komponenten in aller Regel nicht die paint()-Methode überschreibt.

So long,
Ebenius


----------



## hdi (25. Feb 2009)

Oh, ich hab nich nochmal überprüft ob es nen Setter gibt. Bin nach Spacerat's Aussage
einfach davon ausgegangen, dass es keinen gibt


----------



## Spacerat (26. Feb 2009)

@Ebenius: Hab' die rausgeschriebene Stelle per "Eclipse->Komfortsuche" gefunden (mit Codevervollstänigung "new JComponent().isDoubleBuffered()" in Quelltext geschieben und "Deklaration öffnen" gewählt...). Im Prinzip hätte ja ein Blick in die Gliederung der Klasse genügt um den Setter auch noch zu finden. Bin ich aber im Eifer nicht drauf gekommen.


----------

