java - 在两个 JComboBox 之间共享相同的模型

标签 java swing jcombobox comboboxmodel

我有一个人[]和三个人(p1、p2、p3)。 Person 类有两个属性 nameemail

我想在一个 JComboBox 中添加 Person[] 的所有姓名,在另一个 JComboBox 中添加所有电子邮件。

我使用了以下代码。

    Person p1 = new Person("Smith", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4e3d23273a260e232f2722602d2123" rel="noreferrer noopener nofollow">[email protected]</a>");
    Person p2 = new Person("Tom", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f3879c9eb3949e929a9fdd909c9e" rel="noreferrer noopener nofollow">[email protected]</a>");
    Person p3 = new Person("John","<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a5cfcacdcbe5c8c4ccc98bc6cac8" rel="noreferrer noopener nofollow">[email protected]</a>");

    Person[] per_arr = new Person[] { p1, p2, p3};

    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    JComboBox<String> combo1 = new JComboBox<String>();
    JComboBox<String> combo2 = new JComboBox<String>();

    for (Person p : per_arr) {
        combo1.addItem(p.getName());
        combo2.addItem(p.getEmail());
    }
    panel.add(combo1);
    panel.add(combo2);
    frame.setContentPane(panel);
    frame.pack();
    frame.setVisible(true);

但我不想这样使用。我想使用两个相同型号的组合框。我尝试使用 DefaultComboBoxModel 并覆盖 getElementAt() 方法,如下所示。

public class MyModel extends DefaultComboBoxModel<Object> {

public MyModel(Object[] items) {
    super(items);
}

@Override
public Object getElementAt(int index) {
    if (super.getElementAt(index) instanceof Person) {
        return (Person)super.getElementAt(index);
    } else {
        return null;
    }
}

}

上面的 ComboBoxModel 只给我 Person 对象。

问题是如何在一个 JComboBox 中添加 Person[] 的所有姓名,并在另一个 JComboBox 中添加所有电子邮件使用相同的 ComboBoxModel

最佳答案

使用 ComboBoxModel 的一个实例和 JComboBox 的两个实例,每个都有相同的型号。让每个JComboBox有定制renderer显示所需的 Person属性JComboBox

在下面的示例中,每个组合都有自己的单个渲染器实例,该渲染器实现 strategy pattern ,传递 Function<Person, String> 当调用渲染器时选择正确的属性:

DefaultComboBoxModel model = new DefaultComboBoxModel(…);
JComboBox<String> combo1 = new JComboBox<>(model);
combo1.setRenderer(new PersonRenderer(Person::getName));
JComboBox<String> combo2 = new JComboBox<>(model);
combo2.setRenderer(new PersonRenderer(Person::getEmail));

image

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.util.function.Function;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;

/**
 * @see http://stackoverflow.com/a/37222598/230513
 */
public class ComboRendererTest {

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new FlowLayout());
        DefaultComboBoxModel model = new DefaultComboBoxModel(new Person[]{
            new Person("Alpher", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ff9e938f979a8dbf9a879e928f939ad19c9092" rel="noreferrer noopener nofollow">[email protected]</a>"),
            new Person("Bethe", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a6c4c3d2cec3e6c3dec7cbd6cac388c5c9cb" rel="noreferrer noopener nofollow">[email protected]</a>"),
            new Person("Gammow", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2e494f434341596e4b564f435e424b004d4143" rel="noreferrer noopener nofollow">[email protected]</a>")});
        JComboBox<String> combo1 = new JComboBox<>(model);
        combo1.setRenderer(new PersonRenderer(Person::getName));
        JComboBox<String> combo2 = new JComboBox<>(model);
        combo2.setRenderer(new PersonRenderer(Person::getEmail));
        f.add(combo1);
        f.add(combo2);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class PersonRenderer extends DefaultListCellRenderer {

        Function<Person, String> personAttribute;

        public PersonRenderer(Function<Person, String> personAttribute) {
            this.personAttribute = personAttribute;
        }

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object
            value, int index, boolean isSelected, boolean cellHasFocus) {
            JLabel l = (JLabel) super.getListCellRendererComponent(
                list, value, index, isSelected, cellHasFocus);
            Person p = (Person) value;
            l.setText(personAttribute.apply(p));
            return l;
        }
    }

    private static class Person {

        private final String name;
        private final String email;

        public Person(String name, String email) {
            this.name = name;
            this.email = email;
        }

        public String getName() {
            return name;
        }

        public String getEmail() {
            return email;
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new ComboRendererTest()::display);
    }
}

关于java - 在两个 JComboBox 之间共享相同的模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37222407/

相关文章:

java - 使用 Android 将文本文件上传到 Google 云端硬盘

java - 同时抛出两个异常

java - 如何在 JTable java 中搜索元素?

java - GroupLayout:组件未按预期布局?

java - 设置 JComboBox 的背景?

java - java中如何将纯文本超链接转换为html超链接?

Java BigDecimal from String without decimal places 但 asume 最后两位数字为 decimal

java - 从 JTextField 中读取特定文本

Java:在 AbstractTableModel 中添加一行 JCombobox

java - 如何将 actionPerformed( ActionEvent e ) 与多个按钮一起使用?