选择组合框上的项目时执行操作

时间:2013-03-02 10:18:23

标签: java swing actionlistener jcombobox itemlistener

我有一个包含item1和item2的jcombobox,我也有一个jtextfield ..当我在我的jcombobox上选择item1时我希望30出现在我的jtextfield上,而如果选择了Item2则为40 ...我该怎么办?< / p>

3 个答案:

答案 0 :(得分:11)

这就是你使用ActionLIstener

的方法
import java.awt.FlowLayout;
import java.awt.event.*;

import javax.swing.*;

public class MyWind extends JFrame{

    public MyWind() {
        initialize();
    }

    private void initialize() {
        setSize(300, 300);
        setLayout(new FlowLayout(FlowLayout.LEFT));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTextField field = new JTextField();
        field.setSize(200, 50);
        field.setText("              ");

        JComboBox comboBox = new JComboBox();
        comboBox.setEditable(true);
        comboBox.addItem("item1");
        comboBox.addItem("item2");

        //
        // Create an ActionListener for the JComboBox component.
        //
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                //
                // Get the source of the component, which is our combo
                // box.
                //
                JComboBox comboBox = (JComboBox) event.getSource();

                Object selected = comboBox.getSelectedItem();
                if(selected.toString().equals("item1"))
                field.setText("30");
                else if(selected.toString().equals("item2"))
                    field.setText("40");

            }
        });
        getContentPane().add(comboBox);
        getContentPane().add(field);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MyWind().setVisible(true);
            }
        });
    }
}

答案 1 :(得分:2)

简单的解决方案是使用ItemListener。当状态改变时,您只需检查当前选择的项目并相应地设置文本

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestComboBox06 {

    public static void main(String[] args) {
        new TestComboBox06();
    }

    public TestComboBox06() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private JComboBox cb;
        private JTextField field;

        public TestPane() {
            cb = new JComboBox(new String[]{"Item 1", "Item 2"});
            field = new JTextField(12);

            add(cb);
            add(field);

            cb.setSelectedItem(null);

            cb.addItemListener(new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    Object item = cb.getSelectedItem();
                    if ("Item 1".equals(item)) {
                        field.setText("20");
                    } else if ("Item 2".equals(item)) {
                        field.setText("30");
                    }
                }
            });
        }

    }

}

更好的解决方案是创建一个自定义对象,该对象表示要显示的值以及与之关联的值...

<强>更新

现在我已经不再需要10个月的咀嚼脚踝,我更新了示例以使用ListCellRenderer,这是一种更正确的方法,然后是懒惰的并覆盖toString

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestComboBox06 {

    public static void main(String[] args) {
        new TestComboBox06();
    }

    public TestComboBox06() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private JComboBox cb;
        private JTextField field;

        public TestPane() {
            cb = new JComboBox(new Item[]{
                new Item("Item 1", "20"), 
                new Item("Item 2", "30")});
            cb.setRenderer(new ItemCelLRenderer());
            field = new JTextField(12);

            add(cb);
            add(field);

            cb.setSelectedItem(null);

            cb.addItemListener(new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    Item item = (Item)cb.getSelectedItem();
                    field.setText(item.getValue());
                }
            });
        }

    }

    public class Item {
        private String value;
        private String text;

        public Item(String text, String value) {
            this.text = text;
            this.value = value;
        }

        public String getText() {
            return text;
        }

        public String getValue() {
            return value;
        }

    }

    public class ItemCelLRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); //To change body of generated methods, choose Tools | Templates.
            if (value instanceof Item) {
                setText(((Item)value).getText());
            }
            return this;
        }

    }

}

答案 2 :(得分:1)

不是对原始问题的回答,而是在不破坏MVC的情况下如何制作可重复使用且可正常工作的自定义渲染器的示例: - )

// WRONG
public class DataWrapper {
   final Data data;
   final String description;
   public DataWrapper(Object data, String description) {
       this.data = data;
       this.description = description;
   }
   ....
   @Override
   public String toString() {
       return description;
   } 
}
// usage
myModel.add(new DataWrapper(data1, data1.getName());

在MVC环境中错误,因为它混合了数据和视图:现在模型不包含数据,而是为<引入的包装器em>查看原因。这打破了关注点和封装的分离(每个与模型交互的类都需要知道包装数据)。

违反规则的驱动力是:

  • 保留默认KeySelectionManager的功能(由自定义渲染器破坏)
  • 重用包装类(可以应用于任何数据类型)

在Swing中,自定义渲染器是 小硬币,用于容纳自定义视觉表示,无法应对的默认管理器被破坏。调整设计只是为了适应这种蹩脚的默认设置是错误的方式,有点颠倒。正确的是,实施一个应对经理。

虽然重复使用很好,但是以打破基本架构的代价这样做并不是一个好的假期。

我们在演示领域遇到了问题,让我们在演示领域解决它,其中的元素旨在解决这个问题。正如您可能已经猜到的那样,SwingX已经有了这样的解决方案:-)

在SwingX中,字符串表示的提供者称为StringValue,所有默认的渲染器都使用这样的StringValue来配置自己:

StringValue sv = new StringValue() {
     @Override
     public String getString(Object value) {
        if (value instanceof Data) {
            return ((Data) value).getSomeProperty();
        }
        return TO_STRING.getString(value);
     }
};
DefaultListRenderer renderer = new DefaultListRenderer(sv);

由于defaultRenderer是一个StringValue(实现为委托给定),KeySelectionManager的良好实现现在可以委托给渲染器来查找相应的项目:

public BetterKeySelectionManager implements KeySelectionManager {

     @Override
     public int selectionForKey(char ch, ComboBoxModel model) {

         ....
         if (getCellRenderer() instance of StringValue) {
              String text = ((StringValue) getCellRenderer()).getString(model.getElementAt(row));
              ....
         } 
     }

}

概述了这种方法,因为即使不使用SwingX也可以轻松实现,只需定义类似的实现并使用它:

  • 字符串表示的一些提供者
  • 自定义渲染器,可由该提供程序配置,并保证在配置时使用它
  • 行为良好的keySelectionManager,用于查询渲染器的字符串表示

除了字符串提供程序之外的所有字符串都可以原样重用(这正​​是自定义渲染器和keySelectionManager的一个实现)。可以存在字符串提供者的一般实现,f.i。那些格式化值或通过反射使用bean属性。并且所有这些都没有违反基本规则: - )