Panel verkleinert sich unerklärlicherweise

Lucaaa

Bekanntes Mitglied
Hallo!
In meinem Programm kann man im Menü eine Spielfeldgröße festlegen. (Über eine JComboBox). Das Problem ist nun, das sich das Panel ab einer Feldgröße von etwa knapp über 100 verkleinert. Es rückt einfach in die Obere linke Ecke des Frames.
Aber nur wenn man die Feldgröße über die Checkbox auswählt. Wenn man sie direkt gleich im Code festlegt, funktioniert alles.
Was läuft da falsch?
Danke schon mal.

Hier der Code:

Main.java
Java:
package com.ludevstudio.conwaysgameoflife;
public class Main {
 static int width;
 static int height;
 
 static Frame frame;
 static MenuScreen menu;
 static SimulationScreen game;
 
 static Thread simThread;
 
 
 public static void main(String[] args) {
  frame = new Frame();
 
  frame.setDefaultCloseOperation(3);
  frame.setResizable(false);
  frame.setUndecorated(false);
  frame.setSize(900, 900);
  frame.setLocationRelativeTo(null);
  frame.setTitle("Conways Game of Life");
 
 
 
 
 
 width = frame.getWidth();
 height = frame.getHeight();
 
 menu = frame.createMenuScreen();
 
 frame.setVisible(true);
 }
 
 
 public static void startGame() {
 
  simThread = new Thread(new Runnable() {
  
   @Override
   public void run() {
    game = frame.createSimulationScreen();
    game.setVisible(true);
    game.requestFocus();
    long lastFrame = System.currentTimeMillis();
    while(true) {
     long thisFrame = System.currentTimeMillis();
     float tslf = (float) ((thisFrame-lastFrame) / 1000.0);
     lastFrame = thisFrame;
    
     game.update(tslf);
     game.repaint();
    
    
     try {
      Thread.sleep(10);
     } catch (InterruptedException e) {
      System.out.println("Thread is interrupted");
     }
   
    }
   }
  });
 
  simThread.start();
  menu.setVisible(false);
 
 }
 
 public static void stopGame() {
  simThread.interrupt();
  menu.setVisible(true);
  game.setVisible(false);
 }
 
 public static void pauseGame() {
 
 }
 
 public static void resumeGame() {
 
 }
 
 
 
 
 
 
 }

Frame.java
Java:
[/COLOR][/FONT][/LEFT]
package com.ludevstudio.conwaysgameoflife;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Frame extends JFrame {
 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private SimulationScreen screen;
 private MenuScreen menu;
 
 Simulation sim;
 
 
 
 
 public Frame() {
 
 }
 
 
 public SimulationScreen createSimulationScreen() {
  screen = new SimulationScreen();
  add(screen);
  return screen;
 }
 
 
 public MenuScreen createMenuScreen() {
  menu = new MenuScreen();
  add(menu);
  return menu;
 }
 
 
 }
[LEFT][FONT=verdana][COLOR=rgb(20, 20, 20)]

MenuScreen.java
Java:
[/COLOR][/FONT][/LEFT]
package com.ludevstudio.conwaysgameoflife;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.CellEditorListener;
public class MenuScreen extends JPanel implements ActionListener{
  /**
  * 
  */
 private static final long serialVersionUID = 1L;
  public JLabel labHeadLine;
  public JPanel panSettings;
  
  
  public JButton btnStartSimulation;
  
  // Fonts
  Font fontHeadline;
  Font fontHeadSettings;
  Font fontBtnStart;
  Font settingsFont;
  
  // Borders
  LineBorder settingsLineBorder = new LineBorder(Color.white);
  EmptyBorder headBorder = new EmptyBorder(40, 0, 50, 0);
  EmptyBorder settingsMargin = new EmptyBorder(0, 70, 0, 70);
  TitledBorder settingsBorder = BorderFactory.createTitledBorder(settingsLineBorder, "Settings");
  EmptyBorder btnStartBorder = new EmptyBorder(50, 50, 50, 50);
  
  
  // Settings Components
  public JLabel labRuleSystem;
  public JComboBox<String> combRuleSystem;
  public JLabel labFieldSize;
  public JComboBox<String> combFieldSize;
  public String[] strFieldSize = new String[450/5];
  
  public String[] strRuleSystems = new String[] {"23/3 - Standard"};
  
  
 public MenuScreen() {
  setBackground(Color.BLACK);
  setLayout(new BorderLayout());
  setAlignmentX(SwingConstants.CENTER);
  
  // Fonts
  fontHeadline = new Font("Arial", Font.BOLD, 64);
  fontHeadSettings = new Font("Arial", Font.BOLD, 40);
  fontBtnStart = new Font("Arial", Font.BOLD, 50);
  settingsFont = new Font("Arial", Font.PLAIN, 25);
  
  // Config Borders
  settingsBorder.setTitleColor(Color.WHITE);
  settingsBorder.setTitleJustification(TitledBorder.CENTER);
  settingsBorder.setTitleFont(fontHeadSettings);
  
  
  // Components
  labHeadLine = new JLabel("Conways Game of Life");
  labHeadLine.setFont(fontHeadline);
  labHeadLine.setForeground(Color.white);
  labHeadLine.setHorizontalAlignment(SwingConstants.CENTER);
  labHeadLine.setBorder(headBorder);
  add(labHeadLine, BorderLayout.PAGE_START);
  
  panSettings = new JPanel();
  panSettings.setFont(fontHeadline);
  panSettings.setBorder(new CompoundBorder(settingsMargin, settingsBorder));
  panSettings.setForeground(Color.WHITE);
  panSettings.setBackground(Color.black);
  panSettings.setLayout(new GridBagLayout());
  GridBagConstraints gbc = new GridBagConstraints();
  gbc.insets = new Insets(10, 10, 10, 10);
  gbc.anchor = GridBagConstraints.LINE_START;
  add(panSettings, BorderLayout.CENTER);
  
  
  btnStartSimulation = new JButton("Start Simulation");
  btnStartSimulation.setBorder((btnStartBorder));
  btnStartSimulation.setBackground(Color.black);
  btnStartSimulation.setForeground(Color.blue);
  btnStartSimulation.setSize(200, 50);
  btnStartSimulation.setFont(fontBtnStart);
  btnStartSimulation.setFocusable(false);
  btnStartSimulation.setContentAreaFilled(false);
  btnStartSimulation.addActionListener(this);
  add(btnStartSimulation, BorderLayout.SOUTH);
 
 
  // Settings Components
  labFieldSize = new JLabel("Field Size");
  labFieldSize.setForeground(Color.white);
  labFieldSize.setFont(settingsFont);
  gbc.gridx = 0;
  gbc.gridy = 0;
  panSettings.add(labFieldSize, gbc);
  
  for(int i = 5; i<(450/5); i++) {
   strFieldSize[i-5] = new String((i*5) + "x" + (i*5) );
  }
  
  combFieldSize = new JComboBox<String>(strFieldSize);
  combFieldSize.setFont(settingsFont);
  combFieldSize.setBackground(Color.BLACK);
  combFieldSize.setForeground(Color.white);
  combFieldSize.setFocusable(false);
  gbc.gridx = 1;
  gbc.gridy = 0;
  combFieldSize.addActionListener(this);
  
  panSettings.add(combFieldSize, gbc);
  
  labRuleSystem = new JLabel("Rule System");
  labRuleSystem.setForeground(Color.white);
  labRuleSystem.setFont(settingsFont);
  gbc.gridx = 0;
  gbc.gridy = 1;
  panSettings.add(labRuleSystem, gbc);
 
  combRuleSystem = new JComboBox<String>(strRuleSystems);
  combRuleSystem.setFont(settingsFont);
  combRuleSystem.setBackground(Color.BLACK);
  combRuleSystem.setForeground(Color.white);
  combRuleSystem.setFocusable(false);
  gbc.gridx = 1;
  gbc.gridy = 1;
  panSettings.add(combRuleSystem, gbc);
  
 }
 @Override
 public void actionPerformed(ActionEvent e) {
  if(e.getSource()==btnStartSimulation) {
   setVisible(false);
   Main.startGame();
  } else if(e.getSource()==combFieldSize) {
   String text = combFieldSize.getSelectedItem().toString();
   String[] parts = text.split("x");
   Cell.cellsInX = Integer.parseInt(parts[0]);
   Cell.cellsInY = Integer.parseInt(parts[1]);
   
   }
 }
 
}
[LEFT][FONT=verdana][COLOR=rgb(20, 20, 20)]

SimulationScreen.java
Java:
[/COLOR][/FONT][/LEFT]
package com.ludevstudio.conwaysgameoflife;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JLabel;
public class SimulationScreen extends JLabel implements KeyListener {
 private static final long serialVersionUID = 1L;
 
 Simulation sim;
 public float UPDATE_TIME = 0f;
 public float tslu = 0;
 
  public SimulationScreen() {
   setBounds(0,0, Main.width, Main.height);
   addKeyListener(this);
   sim = new Simulation();
  }
 
 
 
 
 
 @Override
 public void paintComponent(Graphics g) {
  super.paintComponent(g);
  
  sim.draw(g);
  
 }
 
 
 public void update(float tslf) {
  tslu += tslf;
  if(tslu > UPDATE_TIME) {
  sim.update();
  tslu = 0;
  }
 }


 @Override
 public void keyPressed(KeyEvent e) {
  if(e.getKeyCode()==KeyEvent.VK_ESCAPE)
   Main.stopGame();
 }


 @Override
 public void keyReleased(KeyEvent arg0) {
  // TODO Auto-generated method stub
  
 }


 @Override
 public void keyTyped(KeyEvent arg0) {
  
 }
 
 
}[/COLOR][/FONT][/LEFT]
Cell.java
Java:
package com.ludevstudio.conwaysgameoflife;
import java.awt.Color;
import java.awt.Graphics;
public class Cell {
 private int x;
 private int y; 
 
 public static int cellsInX = 100;
 public static int cellsInY = 100;
 public static int cellWidth = Main.width/cellsInX;
 public static int cellHeight = Main.height / cellsInY;
 
 public boolean alive;
 public boolean nextRoundAlive;
 

 public Cell(int x, int y) {
  cellHeight = Main.height / cellsInY;
  cellWidth = Main.width / cellsInX;
  
  
  this.x = x;
  this.y = y;
  
 }
 
 
 public void draw(Graphics g) {
  g.setColor(Color.BLACK);
  g.drawRect(x*cellWidth, y*cellHeight, cellWidth, cellHeight);
  
  if(alive) g.setColor(Color.black);
  else g.setColor(Color.white);
  
  g.fillRect(x*cellWidth+1, y*cellHeight+1, cellWidth-1, cellHeight-1);
  
 }
 
 
 public boolean isAlive() {
  return alive;
 }

 public void setAlive(boolean alive) {
  this.alive = alive;
 }
 
 public void nextRoundAlive() {
  alive = nextRoundAlive;
 }
 
 public boolean isNextRoundAlive() {
  return nextRoundAlive;
 }
 
 
 
}



Simulation.java
Java:
[/COLOR][/FONT][/LEFT]
package com.ludevstudio.conwaysgameoflife;
import java.awt.Graphics;
import java.util.Random;
public class Simulation {
 
 private Cell[][] cells;
 private int witdh = Main.width / Cell.cellWidth;
 private int height = Main.height / Cell.cellHeight;
 
 private Random random;
 
 public Simulation() {
  cells = new Cell[witdh] [height];
  
  random = new Random();
  
  
  for(int x = 0; x<witdh; x++) {
   for(int y = 0; y<height; y++) {
    cells[x][y] = new Cell(x, y);
    cells[x][y].setAlive(random.nextBoolean());
   }
  }
 }
 
 public void draw(Graphics g) {
  for(int x = 0; x<witdh; x++) {
   for(int y = 0; y<height; y++) {
    cells[x][y].draw(g);
   }
  }
  
 }
 
 
 void update() {
  for(int x = 0; x<witdh; x++) {
   for(int y = 0; y<height; y++) {
    int mx = x-1;
    if(mx<0) mx = witdh-1;
    int my = y-1;
    if(my<0) my = height-1;
    int gx = (x+1)%witdh;
    int gy = (y+1)%height;
    
    int aliveCounter = 0;
    
    if(cells[mx][my].isAlive()) aliveCounter++;
    if(cells[mx][y].isAlive()) aliveCounter++;
    if(cells[mx][gy].isAlive()) aliveCounter++;
    if(cells[x][my].isAlive()) aliveCounter++;
    if(cells[x][gy].isAlive()) aliveCounter++;
    if(cells[gx][my].isAlive()) aliveCounter++;
    if(cells[gx][y].isAlive()) aliveCounter++;
    if(cells[gx][gy].isAlive()) aliveCounter++;
   
    if(aliveCounter <2 || aliveCounter > 3 ) {
     cells[x][y].nextRoundAlive = false;
   }  else if(aliveCounter == 3) {
    cells[x][y].nextRoundAlive = true;
   }
   
  }
   
  }
  
  
  
  
  for(int x = 0; x<witdh; x++) {
   for(int y = 0; y<height; y++) {
    cells[x][y].nextRoundAlive();
   }
  }
  
 }
 
 
 
 
}
[LEFT][FONT=verdana][COLOR=rgb(20, 20, 20)]
 
Hallo,
in Cell.java ich cellsInX aund cellsInY modifiziert (von 100 zu 200) und das Ergebnis war, dass die unerwartete Verhalten der Feldgröße nur oben einer Wahl von cca 200x200 zu beobachten war.
Also ich habe die beide zu -1 modifiziert und habe sofort eine java.lang.NegativeArraySizeException bekommen, und zwar im Simulation.java, Zeile 14. Was wiederum heißt, dass irgendwie Cell.cellsInX ist erst von Simulation angerufen (da ist -1) und nur später von MenuScreen.actionPerformed() modifiziert.

Wenn ich es gut verstanden habe, die Information fließt volgenderweise in Dein Programm:
1) erst sind static variables gerechnet, z.B. Cell.cellWidth = Main.width / cellsInX == 900 / 100 = 9
2) dann kann der Nutzer die Größe im Menu auswählen. Dann wird Cell.cellsInX und Cell.cellsInY modifiziert, aber nichts anderes.
3) dann wird Simulation() aufgerufen, der aber rechnet so: witdh = Main.width / Cell.cellWidth
Was hier meiner Meinung nach im 2. Punkt fehlt ist die Umrechnung von Cell.cellWidth wenn Cell.cellsInX modifiziert wird.

Was Du machen könntest:
1) eine neue Funktion in Cell schreiben:
Java:
public static void modifySize(int x, int y){
    cellsInX = x;
    cellsInY = y;
    cellWidth = Main.width / cellsInX;
    cellHeight = Main.height / cellsInY;
}

2) in MenuScreen.actionPerformed() diese Funktion aufrufen:
Java:
Cell.modifySize(Integer.parseInt(parts[0]) , Integer.parseInt(parts[1]));

LG
 
Ich kann es gar nicht starten. In Main.java wird rot unterstrichen:
Java:
frame.setDefaultCloseOperation(3);
Java:
menu = frame.createMenuScreen();
Java:
game = frame.createSimulationScreen();

Da steht: "The method [...] is undefined for the type Frame"
 
Hallo,
in diesem Fall das Unterschied ist, dass cellWidth und cellHeight zwei STATIC Variable sind, und im ersten Variante des Programs sind sie nur ein einziges Mal gerechnet (und zwar am Anfang des Programs, wenn alle Klasse "gebaut" sind). MenuScreen.actionPerformed() kümmerte sich ausschließlich um cellsInX und cellsInY, aber nicht um cellWidth und cellHeight. Im Cell.java habe ich natürlich gesehen, dass Du cellWidth = Main.width / cellsInX geschrieben hast, aber das ist nicht "automatisch" umgerechnet jedes Mal wenn irgendwelche Komponente modifiziert wird.

Die Funktion die ich geschrieben habe sorgt eben dafür, alle STATIC Variable wieder berechnen, die von die modifizierten cellsInX oder cellsInY abhängig sind.
 

Zurück
Oben