Im writing a program that deals with creating a house and rearranging the neighbors (similar to game of life)
It is written in Java and it as a Reset button to restart with the current parameters.
The problem is that when i click the resetButton the whole window closes.
You can find the code at the and of the question.
These are other involved fields, so you might be able to understand the code better:
TextField to set the size of the city (number of squares on an edge).
TextFild to set the maximum percentage of neighbors not-like-you that a household will tolerate before they move. I.e., if the number is set to 70, a red house hold with 6 blue neighbors will move; a red household with 5 blue neighbors is ok according to this.
TextField to set a minimum percentage of neighbors not-like-you that a household will tolerate before they move. Make this greater than 0 for a person who LIKES diversity TextField to set the percentage of red households. Note: you can do this with probability. You do not need to have this exact percentage of red households.
TextField to set the percentage of blue households. White will be what is left over. Single step button gives every household one chance to move. You do not need to be careful about that fact that, as you progress through the city, a person early in the move chances may move to a place that later gets a chance (i.e., some households really get two or more turns).
Go button, to start and stop the program from doing steps on its own.
So my questions is how do i let those field and buttons restart with the current parameters ( restart it with what i have originally after playing a few times)
As you can see I added the resetButton to do its job but somehow it is not.
Ok it is like I run the program I have a set of numbers for red and blue as you can see in my, then when I run it it starts with those numbers. And so I keep on changing as i play, and then there is a reset button that lets me reset what I did and should bring back what it originally started with:
public final static int size = 5 and so on
This is my main program
public class Ghetto extends JFrame implements ActionListener, MouseListener,MouseMotionListener
{
protected Grids theGrid;
JButton resetButton;
javax.swing.Timer timer; // generates ticks that drive the animation
public final static int SIZE = 5;
public final static int BLUE = 10;
public final static int RED = 8;
public final static int DIVERSITY_PERCENTAGE = 70;
public static void main(String[] args)
{
new Ghetto();
}
public Ghetto() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
addMouseListener(this);
addMouseMotionListener(this);
setLayout(new FlowLayout());
theGrid = new Grids(SIZE, BLUE, RED, DIVERSITY_PERCENTAGE);
add(theGrid);
resetButton = new JButton("Reset");
add(resetButton);
resetButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resetWithCurrent();
}
});
setSize(new Dimension(550, 600));
setVisible(true);
}
public void resetWithCurrent()
{
//this.dispose();
}
#Override
public void actionPerformed(ActionEvent e)
{
timer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
performStep();
//if (e.getSource() == resetButton )
//{
//resetWithCurrent();
//}
}
});
}
}
Also I added this part
public class Observable{
int state = 0;
int additionalState = 0;
public final void updateState(int increment)
{
doUpdateState(increment);
notifyObservers();
}
private void notifyObservers() {
// TODO Auto-generated method stub
}
public void doUpdateState(int increment)
{
state = state + increment;
}
}
public class ConcreteObservable extends Observable{
public void doUpdateState(int increment){
super.doUpdateState(increment); // the observers are notified
additionalState = additionalState + increment; // the state is changed after the notifiers are updated
}
}
But it didnt make any difference.
Related
Hi I'm building a game which includes 3 JPanels on a JFrame, a Startscreen, a DrawingPanel and a GameOver screen. If I just create the DrawingPanel and tell the GameController class to begin updating it works fine, but if I create a StartScreen with a button to start the game, then when I press the start game button the game window does not display, although the game code runs.
EDIT:
I have created a new program which mimics the creation of the JPanels, but excludes all of the game code to make it a bit simpler to follow. Below I have included all the relevant classes:
This class creates a JFrame and two JPanels. It also runs the code that updates the game state and tells the DrawingPanel to repaint.
public class TestController{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private final int FRAME_WIDTH = (int)screenSize.getWidth();
private final int FRAME_HEIGHT = (int)screenSize.getHeight();
public boolean gameStarted = false;
private JFrame gameWindow;
private TestDrawingPanel myDrawingPanel;
private TestStartGame startGame;
int counter;
Set<Rectangle> rects;
//creates a JFrame and all the JPanels
public TestController(String title)
{
gameWindow = new JFrame(title);
gameWindow.setSize(FRAME_WIDTH, FRAME_HEIGHT);
gameWindow.setVisible(true);
gameWindow.setResizable(false);
gameWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
startGame = new TestStartGame(getAvailableWidth(), getAvailableHeight());
startGame.addAL(new StartButton());
myDrawingPanel = new TestDrawingPanel(getAvailableWidth(), getAvailableHeight());
gameWindow.add(startGame);
gameWindow.add(myDrawingPanel);
myDrawingPanel.setVisible(false);
myDrawingPanel.setEnabled(false);
rects = new HashSet();
}
private int getAvailableWidth()
{
return gameWindow.getWidth() - gameWindow.getInsets().left - gameWindow.getInsets().right;
}
private int getAvailableHeight()
{
return gameWindow.getHeight() - gameWindow.getInsets().top - gameWindow.getInsets().bottom;
}
//starts the game running
public void startTheGame()
{
myDrawingPanel.setEnabled(true);
startGame.setVisible(false);
startGame.setEnabled(false);
myDrawingPanel.setVisible(true);
gameStarted = true;
update();
}
public boolean getGameStarted()
{
return gameStarted;
}
//loop that runs the game code
public void update()
{
counter = 0;
while(gameStarted)
{
updatePictureState();
myDrawingPanel.draw(rects);
myDrawingPanel.repaint();
}
}
//updates the game state
public void updatePictureState()
{
rects.clear();
for (int i = counter + 10; i < counter + 100; i = i + 10)
{
rects.add(new Rectangle(i,i,10,10));
}
}
//an action listener to be added to the start screen
private class StartButton implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Object buttonPressed = e.getSource();
if(buttonPressed.equals(TestStartGame.start))
{
startTheGame();
}
}
}
}
This class is an extended JPanel with a single button to start the game:
public class TestStartGame extends JPanel{
private final JPanel buttons;
public static JButton start;
//creates a JPanel with a single button to start the game
public TestStartGame(int width, int height)
{
setSize(width, height);
setLayout(new GridLayout(2,1));
setBackground(Color.GREEN);
buttons = new JPanel();
buttons.setSize(width, height / 2);
buttons.setBackground(Color.red);
start = new JButton("Start");
buttons.add(start);
add(buttons, BorderLayout.SOUTH);
}
//adds an action listener to the button
public void addAL(ActionListener al)
{
start.addActionListener(al);
}
}
This class is an extended JPanel and acts as the main screen for the game, being updated to with each cycle of the game to display it's current state:
public class TestDrawingPanel extends JPanel{
Set<Rectangle> drawSet;
//creates the drawing panel and sets the size and background
public TestDrawingPanel(int width, int height)
{
setSize(width, height);
this.setBackground(Color.CYAN);
drawSet = new HashSet();
}
public void draw(Set<Rectangle> platforms)
{
drawSet.clear();
drawSet = platforms;
}
//draws the game window
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
System.out.println("works here");
g.setColor(Color.red);
for (Rectangle r : drawSet)
{
g.fillRect((int)r.getX(), (int)r.getY(), (int)r.getWidth(), (int)r.getHeight());
}
}
}
If I just add the TestDrawingPanel, it displays fine, but if I start with a TestStartScreen then when I click the start game button the TestStartScreen does not disappear and the TestDrawingPanel never displays. Interestingly, if I have both screens but do not call the update method is TestController then the start game button works correctly and the TestDrawingPanel displays, although obviously nothing happens as the update method is where the game state is changed.
I have discovered the problem is that if the TestDrawingPanel is not the only JPanel created then the call to repaint it fails.
Here:
Thread.sleep(20);
You are most likely sleeping on the Event Dispatcher Thread. That will freeze your whole application. You have to step back and look into invokeLater to ensure "correct" threading within your UI.
Problem solved courtesy of #Andrew-Thompson:
"while(gameStarted) .. No, no a thousand times no. An infinite loop will likely freeze the GUI. Use a Swing based Timer to call those code statements in the loop, in the actionPerformed method of an ActionListener"
First of all, it's not really a virus that is used to spy, or steal bank accounts. I don't even know if it's a virus at all. I only made it to troll friends/people I know, and practice my programming skills. I will show you the code, then I will try to explain it a bit;
package pracatice;
import java.awt.event.*;
import javax.swing.*;
public class practice extends JFrame
{
public static boolean bool = true;
public static int x = 0;
public static int y = 0;
public static int num = 0;
public static TimerClass tc = new TimerClass();
public static Timer timer = new Timer(30, tc);
public JPanel panel = new JPanel();
public JButton btn = new JButton("press");
public practice()
{
setSize(100,100);
setTitle("Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPanel();
setVisible(true);
}
public void setPanel()
{
btn.addActionListener(new listener());
panel.add(btn);
add(panel);
}
public class listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
num = 0;
timer.start();
}
}
public static class TimerClass implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
do
{
num++;
JOptionPane optionPane = new JOptionPane("PC afected by virus");
JDialog dialog = optionPane.createDialog(null, "Virus");
dialog.setModal(false);
dialog.setLocation(x, y);
dialog.show();
updateCordinates();
}while(bool == true);
}
}
public static void updateCordinates()
{
if(x != 1100)
x += 100;
else if(x == 1100)
{
x = 0;
y += 50;
}
if(y == 650)
y =0;
}
public static void main(String[] args)
{
new practice();
}
}
So, at first it obviously builds a window, 100 X 100 px big. It adds a button that says "press". When you press, it starts a new loop, every 30 milliseconds.
every iteration of the loop, it puts in a new JOPtionPane.showMessageBox(null,...) in a slightly different location.
At first, when I just made it, I didn't know it would be unstoppable. I ran it, and had to restart my laptop. When I pressed ok, it would put in another box, in the exact same spot. When I tried to open task manager, it would automatically minimize it, and go back into the "virus" window. So, the laptop was unusable. I had to restart it, closing some of my dads tabs...
Here are a few things I would like to find out;
1) If I left this run over night, is it possible, that the laptop ran out or RAM, and if it did, what would happen?
2) Can I make it that, when I press a button on the keyboard, the whole thing just closes?
Like I said before, I was only trying to prank my friends, and the program happened to not be closable... any advice?
Yes, the computer will eventually run out of RAM. When that happens, nothing disastrous should happen other than your program crashing.
Not very easily, because JOptionPane windows don't let keyboard events get to the rest of the program. You'd need to use your own type of window instead of JOptionPane. You could then use a KeyListener that does System.exit(0).
I have a game that is similar to the game of life. the game deals with creating a house and rearranging the neighbors and such. I WANT to restart the game, simply need to set all of these values back to the original start values. How do I do that with a code. I understand the English of it but cant seem to convert it to a code.
This is some of my main program (If anyone want me to post the whole main program I can) but to make it simple and I dont want to confuse you guys.
So what I WANT: to restart the game, simply I want to set all of these values back to the original start values.
Some Of Main Program:
public class Ghetto extends JFrame implements ActionListener, MouseListener,MouseMotionListener
{
protected Grids theGrid;
JButton resetButton;
javax.swing.Timer timer; // generates ticks that drive the animation
public final static int SIZE = 5;
public final static int BLUE = 10;
public final static int RED = 8;
public final static int DIVERSITY_PERCENTAGE = 70;
public static void main(String[] args)
{
new Ghetto();
}
public Ghetto() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
addMouseListener(this);
addMouseMotionListener(this);
setLayout(new FlowLayout());
theGrid = new Grids(SIZE, BLUE, RED, DIVERSITY_PERCENTAGE);
add(theGrid);
resetButton = new JButton("Reset");
add(resetButton);
resetButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resetWithCurrent();
}
});
setSize(new Dimension(550, 600));
setVisible(true);
}
//public void resetWithCurrent()
//{
//}
#Override
public void actionPerformed(ActionEvent e)
{
timer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
performStep();
}
});
}
}
Typically, the eaiest way to "reset" is not to. Just throw away the object and make a brand new one! The constructor will take care of everything for you, and you won't have to worry about missing something. If you really need to, you can make a reset method that performs all the necessary setting, and have the constructor call it. You have to be sure to catch everything, so in particular you can't use any field initializations that look like Foo x = bar and you can't use any initializer blocks.
The approach I suggest:
Ghetto ghetto = new Ghetto();
//Do stuff with the ghetto.
ghetto = new Ghetto();
//BLAM! The old ghetto is *gone*, and we have a new one to play with.
If these "values" are stored in a separate class, say class "GameProperties" then you just need to invoke the constructor by creating a new instance of the GameProperties.
The constructor should take care of assigning default values.
So, assuming you have an instance of GameProperties within Ghetto class named props:
Add new instance of GameProperties class and change resetWithCurrent in Ghetto class:
GameProperties props = new GameProperties();
public void resetWithCurrent(){
//This will reset the values to their defaults as defined in the constructor
props = new GameProperties();
}
Remove the values constants as you are using your GameProperties. Use the getters methods
to obtain the properties values.
Create new class:
public class GameProperties {
//assign initial default values
private int size= 5;
private int blue= 10;
private int red= 8;
private int diversity_percentage= 70;
//calling default constructor will set the properties default values
public GameProperties(){
}
public int getSize(){
return size;
}
public int getBlueValue(){
return size;
}
public int getRedValue(){
return size;
}
public int getDiversityPercentage(){
return diversity_percentage;
}
}
Hope it helps.
i'm trying to make it display one JPanel and remove the other depended on which timer is off in java. here is the snip it of code. mainMenu and pongField are the JPanels and this is inside a timer that acts every millisecond;
if (SwingUtilities.getAncestorOfClass(JFrame.class, pongField) != null){
if (!pongField.getTimer().isRunning())
{
mainMenu = new MainMenu(screenX, screenY, myColor, background, contentPane);
contentPane.remove(pongField);
}}
if (SwingUtilities.getAncestorOfClass(JFrame.class, mainMenu) != null){
if (!mainMenu.getTimer().isRunning())
{
switch(mainMenu.getButton())
{
case 1:
pongField = new PongField(screenX, screenY, 0, moderator, player1UpControl, player2UpControl, player1DownControl, player2DownControl, myColor, background, contentPane, speed);
mainMenu.setButton(0);
contentPane.remove(mainMenu);
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}}
let me be a little more specific.
I am trying to make Pong, and one JPanel is the actual game while the other is the main menu. if the game ends the timer stops and if i press a button on the main Menu the timer stops and set getButton() to a number depending on which is pressed. for example if button single player is pressed it creates the game and gets rid of the current Jpanel. but if the game ends it get rid of the current JPanel and displays the main menu. Also each JPanel when created set it's own bounds, background color, and adds itself to the JFrame.
The problem is when i run it and the game ends it doesn't change back unless i minimize it and bring it back up but then the button won't work. here is the code for MainMenu. PongField's code is too long but i think i summed up what it did good enough but i can post it too if you want.
public class MainMenu extends JPanel
{
private static final long serialVersionUID = 1L;
//JButtons
private JButton singleJButton, multiJButton, settingsJButton, exitJButton;
//timer if game is still on
private Timer runningTimer;
//JLabel for title
private JLabel titleJLabel;
//screen size
int screenX, screenY;
//color of text and background
private Color myColor, background;
//Container of the JFrame
private Container contentPane;
//which button was clicked
private int buttonPressed;
public MainMenu(int x, int y, Color myC, Color backg, Container contentP)
{
super();
//Initialize all given variables
screenX = x;
screenY = y;
myColor = myC;
background = backg;
contentPane = contentP;
setBounds(0,0,screenX,screenY);
setBackground(background);
contentPane.add(this);
setFocusable(true);
requestFocusInWindow();
singleJButton = new JButton();
singleJButton.setBounds(100, 100, 100, 50);
singleJButton.setText("Single Player");
singleJButton.setFocusable(false);
contentPane.add(singleJButton);
singleJButton.addActionListener(new ActionListener()
{public void actionPerformed( ActionEvent event )
{singleJButtonAction(event);}});
runningTimer = new Timer( 30, new ActionListener()
{public void actionPerformed( ActionEvent event )
{}});
runningTimer.start();
}
public Timer getTimer()
{
return runningTimer;
}
public int getButton()
{
return buttonPressed;
}
public void setButton(int val)
{
buttonPressed = val;
}
private void singleJButtonAction(ActionEvent e)
{
runningTimer.stop();
buttonPressed = 1;
}
//make this panel have focus
public void focus()
{
requestFocusInWindow();
}
What, is it not working? I'm just guessing because you don't say.
The first thing I see if you're creating and removing panes dynamically. It would be more efficient to just hide them. Of course, I don't know what your layout looks like. The other option is to just construct them on startup with all your other GUI stuff and go ahead and add and remove them, but don't recreate them based on the timer. Just show them and hide them as needed. Like this:
mainMenu.setVisible( true );
mainMenu.setVisible( false );
Every millisecond if also pretty fast. I look at ratcheting down, to say one second or so. Of course, it depends on what you're doing.
HTH
I still have problem understanding what your question is?
One thing that seems to be missing in the code is where you add the mainMenu and pongField you create. You remove them from the contentPane by contentPane.remove(pongField); and contentPane.remove(mainMenu); is that your problem?
I'm a student programming a frogger game, when the frog collides with an object or reaches the end zone either the score is incremented or lives decremented and the frog returned to the start position. this section works and the decrement and increment work when outputting them to the console, I try to pass the variable to the other jpanel and display it there but it doesnt update and display the variable in the textField.
Game Panel
public GamePanel() {
super();
setFocusable(true);
addKeyListener(new KeyList());
System.out.println("GAME PANE FOCUS:" + this.isFocusOwner());
scores.setVisible(true);
lives = p.STARTLIVES;
scores.setCurrentLives(lives);
txtTest.setText("Hello");
txtTest.setVisible(true);
add(scores,new AbsoluteConstraints(0,550,50,800));
Boolean displayable = scores.isDisplayable();
System.out.println("Displayable" + displayable);
scores.setEnabled(false);
scores.revalidate();
scores.repaint();
scores.setVisible(true);
System.out.println("Displayable" + displayable);
car1.start();
car2.start();
car3.start();
car4.start();
Log1.start();
Log2.start();
Log3.start();
Log4.start();
Log5.start();
Log6.start();
Log7.start();
Log8.start();
//check for collisions
}
final public void winZone(Rectangle object){
if(myFrog.frogArea().intersects(object)){
currentScore = currentScore + 100;
System.out.println("current Score " + currentScore);
p.setScore(currentScore);
scores.myScore().setText("hello");
myFrog.lostLife();
}
scores panel
public class jplScores extends JPanel {
Properties p = new Properties();
int currentLives;
int i;
/** Creates new form jplScores */
public jplScores() {
initComponents();
}
public void setCurrentLives(int Lives){
currentLives = Lives;
}
public String getCurrentLives(){
String L = Integer.toString(currentLives);
return L;
}
public JTextField myScore(){
return txtScore;
}
Currently it will display the jpanel from the frame that they are both in but i have tried to make it so its a panel within a panel but i cant get the panel to display from within the game panel.
Any help would be great thanks
public FroggerGame() {
initComponents();
setFocusable(true);
//repaint();
// p.setHeight(550);
// p.setWidth(800);
// p.setLives(3);
// p.setScore(0);
PANELHEIGHT = p.getHeight();
PANELWIDTH = p.getWidth();
welcomePanel();
/*
Toolkit tool = Toolkit.getDefaultToolkit();
imgBackground = tool.getImage(imageBackground);
background = new ImageIcon(imgBackground);
//setDefaultCloseOperation(EXIT_ON_CLOSE);
*/
jps.myScore().addPropertyChangeListener(new java.beans.PropertyChangeListener() {
public void propertyChange(java.beans.PropertyChangeEvent evt) {
// txtScorePropertyChange(evt);
jps.myScore().setText(Integer.toString(gp.currentScore()));
System.out.println(Integer.toString(gp.currentScore()));
jps.getScore(gp.currentScore());
System.out.println(" main score " + gp.currentScore());
}
});
}
....
private void btnEnterActionPerformed(ActionEvent evt) {
welcomePanel.setVisible(false);
getContentPane().setLayout(new AbsoluteLayout());
getContentPane().add(gp,new AbsoluteConstraints(0,0,800,550));
getContentPane().add(jps,new AbsoluteConstraints(0,550,800,100));
//gp.setSize(800, 550);
// gp.setBounds(0, 0, 800, 550);
gp.setVisible(true);
gp.requestFocusInWindow();
jps.setVisible(true);
gp is the game panel and jps is the score panel.
This really has little to do with "panels" or Swing GUI coding and all to do with the basic OOPS issue of passing information from one class to another. One way to solve this is to give your Scores panel a public method, say
public void changeScore(int value) {
// in here add the new value to the currently
// displayed value and display the new value.
}
Then the main class, the one with a Scores panel reference, you can call this method, passing in 1 if score is to increase or -1 if it is to decrease.
I think of this as the "push" solution, where one class pushes information into the other class. Another way to solve this is via listeners where the Scores class listens to critical properties of the other class and then changes its own score when an appropriate event occurs, and this often involves using PropertyChangeListeners or other more Swing-specific listener classes. This is sometimes a nicer solution, but I consider it a slightly more advanced concept.