2013-03-02 83 views
3

我有一个jcombobox包含item1和item2,我也有一个jtextfield ..当我选择我的jcombobox的item1我想30出现在我的jtextfield而40如果Item2是选择...我该怎么做?当选择组合框上的项目时执行动作

+0

http://stackoverflow.com/questions/8653901/jcombobox-actionperformed-event – Azodious 2013-03-02 10:24:04

回答

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); 
      } 
     }); 
    } 
} 
+2

我喜欢你的答案,一个非常小的nit选择,我可能会建议你做“项目1”.equals(选择),而不是 - 虽然极不可能,它将防止可能的NullPointerExceptions;) – MadProgrammer 2013-03-02 10:54:20

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; 
     } 

    } 

} 
+0

非常感谢你〜用重写的ToString(而不是一个适当的渲染器) – mitche027 2013-03-02 10:57:47

+0

包装对象是_evil_ - 在这里它可能看起来像是中间合理的,因为您似乎需要另一个财产来支持其他财产......这是一个本土化的问题,因为业务对象的保理是错误的,首先是:项目本身可能是业务对象,它的toString被一个完整的描述覆盖,而不是与某个特定视图相关的东西;-) – kleopatra 2013-03-02 14:22:06

+1

@kleopatra我完全同意,这是一个快速减少,因为实际编码的时间有限(没有任何借口),坏我 – MadProgrammer 2013-03-02 19:49:18

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环境错误,因为它是混合的数据和观点:现在的模式不包含数据而是一个包装,它是为查看原因而引入的。这破坏了关注点和封装的分离(每个与模型交互的类都需要知道包装数据)。

的驱动力的规则断裂是:

默认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是-A的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与查询渲染器的字符串表示形式

之外的所有字符串提供可重复使用的,是(位于自定义渲染器和日恰好一个实行e keySelectionManager)。可以有字符串提供者的通用实现,f.i.这些格式化值或通过反射使用bean属性。而且完全不会破坏基本规则:-)

+0

昨晚我真的找到一个帖子,你给出了同样的例子。我当时不明白,现在也不明白。有时候我需要一个具体的例子,在它陷入之前。在我看来,你似乎只是创建另一个花哨的包装类,调用getString()方法而不是toString()方法。你将如何使用MadProgrammer的Item类和StringValue类将项添加到ComboBoxModel?此外,由于只有渲染器知道文本,所以如何按排序顺序添加ietms。你的StringValue类是否实现了Comparable? – camickr 2013-03-03 19:35:08

+0

价值/描述对有很多用途。例如一个产品。 “1”是一个锤子(打在我头上),“2”是一个螺丝刀。某处你需要保持价值/描述的映射。所以说一个对象不能把这两个属性放在一起对我来说没有任何意义。现在,这两个属性在一个类中可以通过使用适当的渲染器来选择要在组合框中显示哪些属性。 – camickr 2013-03-04 00:34:40

+0

此外,您的产品可能会有多种不同语言的说明。因此,当您填充Item类时,您将直接从数据库或资源文件或任何您使用的内容填充适当的描述。 – camickr 2013-03-04 00:41:33