Warum nicht repaint() immer aufrufen paintComponent und warum es nicht immer richtig verhält, wenn es aufgerufen wird
Arbeite ich an einem Tetris-Klon in Java, und alles scheint ordnungsgemäß zu funktionieren, bis ich möchte eine ganze Zeile gelöscht werden und alles, was oben gelöscht werden. Obwohl alle meine Daten korrekt steht für die transformation, meine paintComponent Methode scheint nur klar, die Reihe, aber lassen Sie alles, wie oben dargestellt, als es war vor der repaint () - Aufruf. Das neue Stück wird der Herbst durch das phantom-Blöcke und land auf unsichtbare Blöcke in der untersten Reihe, wo die oben genannten Stücke gefallen wären.
Hier mein paint component Methode:
public void paintComponent(Graphics page)
{
super.paintComponent(page);
Graphics2D page2D = (Graphics2D) page;
for (int c = 0; c < 10; c++)
{
for (int r = 0; r < 18; r++)
{
if (well[c][r] != null) //Well is a 2D array of Block objects that have Rectangle object, coordinates and color
{
page2D.setColor(well[c][r].getColor());
page2D.fill(well[c][r].getSquare());
page2D.setColor(Color.gray);
page2D.draw(well[c][r].getSquare());
}
}
}
for (int i = 0; i < 4; i++) //tetro = the player's tetris piece
{
page2D.setColor(tetro.getColor());
page2D.fill(tetro.getBlock(i).getSquare());
page2D.setColor(Color.GRAY);
page2D.draw(tetro.getBlock(i).getSquare());
}
}
Dies ist der Teil meiner actionPerformed-Methode in meinem Timer-listener, der erkennt/löscht Blöcke auf und ruft die repaint-Methode.
int count = 0; //Number of occupied cells in well
int clears = 0; //number of rows to be clear
int lowestClear = -1; //Lowest row that was cleared, -1 if none
for (int row = 0; row < 18; row++)
{
for (int col = 0; col < 10; col++)
{
if (well[col][row] != null)
{
count++;
}
}
if (count == 10)
{
clears++;
if (lowestClear < 0)
{
lowestClear = row;
}
for (int col = 0; col < 10; col++)
{
well[col][row] = null;
}
}
count = 0;
}
if (clears > 0)
{
repaint(); //Doesn't call paintComponent()
for (int i = 1; i <= clears; i++)
{
for (int r = 16; r >= 0; r--)
{
if (r > lowestClear)
{
break;
}
for (int c = 0; c < 10; c++)
{
if (well[c][r] != null)
{
well[c][r+1] = well[c][r];
well[c][r] = null;
}
}
}
}
repaint(); //Does not call paintComponent()
}
tetro.fall();
repaint(); //DOES call paint component
Durch die Zeit der ersten repaint () - Methode aufgerufen wird, auch array richtig zeigt, dass die vollständige Reihe ist nun komplett null. Ich möchte das repaint () - Methode aktualisieren Sie die Systemsteuerung, um zu zeigen, diese leere Zeile, sondern paintComponent() scheint nicht genannt zu werden. Dies ist auch der Fall mit der zweiten repaint () - Methode, wo ich es möchte zu aktualisieren, den Rahmen zu zeigen, die Blöcke in Ihren neuen Positionen nach dem löschen einer Zeile und löschen Sie Sie nach unten. Wieder, paintComponent() wird nicht aufgerufen.
Für das Letzte repaint () - Aufruf, aber wo ich gerade aktualisieren möchten, die position des fallenden Stück egal was für updates es möglicherweise oder möglicherweise nicht erforderlich, um vor, repaint () - Aufruf paintComponent(). Also: Frage Nummer eins ist, warum ist paintComponent() nur aufgerufen, an diesem Beispiel der repaint () - Aufruf.
Jedoch, wenn paintComponent() wird aufgerufen, und Sie erreicht das Ende der Methode, die ich befolgen es im debug-Modus, um zu sehen, in welcher Zeile hat das Gremium die änderungen widerzuspiegeln. Sobald es erreicht :"Repaintmanager.paintDirtyRegions(Map< Component -, Rechteck - >)" - Zeile ein:856, hat es gelöscht, die Zeile und zeigt das neue Stück fallen, aber unsichtbare Blöcke und phantom-Blöcke.
So, meine zweite Frage ist, warum ist paintComponent() Verhalten sich in dieser Weise. Offensichtlich muss ich tun, ein bisschen Lesen auf Repaintmanager und Java-Malerei im Allgemeinen, aber ich wäre sehr dankbar, wenn jemand erklären könnte, mir.
Hier ist die main-Methode, falls wichtig:
import javax.swing.JFrame;
public class TetrisDriver
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Tetris");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Matrix()); //Matrix = jPanel class
frame.pack();
frame.setVisible(true);
}
}
Ich entschuldige mich, wenn dies ist widerlich lang.
InformationsquelleAutor user1726134 | 2012-10-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zunächst, wenn Sie nicht bereits getan haben, würde ich ein Lesen durch Malen in AWT und Swing, die erklärt, dass die Malerei Regelung Swing (und AWT).
Zweitens, die du nicht kontrollierst, die repaints, der repaint-manager und dem OS zu tun, stellen Sie nur Vorschläge.
Drittens, konnte man einen Blick auf die JComponent.paintImmediately Methode ist es erforderlich zu wissen, den Bereich, den Sie aktualisieren möchten, aber vielleicht helfen
Aus der Java-Docs
Kann ich auch mehr Besonnenheit zu Rendern, das Spiel Stand auf einem off-screen Puffer und verwenden Sie diese in der
paintComponent
Methode. Platzieren Sie diese auf einem queue und knallen Sie ab, während die Farbe Prozess, zu erstellen, die mehr oder weniger auf Abruf (halten einen pool von ein paar und wächst, schrumpft der pool, wie Sie benötigen)...Wie würden Sie eine Schlange von GUIs, oder was werden Sie machen eine Warteschlange? Würde es sein wie ein
ArrayList
oder bin ich verlesen, was Sie schrieb?Das würde davon abhängen, was Sie versuchen zu tun
Denken Sie daran, die Malerei kann auftreten, zu jeder Zeit, aus irgendeinem Grund, viele Male ohne Ihr wissen oder kontrollieren. Es könnte sein, dass Sie der Kollision mit einem repaint Punkt zwischen Status-updates, aber es ist schwer zu sagen, ohne irgendeine Art von ausführbarer Beispiel, alles andere ist Rätselraten
InformationsquelleAutor MadProgrammer
repaint()
nicht nennenpaintComponent()
- und das ist auch richtig arbeiten scenerio fürrepaint()
Methode.Es markiert nur einen Staat, der Komponente aktualisiert werden sollten, und paintComponent() aufgerufen wird weiter von Swing selbst.
Viele
repaint()
fordert, kann die Ursache nur eine einzigepaintComponent()
nennen und dies gilt Verhalten.InformationsquelleAutor Piotr Müller
Anstatt
repaint()
Sie könnten versuchen, direkt aufrufenpaint()
selbst.Diese Weise wird die Farbe sofort, Wann immer Sie eine änderung vornehmen möchten. Ordnen Sie diese zu einer anderen Funktion und rufen Sie es stattdessen, wenn Sie möchten, sehen Ihre änderungen sofort.
warum ist es nicht eine gute Idee zu nennen paint()? Ich habe gehört, aber nicht voll verstehen.
Swing verwendet eine passive rendering-Algorithmus, das bedeutet, dass Bild könnte auftreten, jederzeit und aus irgendeinem Grund, meist ohne Ihr wissen oder intervention. Versuch zu malen, so wie Sie Sie vorgeschlagen haben, könnte dazu führen, dass
NullPointerException
oder zu anderen malen Artefakte, wie Sie kämpfen, die Farbe sub-system. Sollten Sie arbeiten innerhalb der API nicht gegen Sie.getGraphics
ist NIE eine gute IdeeInformationsquelleAutor Spino Prime