ComboBox not listening to events - java

This application shows a frame that contains different JComboBoxes and a JLabel.
An event should be generated when the user clicks the last one(style combobox) and the text in the JLabel should be formatted according to the selected choices in each combobox.
When I click on the Style combobox nothing happens.
There's also another error that I couldn't figure out:(
OUTPUT
package labtasksix;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MyFrame extends JFrame {
String NameO []= {"Select name:","TimesRoman","Serif","SansSerif","Monospaced"};
String ColorO[]={"Select color:","RED","BLUE","GREEN"};
String SizeO []={"Select size:","8","12","16","20"};
String StyleO[]={"Select style:","BOLD","ITALIC","PLAIN"};
JLabel lbl= new JLabel("Text Formatted");
JComboBox Name= new JComboBox(NameO);
JComboBox Colour= new JComboBox(ColorO);
JComboBox Size= new JComboBox(SizeO);
JComboBox Style= new JComboBox(StyleO);
public MyFrame() {
super("Format Frame");
setLayout(new FlowLayout());
add(Name);
add(Size);
add(Style);
add(Colour);
add(lbl);
Name.setMaximumRowCount(3);
Size.setMaximumRowCount(3);
Style.setMaximumRowCount(3);
Colour.setMaximumRowCount(3);
EventHandler handler= new EventHandler();
Style.addItemListener(handler);
}
class EventHandler implements ItemListener{
#Override
public void itemStateChanged(ItemEvent e) {
//When user chooses from the last combobox (style)
if(e.getSource()==Style)
{
if(Name.getSelectedItem().equals("BOLD"))
{
lbl.setFont(new Font((String)Name.getSelectedItem(),Font.BOLD, (int) Size.getSelectedItem()));
}
if(Name.getSelectedItem().equals("ITALIC"))
{
lbl.setFont(new Font((String)Name.getSelectedItem(),Font.ITALIC, (int) Size.getSelectedItem()));
}
if(Name.getSelectedItem().equals("PLAIN"))
{
lbl.setFont(new Font((String)Name.getSelectedItem(),Font.PLAIN, (int) Size.getSelectedItem()));
}
if(Colour.getSelectedItem().equals("RED"))
{
lbl.setForeground(Color.red);
}
if(Colour.getSelectedItem().equals("BLUE"))
{
lbl.setForeground(Color.BLUE);
}
if(Colour.getSelectedItem().equals("GREEN"))
{
lbl.setForeground(Color.GREEN);
}
}
}
}
}

It is listening, but you're checking the ComboBox.getSelectedItem(), which hasn't been updated at the time the event is fired. The item the event relates to is referenced in the event itself; call e.getItem() to retrieve it:
Object item = e.getItem();
if (item.equals("BOLD")) {
lbl.setFont(new Font((String) item, Font.BOLD, /* wrong: (int) Size.getSelectedItem() */ 8));
}
Your size calculation (commented above) is wrong too. Your size selection box holds Strings, so you'll have to parse them (or change the model to ints).
Also... you'll get two events for each change, ItemEvent.DESELECTED first (for the old item), then ItemEvent.SELECTED. You should check for the event you're interested in:
if (e.getSource() == Style && e.getStateChange() == ItemEvent.SELECTED) {

Related

Possible to detect double click on a JComboBox item?

I have a question for school that states I should change the background color of my JFrame when "an item in the JComboBox is double clicked".
Is this possible using an ItemListener or ActionListener? Or would I need to implement using a MouseListener?
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class ColorSelection extends JFrame {
String[] colorNames = {
"Black", "Blue"
};
Color colors[] = {
Color.BLACK, Color.BLUE
};
JComboBox coloursComboBox = new JComboBox(colorNames);
ColorItemListener colorItemListener = new ColorItemListener(this);
public ColorSelection() {
super("My color combobox");
coloursComboBox.addItemListener(colorItemListener);
add(coloursComboBox, BorderLayout.NORTH);
setSize(600, 600);
setVisible(true);
}
public class ColorItemListener implements ItemListener {
ColorSelection colorSelection;
public ColorItemListener(ColorSelection colorSelection) {
this.colorSelection = colorSelection;
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (e.getItem().toString().equals("Black")) {
colorSelection.getContentPane().setBackground(Color.BLACK);
} else {
colorSelection.getContentPane().setBackground(Color.BLUE);
}
}
}
}
public static void main(String[] args) {
new ColorSelection();
}
}
Don't know if it is possible because the popup of the checkbox is closed after a single mouse click.
However, if it is possible, I would suggest you would need to add a MouseListener to the JList that has been added to the popup of the combo box.
After creating the combo box you can add a MouseListener to the JList with code like:
JComboBox comboBox = new JComboBox(...);
Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
if (child instanceof BasicComboPopup)
{
BasicComboPopup popup = (BasicComboPopup)child;
JList list = popup.getList();
list.addMouseListener(...);
}

ActionPerformed being called when JComboBox is clicked in Jtable cell

I am using JComboBox in Jtable cell. When I click on the JComboBox and select a value from it, it calls the ActionPerformed fuction. Till here it is working fine but as soon as I click on the JComboBox again, it calls the ActionPerformed function, which it should not. What I want is, to call the ActionPerformed function when the item is selected in the JComboBox. In other words it should work as it worked for the first time when the item was selected from the JComboBox and then the ActionPerformed function was called. I cannot figure out why this problem is occurring. Here are the links that I have looked into and I did some other searches also but still could not find any relative answer to the above mentioned problem.
Adding JComboBox to a JTable cell
How to use ActionListener on a ComboBox to give a variable a value
https://coderanch.com/t/339842/java/ComboBox-ItemListener-calling
Here is the code, you can copy paste it and check it.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
public class TableExample implements ActionListener{
JFrame frame;
JComboBox skuNameComboBoxTable;
TableExample() {
frame = new JFrame();
String data[][] = {{"101", "Amit", "Choose"},
{"102", "Jai", "Choose"},
{"101", "Sachin", "Choose"}};
String column[] = {"ID", "Name", "Degree"};
JTable table = new JTable(data, column);
table.setBounds(30, 40, 200, 300);
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane);
frame.setSize(300, 400);
frame.setVisible(true);
String[] array = {"BS(SE)", "BS(CS)", "BS(IT)"};
skuNameComboBoxTable = new JComboBox(array);
skuNameComboBoxTable.addActionListener(this);
TableColumn col = table.getColumnModel().getColumn(2);
col.setCellEditor(new DefaultCellEditor(skuNameComboBoxTable));
}
public static void main(String[] args) {
new TableExample();
}
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "actionPerformed called");
}
}
Kindly tell me why this problem is occurring and how should I solve it.
Unfortunately, you can't do much when using the DefaultCellEditor - that is how it behaves. Within your code you can add a check to ensure that a change in value occured before handling the event. Something like below:
public void actionPerformed(ActionEvent e) {
if (skuNameSelected == null || skuNameComboBoxTable.getSelectedItem() != skuNameSelected)
JOptionPane.showMessageDialog(null, "actionPerformed called: ");
skuNameSelected = (String) skuNameComboBoxTable.getSelectedItem();
}
You can try using ItemListener and filter your action according to the ItemEvent.
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class JComboBoxTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] items = {"One", "Two", "Three"};
JComboBox cb = new JComboBox(items);
cb.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println("Selected " + e.getItem());
} else {
System.out.println("Deselected " + e.getItem());
}
}
});
frame.add(cb);
frame.pack();
frame.setVisible(true);
}
}
This is happening because you are using the same JComboBox as the DefaultCellEditor for column 2.
Whenever you click a cell from column 2 the ComboBox will change to the value that is on the cell at the moment and that triggers the DESELECT (from the old value) and the SELECT (for the new value). This will only happen if the old value and the new value are not the same.
One way to avoid this is to add a CellEditorListener on the DefaultCellEditor that you are using, like below:
TableColumn col = table.getColumnModel().getColumn(2);
DefaultCellEditor cellEditor = new DefaultCellEditor(skuNameComboBoxTable);
col.setCellEditor(cellEditor);
cellEditor.addCellEditorListener(new CellEditorListener() {
#Override
public void editingStopped(ChangeEvent e) {
System.out.println("Value of combo box defined!");
}
#Override
public void editingCanceled(ChangeEvent e) {
System.out.println("Edition canceled, set the old value");
}
});
This way you will be able to only act when the value has been defined by the ComboBox.
I hope this helps.
You should not be using an ActionListener for this. The combo box uses its own ActionListener to update the TableModel when an item is selected.
So instead you should be listening for changes in the TableModel in order to do your custom code. So you should be using a TableModelListener to listen for changes in the data. However, a TableModelListener can fire an event even if just start and stop editing of the cell which might be a problem for you.
In this case you can use the Table Cell Listener. It will only generate an event when the value in the TableModel has changed.

How to select an item from a JList without using a button?

I've been making a program, and one part of it is the ability to choose an item from a JList and have it display a specific icon in a JLabel. I've made it work so that the user has to select the item from the list and then press a button to initiate the action.
I'm just wondering if there's any way to make it so the button isn't necessary? In other words, the user simply has to click the list item and it immediately initiates the action.
Here is my code:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Example extends JFrame
{
JList list = null;
Example()
{
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
ArrayList data = new ArrayList();
data.add("Py");
data.add("Piper");
list = new JList(data.toArray());
list.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent evt)
{
// To avoid double value selected
if (evt.getValueIsAdjusting())
return;
System.out.println("Selected: " + list.getSelectedValue());
}
});
cp.add(new JScrollPane(list), BorderLayout.CENTER);
}
public static void main(String[] s)
{
Example l = new Example();
l.pack();
l.setVisible(true);
}
}
So right here:
list.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent evt)
{
// To avoid double value selected
if (evt.getValueIsAdjusting())
return;
System.out.println("Selected: " + list.getSelectedValue());
}
});
So what you are actually doing is to "plug" a ListSelectionListener to your JList so that can be notified for any events that occur to the JList. Within the valueChanged you add the code need to be executed when the user select something in the JList.
There is this wonderful resource with the JList JavaDoc.

How to set the title of a JComboBox when nothing is selected?

I want to have a JCombobox in my Swing application, which shows the title when nothing is selected. Something like this:
COUNTRY ▼
Spain
Germany
Ireland
I want "COUNTRY" to show when the selected index is -1 and thus, the user wouldn't be able to select it. I tried to put it on the first slot and then overriding the ListCellRenderer so the first element appears greyed out, and handling the events so when trying to select the "title", it selects the first actual element, but I think this is a dirty approach.
Could you lend me a hand?
Overriding the ListCellRenderer is a good approach, but you tried something overly complicated. Just display a certain string if you are rendering the cell -1 and there is no selection (value is null). You are not limited to display elements on the list.
The following is an example program that demonstrates it:
Full Code:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
public class ComboBoxTitleTest
{
public static final void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
new ComboBoxTitleTest().createAndShowGUI();
}
});
}
public void createAndShowGUI()
{
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
JPanel buttonsPanel = new JPanel();
frame.add(mainPanel);
frame.add(buttonsPanel, BorderLayout.SOUTH);
String[] options = { "Spain", "Germany", "Ireland", "The kingdom of far far away" };
final JComboBox comboBox = new JComboBox(options);
comboBox.setRenderer(new MyComboBoxRenderer("COUNTRY"));
comboBox.setSelectedIndex(-1); //By default it selects first item, we don't want any selection
mainPanel.add(comboBox);
JButton clearSelectionButton = new JButton("Clear selection");
clearSelectionButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
comboBox.setSelectedIndex(-1);
}
});
buttonsPanel.add(clearSelectionButton);
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class MyComboBoxRenderer extends JLabel implements ListCellRenderer
{
private String _title;
public MyComboBoxRenderer(String title)
{
_title = title;
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean hasFocus)
{
if (index == -1 && value == null) setText(_title);
else setText(value.toString());
return this;
}
}
}
index == -1 in the renderer is the head component that, by default, displays the selected item and where we want to put our title when there's no selection.
The renderer knows that there's nothing selected because the value passed to it is null, which is usually the case. However if for some weird reasons you had selectable null values in your list, you can just let the renderer consult which is the explicit current selected index by passing it a reference to the comboBox, but that is totally unrealistic.

why doesn't my itemlistener always trigger

enter image description hereI'm a new programmer and I'm working on a text adventure that uses dropdown boxes (choice) as an input device. I have an itemListener on the first box that populates the members of the 2nd with the members that can be added. The player is then allowed to click the submit button and the first box is reset to the first item on the list and the second box is supposed to be cleared. When I run the program, the first time it reacts exactly as planned. The 2nd time I try to input something using the drop down boxes, the dropdown box doesn't respond. I put a marker inside the itemListener to see if it was even triggering to find out that it wasn't. I feel like I've tweeked the program in every way imaginable but I have no idea what is causing this issue. If I toggle between the items in the drop down box a few times the itemListener starts to respond again.
This is a representation of my issue I threw together.
import java.awt.Choice;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
public class gui implements ActionListener
{
private static JTextPane outputField = new JTextPane();
private static JPanel mainPanel = new JPanel(new GridBagLayout());
private Choice commandDropDown = new Choice();
private Choice itemDropDown = new Choice();
private JButton submitButton = new JButton();
public gui()
{
JFrame frame = new JFrame("test");
mainPanel.setSize(450,585);
commandDropDown = buildCommandBox(commandDropDown);
commandDropDown.setBounds(100, 15, 100, 40);
itemDropDown.setBounds(200, 15, 100, 40);
submitButton.setText("submit");
submitButton.setBounds(15, 15, 100, 40);
submitButton.addActionListener(this);
frame.add(commandDropDown);
frame.add(itemDropDown);
frame.add(submitButton);
frame.setResizable(false);
frame.pack();
frame.setSize(300, 300);
//frame.setLayout(null);
//frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
itemDropDown.removeAll();
commandDropDown.select(0);
}
private Choice buildCommandBox(Choice custoChoi)
{
final Choice c = new Choice();
c.addItem("choices");
c.addItem("Option1");
c.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent ie)
{
System.out.println("the action event for the command"
+ "box is working.");
if(c.getSelectedItem().equals("Option1"))
{
itemDropDown.addItem("things");
itemDropDown.addItem("stuff");
}
}
});
return c;
}
}
Hopefully these pictures clear up any confusion about my post.
http://imgur.com/a/h9oOX#0
In my opinion, your buildCommandBox( Choice custoChoi) is wrong, it should be something like that:
private Choice buildCommandBox(final Choice custoChoi) {
custoChoi.addItem("choices");
custoChoi.addItem("Option1");
custoChoi.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent ie) {
System.out.println("the action event for the command" + "box is working.");
if (custoChoi.getSelectedItem().equals("Option1")) {
itemDropDown.addItem("things");
itemDropDown.addItem("stuff");
}
}
});
return custoChoi;
}
I would recommand to use JComboBox instants of Choice, if Swing is allowed.

Categories