• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

[Java] Fenster zeichnen klappt nicht wie gewollt.

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
Hallo Leute,

ich habe ein kleines Programm geschrieben. Die Logik in dem Programm funktioniert ohne Probleme, allerdings gibt es Probleme beim Fenster zeichnen, die ich nicht nachvollziehen kann.
Es handelt sich hierbei um eine selbsterstellte Version von Canvays Game of Life.
Das Problem ist, dass das Spielfeld, in dem die Zellen angezeigt werden, sich bei jedem neuzeichnen leicht verschiebt und somit meistens die ganz rechten und die unteren Zellen gar nicht oder nur teilweise dargestellt werden, weil der Rest verdeckt wird.
ConvaysGameOfLife Screenshot defekt.jpg

Vielleicht kann mir ja jemand sagen, welche Codezeile da den Mist baut.
[src=java]
//Standardwerte
private int fieldsize = 10;
private String startField = "";
private int fieldDimensionMin = 1;

private final int topPanelHeight = 26;
private final int bottomPanelHeight = 36;
private final int fieldBorderWidth = 5;

//Allgemeine Variableninitialisierung
private Field field;
private JFrame w;
private JPanel top;
private JPanel bottom;
private final JLabel generationNumber = new JLabel("0");
private final JPanel fieldPanel = new JPanel();
private final Color colorAlive = Color.RED;

/**
* Erstellt das Fenster, in welchem das Spiel dargestellt wird.
*/
private void buildWindow() {
//Ein paar Höhen und Breiten für das Fenster definieren / berechnen.
// int topPanelHeight = 26;
// int bottomPanelHeight = 36;
// int fieldBorderWidth = 5;
int width = this.fieldsize*(this.fieldDimensionMin+1) +1 + fieldBorderWidth*2;
if(width < 350) {
width = 350;
}
int height = this.fieldsize*(this.fieldDimensionMin+1) +1 + topPanelHeight + bottomPanelHeight + fieldBorderWidth*2;
if(height < 350 + topPanelHeight + bottomPanelHeight) {
height = 350 + topPanelHeight + bottomPanelHeight;
}

//Fenster erstellen und Grundparameter einstellen
JFrame window = new JFrame();
this.w = window;
window.setSize(width, height);
window.setPreferredSize(new Dimension(width, height));
window.setLocationRelativeTo(null);
window.setTitle("Convays Game of Life");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Container für das komplette Fenster erstellen.
JPanel all = new JPanel();
all.setSize(window.getWidth(), window.getHeight());
all.setPreferredSize(new Dimension(window.getWidth(), window.getHeight()));
all.setLayout(new BoxLayout(all, BoxLayout.PAGE_AXIS));

// System.out.println("---------");
// System.out.println(this.w.getHeight());
// System.out.println(this.w.getWidth());
// System.out.println(all.getHeight());
// System.out.println(all.getWidth());
//
// this.w.pack();
//
// System.out.println("---------");
// System.out.println(this.w.getHeight());
// System.out.println(this.w.getWidth());
// System.out.println(all.getHeight());
// System.out.println(all.getWidth());


//Container für die Überschrift und die Generationsanzeige
this.top = new JPanel();
this.top.setSize(all.getWidth(), topPanelHeight);
this.top.add(new JLabel("Generation "));
this.top.add(this.generationNumber);
// top.setBackground(Color.RED);

all.add(this.top, BorderLayout.PAGE_START);

//Spielfeld-Container definieren
// this.fieldPanel.setSize(all.getWidth()-fieldBorderWidth*2, all.getHeight() - topPanelHeight - bottomPanelHeight-fieldBorderWidth*2);
// this.fieldPanel.setPreferredSize(new Dimension(all.getWidth()-fieldBorderWidth*2, all.getHeight() - topPanelHeight - bottomPanelHeight-fieldBorderWidth*2));
this.fieldPanel.setSize(width-fieldBorderWidth*2, height - topPanelHeight - bottomPanelHeight-fieldBorderWidth*2);
this.fieldPanel.setPreferredSize(new Dimension(width-fieldBorderWidth*2, height - topPanelHeight - bottomPanelHeight-fieldBorderWidth*2));
// this.fieldPanel.setMinimumSize(new Dimension(width-fieldBorderWidth*2, height - topPanelHeight - bottomPanelHeight-fieldBorderWidth*2));
// this.fieldPanel.setBackground(Color.BLUE);

all.add(this.fieldPanel);

//Container für die Buttons erstellen
this.bottom = new JPanel();
this.bottom.setSize(all.getWidth(), bottomPanelHeight);

//Next Gen-Button
JButton b_next = new JButton("Nächste Generation");
b_next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
nextGeneration();
}
});
b_next.setVisible(true);
this.bottom.add(b_next);

//Neustart-Button
JButton b_restart = new JButton("Neustart");
b_restart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
restart();
}
});
b_restart.setVisible(true);
this.bottom.add(b_restart);

//Beenden-Button hinzufügen
JButton b_close = new JButton("Beenden");
b_close.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
b_close.setVisible(true);
this.bottom.add(b_close);

// bottom.setBackground(Color.ORANGE);
all.add(this.bottom, BorderLayout.PAGE_END);

//Fenster packen
window.getContentPane().add(all);
window.pack();

//StartZellen platzieren
this.nextGeneration();

//Fenster anzeigen lassen
window.setVisible(true);

// System.out.println("---------");
// System.out.println(this.w.getHeight());
// System.out.println(this.w.getWidth());
// System.out.println(all.getHeight());
// System.out.println(all.getWidth());
}

/**
* Zeichnet das Spielfeld neu, um den aktuellen Spielstand anzuzeigen.
*/
private void repaint() {
//Alle Pixel in einer Grafik zeichnen lassen
final JPanel fPanel = this.fieldPanel;
final ArrayList<Cell> cells = this.field.getCells();
final Color cAlive = this.colorAlive;

// this.bottom.setSize(this.bottom.getWidth(), this.bottomPanelHeight);
// this.bottom.setPreferredSize(new Dimension(this.bottom.getWidth(), this.bottomPanelHeight));
// this.top.setSize(this.top.getWidth(), this.topPanelHeight);
// this.top.setPreferredSize(new Dimension(this.top.getWidth(), this.topPanelHeight));

//Position des Spielfeldes in X-Richtung bestimmen
int oX = this.w.getWidth()-this.fieldsize*(this.fieldDimensionMin+1) +1;
oX = oX/2;
if(oX < 0) {
oX = 0;
}
final int offsetX = oX;

//Position des Spielfeldes in Y-Richtung bestimmen
int oY = this.w.getHeight()-this.fieldsize*(this.fieldDimensionMin+1) +1 - this.bottom.getHeight() - this.top.getHeight();
oY = oY/2;
if(oY < 0) {
oY = 0;
}
final int offsetY = oY;

// System.out.println(this.w.getHeight());
// System.out.println(this.w.getWidth());
// System.out.println(this.top.getHeight());
// System.out.println(this.top.getWidth());
// System.out.println(this.bottom.getHeight());
// System.out.println(this.bottom.getWidth());
// System.out.println(oX);
// System.out.println(oY);
// System.out.println(fPanel.getWidth()-offsetX*2);
// System.out.println(fPanel.getHeight()-offsetY*2);

//Komponente definieren, die gezeichnet wird
JComponent tmp = new JComponent() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.clearRect(offsetX, offsetY, fPanel.getWidth()-offsetX*2, fPanel.getHeight()-offsetY*2);
//g.clearRect(offsetX, offsetY, fPanel.getWidth(), fPanel.getHeight());
for (Cell c : cells) {
//Zellrand zeichnen
g.setColor(Color.BLACK);
g.fillRect((c.x-1) * (fieldDimensionMin+1) + offsetX,
(c.y-1) * (fieldDimensionMin+1) + offsetY,
fieldDimensionMin+2, fieldDimensionMin+2);
//Zelle zeichnen
if(c.isAlive()) {
g.setColor(cAlive);
g.fillRect((c.x-1) * (fieldDimensionMin+1)+1 + offsetX,
(c.y-1) * (fieldDimensionMin+1)+1 + offsetY,
fieldDimensionMin, fieldDimensionMin);
} else {
g.setColor(Color.WHITE);
g.fillRect((c.x-1) * (fieldDimensionMin+1)+1 + offsetX,
(c.y-1) * (fieldDimensionMin+1)+1 + offsetY,
fieldDimensionMin, fieldDimensionMin);
}
}
}
};
tmp.setPreferredSize(new Dimension(fPanel.getWidth(), fPanel.getHeight()));
// tmp.setBackground(Color.GREEN);

//Neues Spielfeld übernehmen
if (fPanel.getComponentCount() != 0) {
fPanel.remove(fPanel.getComponent(0));
}
fPanel.add(tmp);

//Fenster neu zeichnen lassen.
this.w.revalidate();
}[/src]

Falls das nicht reicht, hier die kompletten Dateien: Anhang anzeigen 0.9.rar
 
Zuletzt bearbeitet:

Timon3

Team ModMii

Registriert
17 Juli 2013
Beiträge
499
Ich kann dein Problem mit der Jar nicht reproduzieren - in Generation 500 war das Feld weiterhin da, wo es sein sollte. Einige Teile sind überdeckt, das waren sie aber von Anfang an. Soweit sehe ich in deinem Code auch keine Probleme. Kannst du eventuell ein Video von dem Problem machen?
 

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #3
Ich habe es ein bisschen falsch dargestellt. Ich meinte damit, dass manche Teile am Anfang überdeckt sind. Dann ziehe ich manuell das Fenster auf die passende Größe und bei der nächsten Generation wandert das ganze Spielfeld runter und ist mindestens unten wieder überdeckt. Irgendwie wird also die Größe von dem "top"-Container immer Größer, als ich es wünsche. Ich hätte ihn gerne bei ca. 30px fixiert. Allerdings wird die Höhe immer größer, egal wie ich alle anderen Container verändere...
 

Timon3

Team ModMii

Registriert
17 Juli 2013
Beiträge
499
Ah, okay, jetzt kann ich dein Problem auch reproduzieren. Das ganze scheint nach einer kurzen Recherche vom BoxLayout zu kommen, das du nimmst - wenn du ein anderes Layout, beispielsweise GridLayout nimmst, solltest du keine Probleme mehr haben. Alternativ könntest du die Positionierung des Felds verändern - es richtet sich momentan immer nach der absoluten Fensterhöhe, wenn du stattdessen nur den nicht verdeckten Teil nimmst, hast du auch keine Probleme mehr.
 

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #5
@GameChamp98: Danke für deinen Vorschlag. Ich werde es gleich mal mit dem anderen Layout ausprobieren. Das mit der Positionierung habe ich bereits gesucht, allerdings nicht gefunden. wie heißen die Funktionen dafür?

Das GridLayout positioniert mit new GridLayout(0, 1) die Container zwar untereinander, allerdings sind die Größen da noch alle gleich (beziehungsweise gleich hoch) - da muss ich noch gucken, wie ich das verändern kann.

Ich habe zwar über Google gefunden, dass es sowas wie setRowExpandRatio() geben soll, aber die Funktion gibt es irgendwie nicht in der Klasse von dem GridLayout, welches ich importiert habe (und ich habe das aktuelle JDK).

--------
Ich habe das Problem durch einen Geistesblitz lösen können.
In der repaint-Methode hatte ich einen Y-Offset berechnen lassen. Durch diesen ist dann alles kaputt gegangen, da dieser nicht nur die Höhe des Spielfeldes, sondern des ganzen Fensters berücksichtigt hat.
 
Zuletzt bearbeitet:

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #7
Der Hinweis auf den Wettbewerb kam von mir :)
Und Hilfe ist erlaubt ;-)
Im Endeffekt habe ich den Fehler aber trotzdem selber gefunden - nur die Eingebung kommt meistens erst nach dem Fragen :-D
 
Oben