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)));
}
Related
I am writing a Java program in which I have an array of buttons (not a calculator!) and I'm looking for an efficient way to know which JButton was clicked. From what I know of Java so far, the only way to do it is to have them all in the same ActionListener and then loop through looking for a match.
Another solution I just thought of would be to extend JButton to include a unique ID number variable in the constructor. It seems that should work when the event object is cast to JButton after an instanceof check. Kind of like using VB's Tag property which is assigned to the index number.
Is there a better/more elegant way?
Is there a better/more elegant way?
yes to use (for almost JComponents) the put/getClientProperty, there you can to set endless number of properties, can be multiplied in contrast with setName / setActionCommand / etc
getClientProperty can be used as unique identificator for Swing Action or EventHandler (rather than to use ActionListener)
Links to the Javadocs: putClientProperty(), getClientProperty()
Here is an example from programm I writing last few months.
I have an enum called Position
public enum Position {
BB, SB, BU, CO, MP3, MP2, MP1, EP3, EP2, EP1;
}
and have some JToggleButtons each of them holding ist own Position.
public class PositionButton extends JToggleButton {
private final Position p;
public PositionButton(Position p) {
this.p = p;
setText(p.toString());
setActionCommand(p.toString());
}
public Position getPosition() {
return p;
}
}
This allows you to create Buttons in a Loop and get value direct from button without comparing:
ActionListener positionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
PositionButton b = (PositionButton )e.getSource();
Position p = b.getPosition();
//do something with Position
}
}
for (Position p : Position.values()) {
PositionButton b = new PositionButton (p);
b.addActionListener(positionListener);
}
The way I've done it before was using actionPerformed for different buttons. I like it more compared to some other ways I've seen.
public void actionPerformed(ActionEvent clicking)
{
if (clicking.getSource() == button[0])
// Do this
if (clicking.getSource() == button[1])
// Do something different
}
Since you built an array, you can throw the ID right where that 0 is and that's your unique ID.
Add a separate action listener for each button.
I have a JTable and Given such codes:
jTable.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
System.out.println(jTable.getRowCount());
System.out.println(jTable.getModel().getValueAt(jTable.getRowCount(), 0));
}
});
If I click on a certain row, like in the picture above, I clicked the second row, how can I get that row's content?(How to get the Canada)?
Personally, I use the Mouse Clicked event. You could try something like this inside your event method:
private void myTableMouseClicked(java.awt.event.MouseEvent evt) {
int row = this.myTable.getSelectedRow();
int column = this.myTable.getSelectedColumn();
this.myTable.getValueAt(selectedRow, selectedColumn);
}
Be aware that the getValueAt method returns an Object. You probably will need to cast the Object returned into the object it is supposed to be. And also you could have a global variable that's going to have the value returned by getValueAt for using it as you need.
I hope it helps.
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 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.
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();
}
}
});
}