I am implementing a function which the function passes a selected item in a JList and a value in a JTextField when users click on a JButton.
I am using several listeners. However, it seems that the loop actionPerformed inside addcartbtn is invoked twice when users pressed the button for the second times and produces unwanted results. When users pressed the third time, the function seems invoked three times.
list.addListSelectionListener(new ListSelectionListener() {
Map<String, Integer> cartlist = new HashMap<String, Integer>();
public void valueChanged(final ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
System.out.println("test0");
final ArrayList<String> cartArrayList = new ArrayList<String>();
addcartbtn.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e2) {
System.out.println("test2");
String itemselected = "";
System.out.println("Index is " + e.getLastIndex());
String itemname = (String) hashmap.get(e.getLastIndex());
itemselected = itemname;
//System.out.println(itemselected);
try {
int insertedquantity = Integer.parseInt(quantity.getText());
cartlist.put(itemselected, insertedquantity);
//shoppingcart.revalidate();
String element = itemselected + " " + String.valueOf(insertedquantity);
cartArrayList.add(element);
System.out.println(element);
//System.out.println(counter);
shoppingcart.setListData(cartArrayList.toArray());
shoppingcart.revalidate();
shoppingcart.repaint();
System.out.println("---------");
} catch (NumberFormatException ex) {
System.out.println("Not a number!");
}
}
});
}
}
});
Thanks everyone for helping!
Don't add an ActionListener inside of a ListSelectionListener -- makes no sense. You'll be adding many many listeners for no purpose. In fact, if you want the action to occur when the button is pressed only, I see no reason for a ListSelectionListener at all. Just use an ActionListener that has been added once to the JButton, perhaps in a constructor or set up method.
Also, a little less indentation may make your code easier for us to read.
Edit: I've reduced the code indentation in your original post.
You're adding a new action listener to your addcartbtn (wouldn't it be much more readable if it was named addCartButton, BTW) each time a selection is made in the JList. The listener should only be added once.
Related
I have a problem with my Java code. I am trying to search trough a JList, with key events, but it seems like it can't find anything.
With this event, I am adding values to my JList:
DefaultListModel<String> model = new DefaultListModel<>();
private void productButtonActionPerformed(java.awt.event.ActionEvent evt) {
for (Shop i : shopSettings.Products) {
model.addElement(i.getProductName()+i.getPrice()+i.getProductCategory()+i.getNumber());
}
jList1.setModel(model);
}
Here I am trying to search trough the JList, with this action, but anytime I write something, it just overwrites the list, and displays nothing.
private void jTextField1KeyReleased(java.awt.event.KeyEvent evt) {
DefaultListModel filteredProducts = new DefaultListModel();
for (Shop i: shopSettings.Products) {
String productName=i.getProductName()+i.getPrice()+i.getProductCategory()+i.getNumber().toLowerCase();
if(productName.contains(jTextField1.getText().toLowerCase()));
{
model.addElement(i.getProductName()+i.getPrice()+i.getProductCategory()+i.getNumber());
}
}
model=filteredProduct;
jList1.setModel(model);
}
Sorry, if the answer is way too obvious, I have just getting started with Java.
could be:
String productName= (i.getProductName()+i.getPrice()+i.getProductCategory()+i.getNumber()).toLowerCase();
Best to learn how the debugger works in your IDE of choice and step through the algorithm to see why it doesn't match.
Edit: To be more clear: Call toLowerCase on the result of the concatenation, not just the last part.
I want to update the jcombobox. So I removed all items first and then going to execute the query. I'm calling this method in a constructor and it's working fine. Also I'm calling this method in a button, and when that btn is pressed it gives me a nullpointerexception. combo box items were also removed. So the problem is in line 5. How to fix this??
private void loadDataToCombo(String query,JComboBox combo) {
ResultSet result1= null;
//removing existing items before adding
combo.removeAllItems();
result1 = DBOptions.executeSQLQuery(query); //line 5
try {
while(result1.next()){
String data = result1.getString(1);
combo.addItem(data);
}
} catch (SQLException ex) {
Logger.getLogger(AddCustomer.class.getName()).log(Level.SEVERE, null, ex);
}
}
If its on the click of the Button, please see that have you initialized the Button..?
JButton butt = new JButton();
I had same problem. I think it is because you have actionlistner on the items. what I did is remove the actionlistener on the items.
I had the same issue, my solution was to replace the combo event actionperformed by the event mouseclicked. This way, it does not catch the item or prevent you from adding them by addItem().
I have a JFrame with a menubar, in which i'd like some dynamic menus, as in, depending on the size of the ArrayList with HashLists. The problem here is that i then got a dynamic amount of JMenuItems, so i need a way to get as much variables as HashLists. In this case i made the name of the variable static, but obviously that's not working on the ActionListener, since all MenuItems will have the same ActionListener.
I'm wondering how to solve this, and how to get a menu with a dynamic amount of menuitems which all have unique actionlisteners.
private ArrayList<HashMap> menuLijst;
.
for (HashMap h : menuLijst) {
String vraag = (String) h.get("vraag");
JMenuItem qMenu = new JMenuItem(vraag);
informatie.add(qMenu);
qMenu.addActionListener(this);
}
Thanks in advance.
Depending on what you want to do in your ActionListener, you can either use this, as you do right now and in the actionPerformed you can then use ((JMenutItem)event.getSource()) to see which menu item has been clicked. Alternatively, you could register as many ActionListeners as there are menus, like this:
for (final HashMap h : menuLijst) {
final String vraag = (String) h.get("vraag");
final JMenuItem qMenu = new JMenuItem(vraag);
informatie.add(qMenu);
qMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// here event.getSource() is the same as qMenu
System.out.println("Menu "+qMenu+" with label "+vraag+" has been pressed");
System.out.println("HashMap is "+h);
}
});
}
But to me (and also seeing your previous questions), it seems that you are abusing the usage of HashMap instead of using appropriate new objects. I don't know what else is in your HashMap, let's say that you have 3 keys: "vraag", "answer", "grade", you could create the following class:
public class MyClass {
private String vraag;
private String answer;
private int grade;
// And getters and setters here.
}
And have a List<MyClass> instead of List<HashMap>.
I don't see why you want to use a HashMap for your Strings. If you save an ArrayList of Strings, and loop over them to add them all to the menu, you can add actionListeners to all of them, just as you are doing now.
In your ActionListener, check which button is clicked by looping through the ArrayList, and comparing to the name of the clicked button.
I have a program in which I am using 3 things, a checkbox, a combobox and a textfield. The logic works like this if checkbox is enable then combobox and textfield are enable unless not.
Then set some value in the textfield by mulitplying it with the item in combobox.
From the frame - The value of Final Price is Price * Quantity.
Now the issue when I click purchase everything went fine. But when I change the value from Jcombobox it doesn't automatically change the value in final price and remains to be 1200 as in first case. For the value to be changed I have uncheck and then check the Checkbox.
What could be the problem. I have used ItemListner for both checkbox and combobox.
#Override
public void itemStateChanged(ItemEvent e){
Object get = e.getSource();
int multiplier;
int ftotal;
if (e.getStateChange()==ItemEvent.SELECTED){
if(get==chkbox1){
qntbox1.setEnabled(true);
size1.setEnabled(true);
multiplier = Integer.parseInt(String.valueOf(qntbox1.getSelectedItem()));
ftotal = Integer.parseInt(price1.getText()) * multiplier;
fprice1.setText(String.valueOf(ftotal));}
You have to implement ActionListener for your JComboBox:
private static final String command_cbo1 = "ComboBox1";
// ...
public class YourClass implements ItemListener, ActionListener
{
// ...
public YourClass()
{
// ...
qntbox1.addActionListener(this);
qntbox1.setActionCommand(command_cbo1);
// ...
}
// ...
public void itemStateChanged(ItemEvent e)
{
// ...
}
// ...
public void actionPerformed(ActionEvent e)
{
JComboBox cb = (JComboBox) e.getSource();
String s = (String) cb.getSelectedItem();
if(e.getActionCommand().equals(command_cbo1))
{
fprice1.setText("" + (Integer.parseInt(price1.getText()) * Integer.parseInt(s)));
}
// ...
}
// ...
}
not directly to your question
1/ JCheckBox is totally useless, that will be really needed for final calculation(s)
2/ consider that JComponents for Price and Final Price would be only JFormattedTextField, then you can pretty to forgot for Parse#Whatever
3/ consider that JComponents for Quantity would be only JSpinner, but workaround for Number Instance would be litte bit complicated as for JFormattedTextField example here
4/ for nice output put everything to the JTable
5/ for JComboBox I preferred ItemListener not ActionListener, because your problems isn't with proper Listener but with parsing Numbers correct way
Ok got it working. The ActionListner made it work (JComboBox). I guess using ItemListner for too many components made parsing a little confusing, add to that I used too many clauses in the ItemListner scope. Thanks a lot everyone for helping.
#mKorbel : I'll be using your suggestion asap :) and will check JTable and said components. have to go through them since I haven't used it.
#Eng.Fouad : Thanks man for the help.
Just one issue. When I typecast getSelectedItem() to integer it gives NumberFormatException error (runtime). So I have to first change the object to String and then parseit into integer. Any clue why direct conversion is throwing error ?
Here is the working code for the project.
public void itemStateChanged(ItemEvent e){
Object get = e.getSource();
if (e.getStateChange()==ItemEvent.SELECTED){
if(get==chkbox1){
qntbox1.setEnabled(true);
size1.setEnabled(true);
fprice1.setText(String.valueOf(Integer.parseInt(price1.getText()) * Integer.parseInt(String.valueOf(qntbox1.getSelectedItem()))));
}
#Override
public void actionPerformed (ActionEvent ae)
{
Object toggel = ae.getSource();
String check;
if (toggel == qntbox1)
{
check = (String) qntbox1.getSelectedItem();
fprice1.setText(String.valueOf(Integer.parseInt(price1.getText()) * Integer.parseInt(check)));
}
I noticed I can use getName() as part of the trick.
What is java.awt.Component.getName() and setName() used for?
But I don't really have a clue where to start. What type of listener should I use (assuming the textfield / or box is currently blinking / selected)
This is my previous question, and thank you for the help guys.
How do I use requestFocus in a Java JFrame GUI?
I realize that for each component (Textfield) that I am creating, I have to insert a statement like requestFocus (or using transferFocus).
Is it possible to apply this policy to all the fields???
I have several textfields and ComboBox. The problem I hit is that I don't want to write methods for every single field / box.
For example, I write a method like this
private JTextField getFirstNameEntry() {
.... do something
}
because my instructor writes his program like this
private JPanel getJContentPane() {
jContentPane = new JPanel();
jContentPane.setLayout(new java.awt.FlowLayout(FlowLayout.LEADING));
jContentPane.add(makeLabel(" First Name *", 100, 20));
jContentPane.add(getFirstNameEntry(), null);
jContentPane.add(makeLabel(" Middle Initial", 100, 20));
jContentPane.add(getMiddleInitialEntry(), null);
// etc
return jContentPane;
However, to save redundancy (that was my motive at first), say I have a box, I can simply add the following code inside the method above: getJContentPane()
titleBox = new JComboBox(new String[]{"Mr.","Mrs.","Ms.","Dr.","Prof.","Rev."});
jContentPane.add(titleBox);
But doing this, I still need to create a method to do addItemListener
private void setComboBoxFocus() {
titleBox.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = titleBox.getSelectedItem().toString();
System.out.println(titleSelected);
titleBox.transferFocus();
}
}
});
}
However, this doesn't really save redundancy at all. If I have more than one ComboBox to be added, I would have to write another similar method. In fact, even in the case with one ComboBox (titleBox), I would still end up with writing a method for titleBox.
So my question is: is there a way to write a general method that can call focus to all (maybe one for ComboBox type)?
Thank you and sorry for the long post.
Why not take a JComboBox argument to your setComboBoxFocus() method, which allows you to set that listener to any JComboBox you may have? Like so:
private void setComboBoxFocus(JComboBox box) {
box.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = box.getSelectedItem().toString();
System.out.println(titleSelected);
box.transferFocus();
}
}
});
}