Using a switch statement for a JComboBox - java

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.

Related

Java predator-prey simulation with GUI can't run simulation properly

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 ...

Show previous text even after click event on Android

Here is my image button Click action below.
It will show "1 null" after clicked, while holding the button it shows rightAnswer. I want to illustrate the saved string of questionLabel after finishing the holding button.
What I want to do is that define "sharedFact" before Action_down happens and keep that text to show after the user button untouched.
The "rightAnswer" should be only shown while the user holding imageButton
I tried to use normal String text like "test", it works, however String sharedFact = questionLabel.getText().toString();
↑ is not working like what I thought, what is the problem and how to fix?
findViewById(R.id.image_button_check).setOnTouchListener((v, event) -> {
String sharedFact = null;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
sharedFact = questionLabel.getText().toString();
questionLabel.setText(rightAnswer);
break;
case MotionEvent.ACTION_UP:
//Here is only test "1" is for identify this code is working
//How can I save questionLabel Text before action down but inside click action?
questionLabel.setText(1 + sharedFact);
break;
}
return false;
});
move your definition from inside the function to a class data member.
String sharedFact = null;
onCreate(){
// your code
findViewById(R.id.image_button_check).setOnTouchListener((v, event) -> {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
sharedFact = questionLabel.getText().toString();
questionLabel.setText(rightAnswer);
break;
case MotionEvent.ACTION_UP:
//Here is only test "1" is for identify this code is working
//How can I save questionLabel Text before action down but inside click action?
questionLabel.setText(1 + sharedFact);
sharedFact = null
break;
}
return false;
});
}

How do I make a selected Combobox value display different text?

I am new to Java and couldn't find any answers for my problem that I was able to understand.
I want to make a selected value in my ComboBox change what text is displayed in the textfield.
For example, if the user selects an artist in the combobox, then the artists' albums are displayed in the textfield.
Any help is appreciated. Thanks!
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
String a = (String)jComboBox1.getSelectedItem();
int artists = 0;
switch (artists){
case 0: jTextField1.setText("Take Care, Nothing Was The Same, Views, More Life, Scorpion");
break;
case 1: jTextField1.setText("Stoney, Beerbongs & Bentleys");
break;
case 2: jTextField1.setText("One Love, Listen, Nothing But the Beat");
break;
case 3: jTextField1.setText("Ready for the Weekend, 18 Months, Motion");
break;
case 4: jTextField1.setText("Cole World: The Sideline Story, 2014 Forest Hills Drive, 4 Your Eyez Only");
break;
case 5: jTextField1.setText("My Beautiful Dark Twisted Fantasy, Yeezus, The Life of Pablo, ye");
break;
case 6: jTextField1.setText("Parachutes, a Rush of Blood to the Head, X&Y, Viva La Vida, Mylo Xyloto");
}
}
Here is a full working example:
import java.awt.GridLayout;
import javax.swing.*;
public class ChangeTextViaCheckbox extends JFrame {
public ChangeTextViaCheckbox() {
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridLayout(3, 1));
JCheckBox cb1 = new JCheckBox("Checkbox 1");
JCheckBox cb2 = new JCheckBox("Checkbox 2");
JTextField tf = new JTextField();
cb1.addActionListener(e -> tf.setText("CB 1 is active"));
cb2.addActionListener(e -> tf.setText("CB 2 is active"));
add(cb1);
add(cb2);
add(tf);
}
public static void main(String[] args) {
ChangeTextViaCheckbox frame = new ChangeTextViaCheckbox();
frame.pack();
}
}
The both ActionListener listen on a performed action. If thats the case, they set a new Text in the JTextField.
But it would be better, if you implement it via JRadioButton and a ButtonGroup. With this there can't be a multiple choice.
Your question is lacking details and examples, you should post the important parts of your code that you've already written, for example I have no idea now what [GUI] API are you using(for example swing or AWT), so I strongly advise you to edit your question and provide more details, but either way I'm going to give you a simple example.
I'm going to assume your using the swing api, but it shouldn't be that different if your using another GUI api (like AWT).
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SwingExample extends JFrame{
public SwingExample(){
String[] artists = {"artist1","artist2","artist3"};
Map<String,String> albumOfArtists = new HashMap<String,String>();
albumOfArtists.put("artist1","album1");
albumOfArtists.put("artist2","album2");
albumOfArtists.put("artist3","album3");
JComboBox combo1 = new JComboBox<String>(artists);
JTextField field1 = new JTextField();
//You implement an action listener to define what should be done when
//an user performs certain operation. An action event occurs,
//whenever an action is performed by the user. Examples: When the user
//clicks a button, chooses a menu item, presses Enter in a text field.
//add action listener to your combobox:
combo1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String selectedString=(String)combo1.getSelectedItem();
field1.setText(albumOfArtists.get(selectedString));
//for example if you select artist1 then the text displayed in the text field is: album1
}
}
add(combo1);
add(field1);
}
private static void createAndShowGUI() {
JFrame frame = new CreateNewJTextField();
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
createAndShowGUI();
}
}
You can use switch() for your combobox. I've written a code which has the name defined to combobox as cb1. The getSelectedItem() method is used for cb1. You can define the corresponding command for each case (starting from index 0).
String a = (String)cb1.getSelectedItem();
int i = 0;
switch (i){
case 0:
break;
}
Make sure to end each case with break; or your code will execute repeatedly.
Now if the textfield you're using is t1 then the following code is generalised,
switch (i) {
case 0: t1.setText(<whatever you want to display>);
break;
}
Hope this helps.
Here's the revisited code:
String a = (String)cb1.getSelectedItem();
int i = 0;
switch(i){
case 0: t1.setText("Take Care, Nothing Was The Same, Views, More Life, Scorpion");
// for combobox option Drake index = 0
break;
case 1: t1.setText("Stoney, Beerbongs & Bentleys");
// for combobox option post_malone index = 1
break;
case 2: t1.setText("One Love, Listen, Nothing But the Beat");
// for combobox option david_guetta
break;
}
switch is a selection statement that successively tests the value of an expression against alist of integers or characters constants. When a match is found, the statements associated with that constant are executed. Here, the variable i is the expression(the option you choose from combobox) which is evaluated.
Hope this helps again!

How do I go back to the main menu from a sub menu using JOptionPane when the user clicks cancel?

I'm making a method wherein it has several choices and each of those choices , once selected, need to have the "cancel" button go back to the main menu.
Main Menu:
public static void start(){
String[] choices = {"1. Routines for Triangles","2. Routines for Temperatures","3. Routines for Geometric Figures","4. String Manipulations",
"5. Miscellaneous Simple Games.","6. Quit"};
String menu = (String) JOptionPane.showInputDialog(null,"choose","Main menu",JOptionPane.QUESTION_MESSAGE,null,choices,choices[0])
while (menu != null){
switch (menu){
case "1. Routines for Triangles":
triangleRoutines(); //one sub menu
break;
case "2. Routines for Temperatures":
break;
case "3. Routines for Geometric Figures":
break;
case "4. String Manipulations":
break;
case "5. Miscellaneous Simple Games.":
break;
case "6. Quit":
break;
}
}
}
A sub menu:
private static void triangleRoutines(){
String[] stringArray = {"Determine the Type of Triangle", "Determine a Valid Triangle", "Determine the Area of the Sides of a Triangle", "Determine a Pythagorean Triple",
};
String reply = (String) JOptionPane.showInputDialog(null, "Choose what you want to do today", "Triangle Processes", JOptionPane.QUESTION_MESSAGE,
null, stringArray, stringArray[0]);
switch (reply){
case "Determine the Type of Triangle":
break;
case "Determine a Valid Triangle":
break;
case "Determine the Area of the Sides of a Triangle":
break;
case "Determine a Pythagorean Triple":
break;
}
}
When a JOptionPane.showInputDialog() dialog is Canceled or Closed without a selection being made then a null is returned. you need to handle this null and act upon it accordingly but you will need to decide what you want to do when it does happen. Close the application, re-display the Main Menu dialog and force the Quit menu option to be selected, etc.
To always keep your Main Menu available place it within the while loop, for example:
String[] choices = {"1. Routines for Triangles", "2. Routines for Temperatures",
"3. Routines for Geometric Figures", "4. String Manipulations",
"5. Miscellaneous Simple Games.", "6. Quit"};
String menu = "";
while (!menu.equals("6. Quit")) {
menu = (String) JOptionPane.showInputDialog(null, "<html>Choose A Menu Item:<br><br></html>", "Main Menu",
JOptionPane.QUESTION_MESSAGE, null, choices, choices[0]);
if (menu == null) {
//continue; //uncomment and delete line below to force menu item 6 to be selected to quit Main Menu.
break; //Quit the Main Menu
}
switch (menu) {
case "1. Routines for Triangles":
triangleRoutines(); //one sub menu
break;
case "2. Routines for Temperatures":
break;
case "3. Routines for Geometric Figures":
break;
case "4. String Manipulations":
break;
case "5. Miscellaneous Simple Games.":
break;
case "6. Quit":
// This case is not really required unless you want to
// do some cleanup of sorts before quiting.
break;
}
}
Utilize the same technique for your methods which contain sub-menus but add a menu option to: Return To Main Menu and perhaps one more additional option to: Quit Application if desired.
The best approach would be to implement the Command design pattern.
However, if the point is that the triangleRoutines needs to return to the previous menu, then given the overall current approach, I think making a modification on where the menu is presented would work. I'm not positive that is the OP's question, but I believe so.
See the comments in the example code for additional details.
Not tested, but something like:
private static void triangleRoutines() {
...
// if the program is done, can return null
// if cancel, then return anything but null
return "";
}
Then
do {
// get the menu from the top level
String menu = (String) JOptionPane.showInputDialog(null,"choose","Main menu",JOptionPane.QUESTION_MESSAGE,null,choices,choices[0])
switch (menu){
case "1. Routines for Triangles":
// if cancel, then will return empty string, and then
// re-present the main menu
triangleRoutines(); //one sub menu
break;
...
case "6. Quit":
menu = null;
break;
} //switch
} while (menu != null);
Thus, in the triangleRoutines() one can "cancel" and it will return an empty String, which is not null, so it will present the top level menu again. If one wants to exit from the submenu triangleRoutines() then return null, and the program will exit.
Again, I might have misunderstood the specific question.

Using jcombobox to return object or variable

I have 2 comboboxes and I need to make it so that when certain options are selected from the drop down list, certain results are outputted. How do I associate certain string variables or objects with multiple combobox selections. I'm not asking you to do my homework for me. Just need pointing in the right direction.
public class gui extends JFrame implements ActionListener{
String[] colour1 = {"red", "blue", "green", "orange", "brown","white", "black", "yellow", "purple", "pink"};
String[] colour2 = {"red", "blue", "green", "orange", "brown","white", "black", "yellow", "purple", "pink"};
JComboBox combo1 = new JComboBox(colour1);
JComboBox combo2 = new JComboBox(colour2);
JLabel message = new JLabel();
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridLayout(0, 1));
public gui() {
panel.add(combo1);
panel.add(combo2);
panel.add(message);
frame.add(panel);
}
I'm using actionPerformed to catch the users input, and then output specific results. At the moment it only takes the value of one combobox and outputs a string. How do i make it take 2.
public void actionPerformed(ActionEvent e){
if(e.getSource() == combo1){
JCombobox cb = (JComboBox)e.getSource();
String colours = (String) cb.getSelectedItem();
switch(colours){
case "red": message.setText("");
break;
case "blue": message.setText("");
break;
case "green": message.setText("");
break;
case "pink": message.setText("");
break;
case "purple":message.setText("");
break;
case "white": message.setText("");
break;
case "black": message.setText("");
break;
case "brown": message.setText("");
break;
case "orange": message.setText("");
break;
case "yellow": message.setText("");
break;
default: message.setText("");
}
}
}
As it was pointed out in the comments, you probably don't need both arrays. When both combo boxes should contain the same values, then you can pass the same array to both combo boxes.
The actual question seems to be aiming at how to perform a specific action depending on the combination of the selections of two combo boxes.
I think there are two options for this: You could either store the combo boxes as instance variables, or you could store the selections of the combo boxes as instance variables. Since you're already storing the combo boxes as instance variables, this should be the easier one to go here. So you could do something like this:
#Override
public void actionPerformed(ActionEvent e)
{
String color1 = (String)combo1.getSelectedItem();
String color2 = (String)combo2.getSelectedItem();
// Possibly check if either color is 'null' here
if (color1.equals("blue") && color2.equals("yellow"))
{
message.setText("green");
}
...
}
(Note: If you now intend to write a nested switch-statement like
switch(colour1)
{
case "red":
switch(colour2)
{
// 10 cases...
}
break;
// 10 x 10 cases...
}
you should think about a different approach, depending on what you want to do with these colors...)
What you want is display a Value depending on the selected Values of the two comboboxes. Make combo1 and combo2 private fields. Write a private method to respond to the action event of both combo. Switch on combo values. Note that you can access both combo directly because they are class fields

Categories

Resources