I'm trying to add a GUI to the predator-prey simulation. It can allow users to choose which simulation(species involved) they want to do, set the simulation field size they want, and show the progress of the simulation and result.
I asked a question before, and I kinda figure it out what caused the problem.
But now I encounter another question:
How do I let the simulation buttons use the same object method which generate button use, but also don't generate the field again?
As the code shown below,
(1)after I generate the field and press "Reset" button, it will generate the field again then reset simulation(show up a new field window with different data);
(2)after I generate the field and press "Next step" button, it will generate the field again then show next step simulation(show up a new field window and don't inherit the initial data I generate);
(3)after I generate the field and press "long run step" button, it will generate the field again then show next hundred step simulation result(show up a new field window and don't inherit the initial data I generate and don't show the progress);
private class ButtonHandler implements ActionListener{//Generate field
public void actionPerformed(ActionEvent e){
String depthstr = depthtxt.getText();
String widthstr = widthtxt.getText();
int depth = Integer.parseInt(depthstr);
int width = Integer.parseInt(widthstr);
switch(version) {//Different specices simulation choosed by user
case 0:
Simulator set = new Simulator();
set.Simulator(depth,width);
break;
case 1:
SimulatorRF setRF = new SimulatorRF();
setRF.SimulatorRF(depth,width);
break;
case 2:
SimulatorRW setRW = new SimulatorRW();
setRW.SimulatorRW(depth,width);
break;
...
case 25:
SimulatorFWBH setFWBH = new SimulatorFWBH();
setFWBH.SimulatorFWBH(depth,width);
break;
}
reset_butt.setEnabled(true);
nextstep_butt.setEnabled(true);
longstep_butt.setEnabled(true);
}
}
private class SimulateOption implements ActionListener{
public void actionPerformed(ActionEvent e){
switch(version) {
case 0:
Simulator set = new Simulator();
set.Simulator(depth,width);
if(e.getSource() == reset_butt){
set.reset();
}
else if(e.getSource() == nextstep_butt){
set.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
set.runLongSimulation();
}
break;
case 1:
SimulatorRF setRF = new SimulatorRF();
setRF.SimulatorRF(depth,width);
if(e.getSource() == reset_butt){
setRF.reset();
}
else if(e.getSource() == nextstep_butt){
setRF.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
setRF.runLongSimulation();
}
break;
case 2:
SimulatorRW setRW = new SimulatorRW();
setRW.SimulatorRW(depth,width);
if(e.getSource() == reset_butt){
setRW.reset();
}
else if(e.getSource() == nextstep_butt){
setRW.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
setRW.runLongSimulation();
}
break;
...
case 25:
SimulatorFWBH setFWBH = new SimulatorFWBH();
setFWBH.SimulatorFWBH(depth,width);
if(e.getSource() == reset_butt){
setFWBH.reset();
}
else if(e.getSource() == nextstep_butt){
setFWBH.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
setFWBH.runLongSimulation();
}
break;
}
reset_butt.setEnabled(true);
nextstep_butt.setEnabled(true);
longstep_butt.setEnabled(true);
}
}
}
Is there a way to fix my code to solve the problem?
I hope that
(1)after I click the "reset" button, it reset the field I generated (don't show up a new field window)
(2)after I click the "next step" button, it simulate next step of the field I generated (inherit the initial data I generate and don't show up a new field window)
(3)after I click the "next hundred step" button, it simulate next hundred step of the field I generated and show the process (inherit the initial data I generate and don't show up a new field window)
Here are my full codes if you are intrested:
https://github.com/KasmaJC/predator-prey-simulation-with-GUI
*There is a BlueJ project rar. at button
Well I figure it out myself again...
I put all of my Classes into a package(name as PredatorPreySimulation), and change all simulator classes' method into static method.
By doing so, I don't need to create an instance of the class to call a static method, and I can let the simulation buttons use the same method which generate button use, but also don't generate the field again.
In this case, I can use the code below:
import PredatorPreySimulation.Simulation;
import PredatorPreySimulation.SimulationRF;
...
and
public class ButtonHandler implements ActionListener{//Generate field
public void actionPerformed(ActionEvent e){
String depthstr = depthtxt.getText();
String widthstr = widthtxt.getText();
int depth = Integer.parseInt(depthstr);
int width = Integer.parseInt(widthstr);
switch(version) {//Different specices simulation choosed by user
case 0:
Simulator.Simulator(depth,width);
break;
case 1:
SimulatorRF.SimulatorRF(depth,width);
break;
...
case 25:
SimulatorFWBH.SimulatorFWBH(depth,width);
break;
}
reset_butt.setEnabled(true);
nextstep_butt.setEnabled(true);
longstep_butt.setEnabled(true);
}
}
private class SimulateOption implements ActionListener{
public void actionPerformed(ActionEvent e){
switch(version) {
case 0:
if(e.getSource() == reset_butt){
Simulator.reset();
}
else if(e.getSource() == nextstep_butt){
Simulator.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
Simulator.runLongSimulation();
}
break;
case 1:
if(e.getSource() == reset_butt){
SimulatorRF.reset();
}
else if(e.getSource() == nextstep_butt){
SimulatorRF.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
SimulatorRF.runLongSimulation();
}
break;
...
case 25:
if(e.getSource() == reset_butt){
SimulatorFWBH.reset();
}
else if(e.getSource() == nextstep_butt){
SimulatorFWBH.simulateOneStep();
}
else if(e.getSource() == longstep_butt){
SimulatorFWBH.runLongSimulation();
}
break;
}
reset_butt.setEnabled(true);
nextstep_butt.setEnabled(true);
longstep_butt.setEnabled(true);
}
}
}
I might be bad at expressing questions... I'll try to improve my asking skill ...
Related
After doing a few small things i have decided to try my hand at a text based rpg. I am only using the console as i again am learning still. I am however at this point running into an issue i cant seem to get passed nor find any help on. I have my Game class which holds my main method as well as a few other classes one of which is my Player class. Within my Player class i have this:
public void playerControls(KeyEvent e)
{
int key = e.getKeyCode();
if (key == KeyEvent.VK_W)
{
System.out.println("Up");
}
if (key == KeyEvent.VK_A)
{
System.out.println("Left");
}
if (key == KeyEvent.VK_S)
{
System.out.println("Down");
}
if (key == KeyEvent.VK_D)
{
System.out.println("Right");
}
if (key == KeyEvent.VK_I)
{
System.out.println("Inventory");
}
if (key == KeyEvent.VK_O)
{
System.out.println("Options");
}
if (key == KeyEvent.VK_M)
{
System.out.println("Map");
}
if (key == KeyEvent.VK_C)
{
System.out.println("Character");
}
}
Then inside of my Game class i have within my main method:
//START OF GAME
do
{
player.playerControls(e);
validInput = true;
System.out.println("!!!!!!!!!!enter the intro story here!!!!!!!!!");
} while (gameRun);
}
The problem i am having is that i get an error saying e cannot be resolved to a variable when i run it as null i also throw errors. My question is how do I (like this/also "properly") call the playerControls from my players class into my Game class so that i can run the game and allow user input. Thank you for any answers. Have a great day :)
Instead of having your method require a KeyEvent you can just read the console input.
do {
String input = System.console().readLine();
//Change playerControls(KeyEvent e) to playerControls(String e)
player.playerControls(input);
validInput = true;
System.out.println("!!!!!!!!!!enter the intro story here!!!!!!!!!");
} while (gameRun);
Yes there is a way to do this with a single Char instead of a String, but it is not easy enough in my opinion for a starter.
Now you also would have to change your playerControls-method further:
public void playerControls(String e){
switch(e){
case "Up": system.out.println("Up");
break;
//Do so with all controls
}
Instead of the break which is to stop executing every following case(which will happen if you forget the break) you could use return;.
I have a JComboBox set up as shown below:
private String[] boxChoices = {"option 1", "option 2"};
JcomboBox box = new JCombobox(boxChoices);
box.addItemListener()
{
public void itemStateChanged(ItemEvent event)
{
int selection = box.getSelectedIndex();
switch (selection)
{
case 0: JOptionPane.showMessageDialog(null, "you have selected option 1");
break;
case 1: JOptionPane.showMessageDialog(null, "you have selected option 2");
break;
default: break;
}
}
}
My issue is that when I pick an option the message will be shown twice instead of once. For example if I choose Option 1 the following would appear:
you have selected option 1
you have selected option 1
What is causing this to happen?
In addition to #Blip's answer, you can also use actionListener. An actionEvent for JComboBox is only triggered once when you change a selection.
box.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
int selection = box.getSelectedIndex();
switch (selection) {
case 0:
JOptionPane.showMessageDialog(null, "you have selected option 1");
break;
case 1:
JOptionPane.showMessageDialog(null, "you have selected option 2");
break;
default:
break;
}
}
});
This behaviour occurs because Item listener is called 2 times because of selection of any item in the JComboBox. The first is called for deselection of previously selected item and the second time it is called for selection of the new item.
You can filter this by using a if clause to reflect the actual event you want to catch i.e. Selection or deselection :
if(event.getStateChange() == ItemEvent.SELECTED)
OR
if(event.getStateChange() == ItemEvent.DESELECTED)
based on your preference of choice of state change you want to trap.
I'm not sure but it could be because you're using an anonnymous listener.
Implement the ItemListener and add it.
I am making a very basic Java based RPG game with many of options as you go along and I want to make it so when you get the ability to type, if you press "x" it will automatically quit the game. I don't want to continuously add the "if-then" statement every time the user progresses.
What I don't want to do: (I would have to do this over 50 times for: inventory, quit game, character information and more)
switch (choice1)
{
case "x":
System.out.println("\nYou quit the game!");
System.exit(0);
break;
}
What I have: (Doesn't work)
import java.util.Scanner;
import java.awt.*;
import java.awt.event.*;
public class TheDungeon extends KeyAdapter
{
public void keyPressed(KeyEvent e) {
char ch = e.getKeyChar();
if (ch == 'a')
{
System.out.println("You pressed A");
}
}
public static void main(String[] args)
{
/* My variables...
*/
System.out.println("e: Check experience and level");
System.out.println("c: Character Information");
System.out.println("i: Inventory");
System.out.println("x: Quit Game");
choice1 = keyboard.nextLine();
switch (choice1)
{
case "x": //This section
System.out.println("\nYou quit the game!"); //here works
System.exit(0); //but I don't
break; //want to add this section
} //every time the user
//progresses.
To use KeyAdapters and/or KeyListeners you will need to construct a Gui in which to add these Adapters/Listners too.
The way you are currently reading in the users action is a valid way to do it for a console app.
Edit Extending on BlakeP's Answer if you have your determineAction method you could have a Map of the text your print out like so then you only need to add the special actions for the keys.
Map<Character, String> actionText = new HashMap<Character, String>();
actionText.put('x', "\nYou quit the game!");
actionText.put('i', "\nInventory Items:\n Things are here");
private void determineAction(char choice) {
System.out.println(actionText.get(choice));
switch (choice1)
{
case "x":
System.exit(0);
break;
}
}
Or you should have another method to do each special action, this will keep your switch shorter and easier to read. Like so
private void determineAction(char choice) {
System.out.println(actionText.get(choice));
switch (choice1)
{
case "x":
doExit();
break;
case "i":
printInventory();
break;
}
}
private void doExit()
{
System.out.println("\nYou quit the game!");
System.exit(0);
}
private void printInventory()
{
System.out.println("\nInventory Items:");
System.out.println("\n Things are here");
}
The KeyAdapter class is meant for GUI apps (notice the AWT package that it is in), and it sounds like you are doing just a console app. As far as I know, there is no "keypress" listener for console apps.
I would suggest putting the switch statement in a method such as "determineAction" and then return what you need (if anything).
Example method:
private void determineAction(char choice) {
switch (choice1)
{
case "x":
System.out.println("\nYou quit the game!");
System.exit(0);
break;
case "i":
System.out.println("\nInventory Items:");
System.out.println("\n Things are here");
break;
}
}
So after every time you ask for the choice, put this line --
determineAction(choice);
And it will run the switch statement without you having to copy it each time.
I am making a real time graph with values that come in via serial communication. I have the data coming in called my "Celsius" value. I am displaying that on the GUI in a JLabel, so the value constantly changes. The problem I am having is I want to have buttons that can change the value in the JLabel to Fahrenheit or back to Celsius. So right now, I have my actionPerformed calling the updateTemp() method so it will update the JLabel right away when the program beings. I have the code below for the 3 methods I think need to be changed around.
public void actionPerformed(final ActionEvent e) {
updateTempC();
final Double n = serial.x;
series.addOrUpdate(new Millisecond(), n);
Object source = e.getSource();
if (e.getSource() == buttonF){
degree.setText("degrees F");
updateTempF();
}
if (e.getSource() == buttonC){
degree.setText("degrees C");
updateTempC();
}
}
public void updateTempF(){
int step1;
int step2;
int step3;
String indata = serial.temp;
int temp = Integer.parseInt(indata);
step1 = temp*9;
step2 = step1/5;
step3 = step2 + 32;
String indata1 = Integer.toString(step3);
this.realtime.setText(indata1);
}
public void updateTempC(){
String indata = serial.temp;
this.realtime.setText(indata);
}
Right now when I press the JButton to change to Fahrenheit, it changes for a second but then goes right back to displaying Celsius because the graph is updated every second and the actionPerformed will go right back to calling the updateTempC(). I am wondering how, when I hit the button for Fahr. or Cels., it will change for the rest of the time. THanks
You should have a variable like boolean fahrenheitTemp. When buttonF is clicked, fahrenheitTemp will be set to true. When buttonC is clicked, fahrenheitTemp will be set to false. If fahrenheitTemp is true, call updateTempF(), else call updateTempC(). (Also, you have a Object source variable, but you never use it.)
Try modifying your actionPerformed(ActionEvent) to something like this:
boolean fahrenheitTemp = false;
public void actionPerformed(final ActionEvent e) {
if (fahrenheitTemp) {
updateTempF();
} else {
updateTempC();
}
final Double n = serial.x;
series.addOrUpdate(new Millisecond(), n);
Object source = e.getSource();
if (source == buttonF) {
degree.setText("degrees F");
fahrenheitTemp = true;
updateTempF();
} else if (source == buttonC) {
degree.setText("degrees C");
fahrenheitTemp = false;
updateTempC();
}
}
So this is my first time working with the JOptionPane and I was wondering if someone could help explain how I could make both of my buttons do certain actions? For all intent and purposes have it just print out "Hi". Here is my code. So far it only prints out "Hi" if I click the "Uhh...." button but I want it to do the same when I click the "w00t!!" button as well. I know it has something to do with the parameter "JOptionPane.YES_NO_OPTION" but I'm not sure what exactly I have to do with it. Thanks for the help in advance!
Object[] options = {"Uhh....", "w00t!!"};
int selection = winnerPopup.showOptionDialog(null,
"You got within 8 steps of the goal! You win!!",
"Congratulations!", JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE, null,
options, options[0]);
if(selection == JOptionPane.YES_NO_OPTION)
{
System.out.println("Hi");
}
From the javadocs,
When one of the showXxxDialog methods returns an integer, the
possible values are:
YES_OPTION
NO_OPTION
CANCEL_OPTION
OK_OPTION
CLOSED_OPTION
So, your code should look something like,
if(selection == JOptionPane.YES_OPTION){
System.out.println("Hi");
}
else if(selection == JOptionPane.NO_OPTION){
System.out.println("wOOt!!");
}
But regardless, this logic is a bit bizarre so I would probably just roll my own dialog.
In JOPtionPane class there are some constants that represent the values of the buttons.
/** Return value from class method if YES is chosen. */
public static final int YES_OPTION = 0;
/** Return value from class method if NO is chosen. */
public static final int NO_OPTION = 1;
/** Return value from class method if CANCEL is chosen. */
public static final int CANCEL_OPTION = 2;
You changed the names of the buttons, and consequently, your first button "Uhh" has the value 0, and its button "w00t!" assumed a value of 1.
So, you can use this:
if(selection == JOptionPane.YES_OPTION)
{
System.out.println("Hi");
}
else if(selection == JOptionPane.NO_OPTION){
// do stuff
}
or maybe could be better use the swicht/case function:
switch (selection )
{
case 0:
{
break;
}
case 1:
{
break;
}
default:
{
break;
}
}
int selection = 0;
JOptionPane.showOptionDialog(null,
"You got within 8 steps of the goal! You win!!",
"Congratulations!", JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE, null,
options, options[0]);
if(selection == JOptionPane.YES_NO_OPTION)
{
System.out.println("Hi");
}