I have a JList which runs code each time the value in the list is double-clicked. The value is populated when a button is pressed. My problem is each time I click the button and then double-click the JList value it will repeat the code by however many times the button is pressed.
For example, the first time everything looks great, but if I press the button again to change the JList value, it will execute the code for a double-click twice. If I press it a third time, it will execute the code three times and so on. I am new to this so apologies if this is an easy one. Thanks for any info. Code is below let me know if more is necessary.
public DefaultListModel results(StringBuilder message)
{
DefaultListModel model = new DefaultListModel();
model.addElement(message);
showOption.setModel(model);
MouseListener mouseListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2)
{
int index = showOption.locationToIndex(e.getPoint());
Object o = showOption.getModel().getElementAt(index);
System.out.println("Double-clicked on: " + o.toString());
}
}
};
showOption.addMouseListener(mouseListener);
return model;
}
You are adding a new MouseListener each time results is called...
This...
DefaultListModel model = new DefaultListModel();
model.addElement(message);
showOption.setModel(model);
Shows that showOption is an existing instance of JList (which is good), but then you do...
MouseListener mouseListener = new MouseAdapter() {
//...
};
showOption.addMouseListener(mouseListener);
Which adds ANOTHER MouseListener to the JList, so the each time this method is called, there will another MouseListener added to the JList.
Add a single MouseListener to the JList when you first create it.
Related
BACKGROUND INFO: I want to make a 9x9 grid of buttons that act as empty beds. All buttons say "Add bed" and when clicked open up a window to write data about the occupant. Once saved the button will change to an occupied bed image.
QUESTION: Is it possible to create an event listener that does the same thing for each button, but applies it to the button being pressed? Im new to java but I understand that good code should be able to do this in a few lines rather than 100+
CODE:
//button1 (inside the gui function)
addBed1 = new JButton("Add bed"); //button 1 of 9
addBed1.addActionListener(new room1Listener());
class room1Listener implements ActionListener{
public void actionPerformed(ActionEvent event){
addBed1.setText("Adding bed..);
addBedGui(); //Generic window for adding bed info.
}
}
Is it possible to create an event listener that does the same thing for each button, but applies it to the button being pressed? Im new to java but I understand that good code should be able to do this in a few lines rather than 100+
Absolutely. In fact you can create one ActionListener object and add this same listener to each and every button in a for loop. The ActionListener will be able to get a reference to the button that pressed it via the ActionEvent#getSource() method, or you can get the JButton's actionCommand String (usually its text) via the ActionEvent#getActionCommand() method.
e.g.,
// RoomListener, not roomListener
class RoomListener implements ActionListener{
public void actionPerformed(ActionEvent event){
AbstractButton btn = (AbstractButton) event.getSource();
btn.setText("Adding bed..);
addBedGui(); //Generic window for adding bed info.
}
}
and
RoomListener roomListener = new RoomListener();
JButton[] addButtons = new JButton[ADD_BUTTON_COUNT];
for (int i = 0; i < addButtons.length; i++) {
addButtons[i] = new JButton(" Add Bed "); // make text big
addButtons[i].addActionListener(roomListener);
addBedPanel.add(addButtons[i]);
}
I'm making a To-Do List application and I have a PrimaryList frame and a SubList frame. When a user selects something from the PrimaryList (Grocery...or something like that) and then hits a forward arrow JButton, it is supposed to launch up the SubList frame. Now here is what I have for the actionPerformed method of the forward arrow button called btnArrow.
private void btnArrowActionPerformed(java.awt.event.ActionEvent evt) {
lstToDoLists.addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e){
if (lstToDoLists.getSelectedIndex() > 0){
btnArrow.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent ae){
if (btnArrow==ae.getSource()){
SubList sublist = new SubList();
sublist.setVisible(true);
}
}
});
}
}
});
}
Now, when I run the PrimaryList file and click on an item in my JList and then select the forward arrow button, I get nothing. But then when I click another element from the list and press the forward arrow button again, my SubList pops up twice.
Something isn't write with what I've written and I am hoping someone else will know how to fix this problem.
You're adding listeners inside of listeners -- something that you don't want to do, since this means that new listeners will be added, each time an event occurs.
Solution: don't add listeners inside of other event listeners but rather add the listeners once and in your code's constructor or initialization method.
Note that I would not use a ListSelectionListener at all. Instead I'd just use a single ActionListener on the button. Then in that listener, get the list's selection and use it.
e.g.,
private void btnArrowActionPerformed(java.awt.event.ActionEvent evt) {
// if list contains String:
String selectedItem = (String) lstToDoLists.getSelectedItem();
// check that selectedItem isn't null, i.e,
if (selectedItem != null) {
// TODO: do something with selection here
}
}
As a side recommendation, please look at The Use of Multiple JFrames, Good/Bad Practice?.
I have two JComboBox and one button. I am trying to do that if I select an item from the two combo box individually and press the button called search. Then the two selected items from the two combo box will save in a new two separate string.
Please anyone help me to solve the problem.
Here is the code snippet
//here is the strings that in the combo box
String lc[] = {"Kolabagan-Dhaka", "Gabtoli-Dhaka", "Fakirapul-Dhaka", "Shaymoli-Dhaka"};
String rc[] = {"Banani-Bogra", "Rangpur","Shatrasta-Bogra"};
//here is my two jcombo box
JComboBox lcCombo = new JComboBox(lc);
JComboBox rcCombo = new JComboBox(rc);
// here is my search button
JButton searchButton = new JButton("Search");
There are two ways to go about this. The first is to have one class that implements ActionListener and in the implementation, check the source (ActionEvent.getSource()). Based on which component sourced the event, you take the appropriate action.
The other option (and my preference) is to create an ActionListener for each component that requires one. You can use anonymous classes if you don't want to explicitly define one for each case. This way each listener knows exactly what component caused the event and what action to take.
Example:
JComboBox lcCombo = new JComboBox(lc);
lcCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
//do left stuff
}
});
JComboBox rcCombo = new JComboBox(rc);
rcCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
//do right stuff
}
});
To expand on unholysampler, once you have the ActionListener working you can use lcCombo.getSelectedIndex() to check which item has been selected.
I'm quite new to Java Swing. And I'm stuck on trying to add a ListSelectionListener on a JComboBox instance. It seems only the ListSelectionModel interface has addListSelectionListener method. I kind of cannot figure it out...
Why I want to do add it is that I want program do something even the item in the combo box is not changes after selecting.
POTENTIAL ANSWER
I was simply thinking of attaching an actionListener on combobox not working. and i think it's bug of openjdk. I've reported it here
Thanks in advance.
Take a look at JComboBox#addItemListener:
JComboBox combo = createCombo();
combo.addItemListener(new ItemListener()
{
#Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED)
{
Object selectedItem = e.getItem();
// Do something with the selected item...
}
}
});
This event is fired for both mouse and keyboard interaction.
For JComboBox, you'll have to use ActionListener.
JComboBox jComboBox = new JComboBox();
jComboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("combobox event");
}
});
AFAIK, actionPerformed is raised whenever the user makes a selection for the JComboBox even if it's the same item that was already selected.
It depends on your requirement. The ActionEvent is only fired when the keyboard is used, not when the selection changes as the mouse is moved over the items.
If you want to do some action when the item selection changes even if the mouse is moved then yes you will probably need access to the JList. You can access the JList used by the popup with the following code:
JComboBox comboBox = new JComboBox(...);
BasicComboPopup popup = (BasicComboPopup)comboBox.getAccessibleContext().getAccessibleChild(0);
JList list = popup.getList();
list.addListSelectionListener(...);
Use a PopupMenuListener. When the popup menu closes get the selected index and do your processing.
This must be a misunderstanding from my side, but I have the following:
I have added an ItemListener to a Jcombobox.
In the item listener, I check in the event if it is of type ItemSelected.
If it is, I update a value in a JTextPane.
The problem is that it works as follows:
I click on a new value in the jcombobox and nothing is changed in the jtextfield. I have to actually click on another component e.g. the jtextfield and then the jtextfield is updated.
It seems that the focus must be removed from the jcombobox so that the event change is dispatched to the itemlistener code.
Is this how it is supposed to work, or am I doing something wrong? Is it possible to handle the event without needing to remove focus?
UPDATE: This my code and the method updateJTextPane is called after I click on another component an not when I select a new value from the combo. I.e. combo has value "1", I click on the drop-down list and click on "2". Current selected item is now "2". My method is not being called at this point. I click on a second combo box, second combo has focus and then my method updateJTextPane() is called. Why?
UPDATE 2:
//Code from Netbeans generator
JComboBox myCbx = new javax.swing.JComboBox();
myCbx.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
myCbx.setName("myCbx"); // NOI18N
//My ItemListener
class myItemListener implements ItemListener{
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED) { // Item was just selected
updateJTextPane();
}
}
}
//add item listener to combo
myCbx.addItemListener(new myItemListener());
UPDATE 3:Inner class myItemListener is added to 5 more comboboxes in the same JDialog if this matters in a way I do not know
Thank you
This is not how it is supposed to work. Item events should be generated immediately whenever the selected item changes.
I suggest to start with a simple example such as this one and see if events are actually being generated. If this works, then you only need to search for the differences between this and your own code.
Update:
Your itemStateChanged method looks fine, the problem must be elsewhere. Perhaps there is something wrong with updateJTextPane. What happens if you replace the call to updateJTextPane with a System.out.println? Also, can you print out the source of the event (ie.getSource()) and verify that the event is actually coming from the first combo box?
If you post a self-contained example that can be compiled and run, it should be much easier to pinpoint the problem.
It should work as you described it, the following runs just fine:
class Frame extends JFrame {
JComboBox box;
JTextField field;
String[] entries = { "one", "two", "three" };
Frame() {
setLayout(new FlowLayout());
box = new JComboBox(entries);
box.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
field.setText((String) box.getSelectedItem());
}
}
});
add(box);
field = new JTextField();
field.setColumns(10);
add(field);
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Frame frame = new Frame();
}
});
}
}
Is it possible to handle the event without needing to remove focus?
Sure it is! :)
Here's a sample of how it could work, assuming my understanding of your requirements is correct:
class ComboListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println("Selected Item: \""
+ ((JComboBox)e.getSource()).getSelectedItem() + "\"");
}
}
}
If you don't add the if check, you are going to perform the action for both the first item being unselected and the second one being selected.
I have encountered the similar situation on Choice.
To me it more likes a bug in Java. My case is I have two Choices A and B. B depends on A's selection. For example, A={a1, a2, a3}. If A=a1 B is a Choice list of {1, 2, 3}. If A=a2, B is a list of {4,5,6}., If A= a3, B is a list of {7,8,9}. The flow is select a1 and then select 2 on B. Select a2 and B is in default index 0 (4) and select 5 on B, the itemStateChanged() funcation will not be called. It looks like the view control does not sync with the data set to it. The reason the itemStateChanged() is not called since the 5 has the same index of previous selection.