Subclassing JButton to obtain info on button property

时间:2016-07-11 21:35:22

标签: java swing user-interface jbutton

My problem: I have a dynamic list of objects (dynamic in the sense that I don't know how many elemets it will contain). I need a button for each of them, and each button needs to "tell me" wich item has been selected. I don't reallt want to use checkboxes or radiobuttons (and as far as I know those can't store/return an object, right?) So, my solution was: Subclass JButton into ItemButton, which is a JButton, but I also has a field to store my Item. This way, in the listener attached to it I can just call a returnItem method, and I'll have the selected item, ready for use.

This is an inner class:

class toolButton extends JButton {
    toolButton(String name, int i) {
        super(name);
        this.index = i;     
    }

    public int getSelectionIndex() {
        return this.index;
    }

    private int index;
}

The method that generates my button list:

public void showItemList(ArrayList<Item> arrayList) {
    for (int i = 0; i < arrayList.size(); i++) {
        toolButton but = new toolButton(arrayList.get(i).getName()", i);   //getName() returns the name of the Item to be displayed
        this.add(but);
        but.addMouseListener(new MouseAdapter() {
            // Simple anonymous class for the listener
            public void mousePressed(MouseEvent e) {
                selected = but.getSelectionIndex(); //This sets the index number in the class that uses this method
            }
        }); 
    }       
}

It works, for what I'm doing at least. But I was wondering if there is a better method, or it this is at least acceptable, if it isn't frowned upon althoger. I don't think using getSource() on the actionEvent whould be of much use in this case. And I can't really write a listener for each button because I don't know how many there are.

Edit: What I'm trying to model is a simple dispenser, a dispenser has a collection of items (each of which has a name and a price). The dispenser class has a method "buy(Item item)". So what I want to do is have a button represent each avaiable item in the dispenser, and when the button is pressed, I want a reference to an Item to pass to the method buy(Item) (the button doesn't have to call the buy(Item) method itself). As I'm sure you understood, this is a class exercise, so I can't change the requirments.

1 个答案:

答案 0 :(得分:1)

If the item names in the arrayList argument suffice to resolve the corresponding item categories, you will not have to subclass JButton, but can use it as is:

public void showItemList(ArrayList<Item> arrayList){
    for(int i = 0; i < arrayList.size(); i++){
        JButton but = new JButton(arrayList.get(i).getName());
        getContentPane().add(but);
        but.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent event){
               String itemName = event.getActionCommand();
           } 
        });
    }
}

Some notes:

  • If you are subclassing JFrame, you should use its contentpane instead of adding buttons directly to it: getContentPane.add(button). If you're using a JPanel, your code is ok.
  • In your case, you should use the ActionListener instead of the MouseListener. As an added value, you get to query the label of the clicked button: event.getActionCommand(), so you know which item was selected and you don't have to implement a subclass to keep track of the index.