JComboBox and ItemListener / ActionListener - java

I am creating a program for class where you have a JComboBox and when one option is selected it pops up a window with different options. I have one option that pops up a new window with two buttons on it.
First I'm not sure if I should be using ItemListener or ActionListener for the JComboBox options. Right now I have an ItemListener which I thought would work for just "The Matrix" option but it works for both options and I can't figure out why. I'll post all my code just in case but I'll add stars above and below the specified issue.
Thanks for any help or pointing me in the right direction!
public class MultiForm extends JFrame{
private JComboBox menu;
private JButton bluePill;
private JButton redPill;
private JLabel matrix;
private int matrixSelection;
private static String[] fileName = {"", "The Matrix", "Another Option"};
public MultiForm() {
super("Multi Form Program");
setLayout(new FlowLayout());
menu = new JComboBox(fileName);
add(menu);
*************************************************************************
TheHandler handler = new TheHandler();
menu.addItemListener(handler);
}
private class TheHandler implements ItemListener{
public void itemStateChanged(ItemEvent event) {
if(event.getStateChange() == ItemEvent.SELECTED) {
menu.setSelectedItem("The Matrix");
menu.getSelectedIndex();
*************************************************************************
//Create a new window when "The Matrix" is clicked in the JCB
JFrame newFrame = new JFrame();
JPanel panel = new JPanel();
newFrame.setLayout(new FlowLayout());
newFrame.setSize(500, 300);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
add(panel, BorderLayout.CENTER);
matrix = new JLabel("<html>After this, there is no turning back. "
+ "<br>You take the blue pill—the story ends, you wake up "
+ "<br>in your bed and believe whatever you want to believe."
+ "<br>You take the red pill—you stay in Wonderland, and I show"
+ "<br>you how deep the rabbit hole goes. Remember: all I'm "
+ "<br>offering is the truth. Nothing more.</html>");
newFrame.add(matrix, BorderLayout.NORTH);
Icon bp = new ImageIcon(getClass().getResource("Blue Pill.png"));
bluePill = new JButton("Blue Pill", bp);
newFrame.add(panel.add(bluePill));
Icon rp = new ImageIcon(getClass().getResource("Red Pill.png"));
redPill = new JButton("Red Pill", rp);
newFrame.add(panel.add(redPill));
newFrame.setVisible(true);
}
}
}
public static void main(String[] args) {
MultiForm go = new MultiForm();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(400, 200);
go.setVisible(true);
}
}

ItemListener and ActionListener will tell when something about the combo box has changed. You then need to ascertain WHAT has changed and take appropriate action
For example...
private class TheHandler implements ItemListener{
public void itemStateChanged(ItemEvent event) {
if(event.getStateChange() == ItemEvent.SELECTED) {
Object source = event.getSource();
if (source instanceof JComboBox) {
JComboBox cb = (JComboBox)source;
Object selectedItem = cb.getSelectedItem();
if ("The Matrix".equals(selectedItem)) {
// Do the matrix
} else if ("Another Option".equals(selectedItem)) {
// Do another option
}
}
}
}
}
This simply checks what the selectedItem is and takes appropriate action according to what is selected. You could also use selectedIndex instead, which will return a int representing the selected item, but which ever is easier for you.
Have a look at How to Use Combo Boxes for more details
If all you want to know is when a item is selected, you might find a ActionListener simpler, as you don't need to check the state (SELECTED/UNSELECTED), as it only triggers on the selected state change

Related

ListSelectionListener does not fire events when calling setSelected methods

First question here, hopefully I do this correctly.
Below is a minimal example of my problem that I quickly whipped up representative of my project. I have created a custom renderer for a JList containing some objects (in the example I've used Strings for illustrative purposes). My issue is that, as far as I can tell, if I add a ListSelectionListener to the list, the family of setSelected...() methods do not fire events that trigger the conditional if(e.getValueIsAdjusting()).
In the example below, the problem is immediately obvious upon starting the program: even though list.setSelectedIndex(2); is called after assigning the JLabel's selected text as "none", it does not change until you, the user, click the list items. In fact, it must be a different item to the one currently selected.
I would like this functionality so that the flow of my program will be that, after a user adds/removes items from the list, the "view" is immediately updated once the selected list item is changed.
Have I done something wrong, or am I approaching this incorrectly?
Thank you. :)
import java.awt.BorderLayout;
import java.beans.*;
import javax.swing.*;
public class Example implements PropertyChangeListener {
String ITEM_SELECTED = "Item Selected";
String DELETE_SELECTED = "Delete Selected";
PropertyChangeSupport pcs = new PropertyChangeSupport(this);
JLabel selected;
JList<String> list;
DefaultListModel<String> model;
public static void main(String[] args) {
new Example();
}
public Example() {
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel(new BorderLayout());
model = new DefaultListModel<>();
model.addElement("Entry 1");
model.addElement("Entry 2");
model.addElement("Entry 3");
model.addElement("Entry 4");
model.addElement("Entry 5");
list = new JList<>(model);
selected = new JLabel("Currently selected: none");
list.setSelectedIndex(2);
list.addListSelectionListener(e -> {
if(e.getValueIsAdjusting()) {
pcs.firePropertyChange(ITEM_SELECTED, null, null);
}
}
);
JButton removeItem = new JButton("Remove item");
removeItem.addActionListener(e -> {
pcs.firePropertyChange(DELETE_SELECTED, null, null);
}
);
mainPanel.add(new JScrollPane(list), BorderLayout.WEST);
mainPanel.add(removeItem, BorderLayout.NORTH);
mainPanel.add(selected, BorderLayout.CENTER);
pcs.addPropertyChangeListener(this);
frame.add(mainPanel);
frame.setSize(300, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
String event = (String) evt.getPropertyName();
if (event.equals(ITEM_SELECTED)) {
selected.setText("Currently selected: " + list.getSelectedValue());
}
if (event.equals(DELETE_SELECTED)) {
int selectedIndex = list.getSelectedIndex();
model.removeElement(list.getSelectedValue());
if (selectedIndex > 0)
list.setSelectedIndex(selectedIndex-1);
else if (selectedIndex == 0)
list.setSelectedIndex(selectedIndex);
}
}
}
The e.getValueIsAdjusting() method checks if the value is still being adjusted. In your case it looks like the event fired by list.setSelectedIndex(2) would have e.getValueIsAdjusting() return false.
You can probably fix this by doing the opposite check : !e.getValueIsAdjusting().
This will then check that any change responded to is the final one for that chain of events.

using listeners with both list and button

Very new to Java, but I am slowly picking my way through things. So please be kind. I understand most things I've tried so far, and built a version of the following that uses console output, but now I'm trying to make a GUI. I tried the netbeans GUI maker, but it created so much new code that when I tried to pick through it, I got lost. I'm much better at learning by piecing new things together myself, not having an IDE generate a ton of code and then attempt to find where I want to work.
I am trying to build an window that has a list with three choices on the left side, a button in the middle that confirms your choice, and an answer output on the right. Once the button is pressed, the input from the list is read and is converted into a corresponding answer. As of right now, all I get is "We recommend... null" after selecting an option in the list. The button appears to do nothing at the moment.
I have used tutorials, hacked up others' code from online, and referenced a few books, but I'm stuck.
Here is what I have:
package diffguidegui;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class DiffGuideGUI extends JPanel implements ListSelectionListener {
private JList resultsTabList;
private DefaultListModel listModel;
private static final String recommendString = "Recommend a Option";
private JButton recommendButton;
private String recommendOutput;
final JLabel output = new JLabel("We recommend..." + recommendOutput);
//build list
public DiffGuideGUI () {
super(new BorderLayout());
listModel = new DefaultListModel();
listModel.addElement("A");
listModel.addElement("B");
//create the list and put it in the scroll pane
resultsTabList = new JList(listModel);
resultsTabList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
resultsTabList.setSelectedIndex(0);
//listener for user input
resultsTabList.addListSelectionListener(this);
resultsTabList.setVisibleRowCount(2);
JScrollPane listScrollPane = new JScrollPane(resultsTabList);
//build the button at the bottom to fire overall behavior
recommendButton = new JButton(recommendString);
recommendButton.setActionCommand(recommendString);
recommendButton.addActionListener(new RecommendListener());
//create a panel that uses Boxlayout for the button
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.add(recommendButton);
//create a panel that uses Boxlayout for the label
JPanel outputPane = new JPanel();
outputPane.setLayout(new BoxLayout(outputPane, BoxLayout.LINE_AXIS));
outputPane.add(output);
add(listScrollPane, BorderLayout.WEST);
add(buttonPane, BorderLayout.CENTER);
add(outputPane, BorderLayout.EAST);
}
//build listener class
class RecommendListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//build in logic for choice made here
String resultsTabChoice;
resultsTabChoice = (String)resultsTabList.getSelectedValue();
if( resultsTabChoice.equals("A")) {
recommendOutput = "One";}
else {recommendOutput = "Two";}
}
}
public void valueChanged(ListSelectionEvent e) {
if(e.getValueIsAdjusting() == false) {
if(resultsTabList.getSelectedIndex() == -1) {
recommendButton.setEnabled(false);
} else {
recommendButton.setEnabled(true);
}
}
}
//Create GUI and show it
private static void createAndShowGUI() {
JFrame frame = new JFrame("Recommend Window");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create and set up content pane
JComponent newContentPane = new DiffGuideGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
//display the window
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
The button appears to do nothing at the moment.
It does something. It calculates the value for your recommendOutput varable. But you never output this value.
try the following:
//build listener class
class RecommendListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//build in logic for choice made here
String resultsTabChoice;
resultsTabChoice = (String)resultsTabList.getSelectedValue();
if( resultsTabChoice.equals("A")) {
recommendOutput = "One";}
else {recommendOutput = "Two";}
System.out.println(recommendOutput); // <-###################
}
}
This should print the value to stdout
To put the value into your label try this instead:
output.setText(recommendOutput);
where do you set the text for the JLabel? It says "We recommend NULL" because recommenedOutput is null when the object is created. I dont see
output.setText("We recommend "+value) anywhere. You probably need output.invalidate() also. Try putting setText(String text)/invalidate() in the RecommendListener.actionPerformed() method.
output.setText("We recommend A");
output.invalidate();

trouble in JComboBox

hello i am confused in reading values from JComboBox. I want a program that if user click and select any item from JComboBox. It will appear as output. example i choose apple it will appear apple the main problem of this is i have no button of my program so i really need it to click then output here is my code so far .
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class imagebut extends JFrame
{
ImageIcon we = new ImageIcon(getClass().getResource("ban.png"));
ImageIcon wer = new ImageIcon(getClass().getResource("ba.png"));
public static void main(String args [])
{
imagebut w = new imagebut();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
w.setSize(300,300);
w.setVisible(true);
}
String []kwe = {"Convertion","Adv.Calculator","Looping","Remarks","Average","MagicSquare","Calendar","Multiplication"};
JComboBox box = new JComboBox(kwe);
public imagebut()
{
/* JButton converter = new JButton("Convertion");
JButton advancecalc = new JButton("Adv.Calculator");
JButton calc = new JButton("Calculator");
JButton Multiplication = new JButton("Multiplication");
JButton Looping = new JButton("Looping");
JButton Calendar = new JButton("Calendar");
JButton Remarks = new JButton("Remarks");
JButton Average = new JButton("Average");
JButton Magicsq = new JButton("Magic Square");*/
JLabel background = new JLabel(new ImageIcon(getClass().getResource("gif.gif")));
JPanel pan = new JPanel();
box.setBounds(10,10,150,25);
getContentPane().add(background);
background.add(box);
/* background.add(converter);
background.add(calc);
background.add(advancecalc);
background.add(Magicsq);
background.add(Remarks);
background.add(Calendar);
background.add(Average);
background.add(Looping);
background.add(Multiplication);*/
}
}
this is my update so example if i click convertion it will make an Frame for Convertion if Average another frame .
Add ActionListener to your JComboBox component and to like:
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
System.out.println(jComboBox1.getSelectedItem().toString());
}
this will get the selected item from your combo box, it will triggers every item you select from combobox
Seems you need to use ItemListener, for example:
JComboBox box = new JComboBox(kwe);
box.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED){
System.out.println(((JComboBox)e.getSource()).getSelectedItem());
// other actions
}
}
});

Button ActionListener runs both combo box choices at the same time why?

Hello I have a problem with my comboBox. In app that im making my panel has a combo box with two choices and a button next to the combo box to proceed to the choice selected in the combo box but instead both if Statements run and no I have no idea why.
Combo box code is simple private JComboBox mainChoice = new JComboBox();
mainChoice.addItem("") etc...
class mainPanelGoButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
String choice = (String)mainChoice.getSelectedItem();
System.out.printf(choice);
if(choice == "View Passenger Details");
{
JTextField first = new JTextField();
JTextField last = new JTextField();
Object[] message = {
"First Name:", first,
"Last Name:", last
};
int option = JOptionPane.showConfirmDialog(null, message, "Enter passenger name", JOptionPane.PLAIN_MESSAGE);
if (option == JOptionPane.OK_OPTION)
{
// Load passenger data
p = dataHandler.getPassengerData(first.getText(), last.getText());
if(p != null)
{
updateTextfields( p);
// Display passenger data
getContentPane().removeAll();
getContentPane().add(passengerDetailsPanel);
setSize(400,340);
setLocationRelativeTo(null);
validate();
repaint();
printAll(getGraphics());
}
}
}
if(choice == "Add New Passenger")
{
if(displayPassengerInputForm());
{
// Display passenger data
getContentPane().removeAll();
getContentPane().add(passengerDetailsPanel);
setSize(400,340);
setLocationRelativeTo(null);
validate();
repaint();
printAll(getGraphics());
}
}
}
}
// EXAMPLE OF MY PROGRAM THAT RETURNS BOTH WINDOW A and WINDOW B
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Frame extends JFrame
{
private JPanel mainPanel = new JPanel();
private JComboBox<String> mainChoice = new JComboBox<String>();
private JButton goButton = new JButton("GO");
public Frame()
{
createMainPanel();
this.add(mainPanel);
}
private void createMainPanel()
{
// Fill choice box
mainChoice.addItem("Find Passenger");
mainChoice.addItem("Add New Passenger");
// Set button
goButton.addActionListener(new mainPanelGoButtonListener());
goButton.setPreferredSize(new Dimension(5,5));
// Add to main panel
mainPanel.setLayout(new GridLayout(1,2,4,4));
mainPanel.add(mainChoice);
mainPanel.add(goButton);
}
class mainPanelGoButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
if(mainChoice.getSelectedItem().equals("Find Passenger"));
{
// DISPLAYS WINDOW FOR INPUT
System.out.printf(" WINDOW A ");
}
if(mainChoice.getSelectedItem().equals("Add New Passenger"));
{
// DISPLAYS WINDOW FOR INPUT
System.out.printf(" WINDOW B ");
}
}
}
public static void main(String args[])
{
Frame frame = new Frame();
frame.setTitle("SSD Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400,50);
frame.setVisible(true);
}
}
Each time I press a button it prints out both Window A and Window B instead of one
One problem I see is that you use == to compare Strings.
Don't use == to compare Strings as this compares if two String objects are the same, something that you are not interested in testing. Use the equals(...) or equalsIgnoreCase(...) method which tests if two Strings contain the same characters, in the same order, with or without the same case respectively, and this is what you are really interested in.
Next: be sure you use if (something) { xxxx } else if (somethingElse) { xxxx } to be sure that only one if block gets performed.
Next: look up the CardLayout which will allow your GUI to change views much more cleanly.
Edit
You ask:
do you mean: mainChoice.getSelectedItem().equals("Add New Passenger") ?? cause im still getting the same result ;
Yes, exactly. But on further reflection, your code above cannot be causing both if blocks to fire as the String == can't be true for both test Strings. Something else is causing your problem.
could you give me some quick example?
Actually it would be better if you could create and post a minimal runnable program that reproduces your problem for us.

Multiple JLabel MouseListeners

I'm trying to add several JLabels to a JPanel along with mouse listeners using a loop. These JLabels are going to have mouse listeners so that they change their icon when clicked (Using label.setIcon()). However, I only want to have one "selected" at a time. So, I need them to know when another label is clicked so it knows to turn itself off before the new label gets selected. However, my problem is that because I'm adding these labels with a loop they all have the same MouseListener.
Can anyone teach me a simple way to accomplish this?
This is a short example, how you could implement it (please note, that I didn't use the icon, but change the label instead):
public class MouseListenerExample extends JFrame {
public static class MyMouseListener extends MouseAdapter {
private static final Collection<JLabel> labels = new ArrayList<JLabel>();
private final JFrame frame;
public MyMouseListener(JFrame frame, JLabel label) {
this.frame = frame;
labels.add(label);
}
#Override
public void mouseClicked(MouseEvent e) {
for (JLabel label : labels) {
String text = label.getText();
if (text.startsWith("X ")) {
label.setText(text.substring(2));
}
}
JLabel currentLabel = (JLabel) e.getComponent();
currentLabel.setText("X " + currentLabel.getText());
}
}
public MouseListenerExample() {
super("MouseListener Example");
Container c = getContentPane();
c.setLayout(new FlowLayout());
for (int i = 0; i < 10; i++) {
JLabel jLabel = new JLabel("Label " + i);
c.add(jLabel);
jLabel.addMouseListener(new MyMouseListener(this, jLabel));
}
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new MouseListenerExample();
}
}
The main idea is, that you create a new MouseListener for each label, but keep a list of labels outside of each listener's scope (in this example I just use a static variable, but you could also have a field containing the list of labels in the frame.

Categories