/ / Java Game Development: Grafik - Java, Swing, Animation, Jframe, Jpanel

Java Spieleentwicklung: Grafik - Java, Swing, Animation, Jframe, Jpanel

Ich bin neu hier. Ich hoffe, Sie können mir helfen.

Problem: Problem beim Anzeigen von Animation in JFrame. Scheint, ich verstehe / verstehe nicht genug, wie Java's Grafik funktioniert.

Globale Idee: Sagen wir, ich möchte ein Spiel, einen Film oder einen Clip machen. Dafür brauche ich diese (nicht) einfache Animation.

Ein Beispiel für diese Frage: Ich habe Klasse Screen, die den Bildschirm stuff-Deklaration des JFrame, Festlegen seiner Konfiguration (Größe, Schließen, usw.) und dann Erstellen der Objekte der Klasse Box, die auf dem Rahmen angezeigt werden sollen. Schaut bitte dieses Bild / Diagramm der Klassen an (hoffe, ich habe es richtig geschrieben): KlassenDiagramm

Jetzt erweitert class Box JPanel. Ich erben von JPanel die Methode Paint () und überschreiben sie, Malkästen.

In der Screen-Klasse, nachdem ich die beiden erstellt habeBoxen, ich .add () sie an den JFrame. Als nächstes startet eine Schleife while (true) und aktualisiert die Position der Box alle 200 milisec, indem der Thread diese Menge schlafen lässt. (In diesem Fall hängt nur einfaches x ++ oder y ++ davon ab, welche Box, Box1 oder Box2).

Hauptproblem 1): Das Programm wird ausgeführt und zeigt den JFrame, aber auf dem JFrame wird es angezeigt nur das zuletzt hinzugefügte Objekt / Komponente - Box. Es zeigt den anderen nicht. Warum?

Ich habe ein Thema gefunden, Wie fügt man einem JFrame mehrere Komponenten hinzu?, und versuchte die Tipps, die der am meisten gewählte Beitrag gab, durch jjnguy 15. November "10 um 17:02 Uhr. Aus irgendeinem seltsamen Grund funktionierte nicht der erste oder der zweite Tipp für mich.

Hauptproblem 2): Soweit ich verstehe, brauche ich Layout-Manager. Warum brauche ich es, wenn ich nur an einem bestimmten X, Y am Rahmen malen möchte ()?

Ich fand einen anderen Beitrag (kann es nicht wieder finden) + Oracle's Richtlinien über Layouts, schlug vor, dass ich setLayout (null) in Betracht ziehen sollte; ich habe versucht, dies zu tun, aber dann gibt es wieder ein Problem.

Hauptproblem 3): Der JFrame erscheint, es zeigt nur 1 Box (die grüne wird nicht angezeigt, was auch immer Sie tun werden. Ich weiß nicht warum) und wenn es sich bewegt, wird es von der anderen Seite gelöscht. Hier: Box-Bewegung

Vielen Dank im Voraus für jegliche Hilfe, Tipps und Erklärungen! Hoffe, der Beitrag ist klar, organisiert und gut aussehend.


public class Screen {

public static void main(String[] args) {
new Screen();
}

private JFrame window;

public Screen() {
window = new JFrame("Multiply components panel");
//window.setLayout(null);
window.setSize(200, 200);

window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

Box b1 = new Box(10,10, "box1");
//b1.setBounds(10, 10, 50, 50);

Box b2 = new Box(100,100, "box2");
//b2.setBounds(100, 100, 50, 50);


window.add(b1);
//window.add(b2);


window.setVisible(true);

while (true){

b1.update();
b2.update();

try {
Thread.sleep(200);
} catch (Exception e) {
// TODO: handle exception
}
}

}
}

public class Box extends JPanel{

int x, y, w, h;
private String name;

public Box(int x, int y, String name) {
this.x = x;
this.y = y;
this.w = 100;
this.h = 100;
this.name=name;
}


public void paint(Graphics g){
System.out.println(this.name.equalsIgnoreCase("box1"));
if(this.name.equalsIgnoreCase("box1")){
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
}else{
g.setColor(Color.GREEN);
g.fillRect(x, y, w, h);
}


}


public void update() {
if(this.name.equalsIgnoreCase("box1"))
x++;
else
y++;
//this.setBounds(x, y, w, h);
System.out.println("Current "+name+": X: "+x+", Y: "+y+", W: "+w+", H: "+h);
repaint();
}

}

Antworten:

3 für die Antwort № 1

Hauptproblem 1): Das Programm läuft und zeigt den JFrame, aber auf dem JFrame zeigt nur das zuletzt hinzugefügte Objekt / Komponente-Box an. Es tut nicht zeig den anderen. Warum?

Sie machen window.add(b1); window.add(b2);, standardmäßig JFrame hat BorderLayout Sie ersetzen also die zuletzt hinzugefügte Box add(..).

Hauptproblem 2): Soweit ich verstehe, brauche ich Layout-Manager. Warum machen Ich brauche es, wenn ich nur an bestimmten X, Y am Rahmen malen möchte ()?

Wenn Sie verwenden JPanels als Objekte im Spiel als, wäre dies die einzige Zeit zu verwenden setLayout(null) wie wir wollen die volle Kontrolle über die JPanels Platzierung.

Hauptproblem 3): Der JFrame erscheint, er zeigt nur 1 Box (das grüne man wird nicht auftauchen, was auch immer Sie tun werden. Ich weiß nicht wieso) und wann Bewegt sich - es wird von der anderen Seite gelöscht. Hier: Box-Bewegung

weil du das tust g.fillRect(x,y,w,h), es sollte sein g.fillRect(0,0,w,h)

Andere Probleme:

1) Ich denke, ein großes Problem, das Sie haben, ist hier:

public class Box extends JPanel{

...

public void paint(Graphics g){

...
}

}

Sie sollten überschreiben paintComponent von JPanelund erinnere dich, anzurufen super.paintComponent(g) als erster Aufruf in überschriebener Methode.

3) Sie sollten überschreiben getPreferredSize von JPanel und korrekte Abmessungen zurückgeben, die dem Bild oder dem Inhalt des JPanel

4) nicht anrufen setSize auf JFrame richtig verwenden Layoutmanager und / oder überschreiben getPreferredSize von notwendigen Behältern als einfach anrufen pack() auf JFrame bevor Sie es sichtbar machen.

5) wie von @ MadProgrammer gesagt, lesen Sie weiter Nebenläufigkeit im Swing Grundsätzlich sollten jedoch alle Swing-Komponenten über EDT erstellt / manipuliert werden SwingUtilities.inokeXXX Block.

6) das ist definitiv schlecht:

while (true){

b1.update();
b2.update();

try {
Thread.sleep(200);
} catch (Exception e) {
// TODO: handle exception
}
}

Sie erstellen nicht nur eine Endlosschleife, sondern rufen auch an Thread.sleep auf dem Thread, den du dir GUI erstellt hast, wird also scheinbar eingefroren. Schau es dir an Wie verwende ich Swing-Timer?, siehe auch Dies ähnliche Frage zum oben genannten Thema.

Hier ist Code mit obigen Fixes implementiert:

Bildbeschreibung hier eingeben

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Screen {

private JFrame window;

public static void main(String[] args) {

//creat UI on EDT
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Screen();
}
});
}

public Screen() {
window = new JFrame("Multiply components panel") {
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 400);
}
};

window.setLayout(null);//only reason this is warrented is because its a gmae using JPanels as game objects thus we need full control over its placing
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//changed from DISPOSE to EXIT so Timers  will be exited too

final Box b1 = new Box(10, 10, 50, 50, "box1");

final Box b2 = new Box(100, 100, 50, 50, "box2");

window.add(b1);
window.add(b2);

window.pack();
window.setVisible(true);

Timer timer = new Timer(200, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
b1.update();
b2.update();
}
});
timer.setInitialDelay(0);
timer.start();

}
}

class Box extends JPanel {

int x, y, w, h;
private String name;

public Box(int x, int y, int w, int h, String name) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.name = name;
setBounds(x, y, w, h);//let the Box class handle setting the bounds more elegant OOP
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println(this.name.equalsIgnoreCase("box1"));
if (this.name.equalsIgnoreCase("box1")) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, w, h);
} else {
g.setColor(Color.GREEN);
g.fillRect(0, 0, w, h);
}
}

@Override
public Dimension getPreferredSize() {
return new Dimension(w, h);
}

public void update() {
if (this.name.equalsIgnoreCase("box1")) {
x++;
} else {
y++;
}
this.setBounds(x, y, w, h);//set the new bounds so box may be updated
System.out.println("Current " + name + ": X: " + x + ", Y: " + y + ", W: " + w + ", H: " + h);
revalidate();
repaint();
}
}

Zuletzt schau dir mein Tutorial / Code-Snippet an Game Development Loop, Logik und Kollisionserkennung Java Swing 2D.

Es hat alles, was Sie brauchen, um ein einfaches 2D-Spiel zu starten,wie Game-Loop, Logik, Pixel-Kollisionserkennung, Animation (dh Austausch zwischen mehreren Sprites, um eine Animation des Sprite-Sets zu erstellen) und vieles mehr, ist der grundlegende Unterschied, dass Objekte als Spiel-Entitäten verwendet werden, dh eine Klasse enthält alle benötigten Elemente Informationen für ein Objekt, das gezeichnet werden soll, IMO, so sollten Spiele gemacht werden, Dinge könnten grafisch intensiv werden und viele JPanels fragen sich, ob der Bildschirm den gesamten FPS definitiv fallen lassen wird