java - 动态填充 JComboBox 而不使用关联数组

标签 java swing jcombobox

我有一个 JComboBox,其中填充了文件 (XML) 中的信息,并且我希望使用基于第一个 ComboBox 中所选项目的信息填充第二个 ComboBox .

我的英语有点生疏,所以我给你看一个例子,这是我的 XML 文件:

<components>
    <house id="Kitchen">
        <espresso_machine>C</espresso_machine>
        <coffee_machine>C</coffee_machine>
        <coffee_pot>C</coffee_pot>
        <kettle>C</kettle>
        <toaster>C</toaster>
        <microwave>C</microwave>
        <oven>C</oven>
        <frying_pan>C</frying_pan>
        <stand_mixer>C</stand_mixer>
        <extrator_fan>C</extrator_fan>
        <tv>C</tv>
        <compact_flurescent>C</compact_flurescent>
        <flurescent_tube>C</flurescent_tube>
        <dishwasher>C</dishwasher>
        <freezer>C</freezer>
        <blender>C</blender>
        <can_opener>C</can_opener>
        <cooking_range>C</cooking_range>
        <popcorn_popper>C</popcorn_popper>
    </house>
    <house id="Laundry">
        <washing_machine>C</washing_machine>
        <clothes_dryer>C</clothes_dryer>
        <vacuum_handler>C</vacuum_handler>
        <compact_fluorescent>C</compact_fluorescent>
        <iron>C</iron>
    </house>
    <house id="Room">
        <compact_fluorescent>C</compact_fluorescent>
        <ac_room>C</ac_room>
        <tv>C</tv>
        <cell_phone_charger>C</cell_phone_charger>
        <clock_radio>C</clock_radio>
    </house>
</components>

我的第一个组合框具有属性“id”内容(厨房、洗衣房、房间)。 我第一次打开 JDialog 时,选择了“厨房”选项(在第一个组合框中),第二个组合框具有所有子元素限定名称(浓缩咖啡机、咖啡机、咖啡壶、水壶等)

当我更改第一个组合框中的所选项目时,我需要更改第二个组合框的内容。

这是我的代码示例:

houseSpaceCombo = new JComboBox(configs.XMLreaderDOM4J.readHouseTypeID());
equipmentsCombo = new JComboBox(configs.XMLreaderDOM4J.readHouseEquipmentsID(houseSpaceCombo.getSelectedItem().toString()));

另外两种方法:

public static String[] readHouseTypeID()
{      
    Element root = getDoc().getRootElement();

    ArrayList<String> attributeAL = new ArrayList<>();

    for (Iterator i = root.elementIterator( "house" ); i.hasNext();)
    {
        Element foo = (Element) i.next();
        attributeAL.add(foo.attributeValue("id").toString());
    }

    String[] vec = convertArrayListToArray(attributeAL);

    return vec;
}

public static String[] readHouseEquipmentsID(String selectedItem)
{       
    Element root = getDoc().getRootElement();
    Element innerElement;

    ArrayList<String> attributeAL = new ArrayList<>();

    for ( Iterator i = root.elementIterator( "house" ); i.hasNext(); ) {
    Element element = (Element) i.next();
    if(element.attributeValue("id").equals(selectedItem)) {
        for ( Iterator j = element.elementIterator(); j.hasNext(); ) {
            innerElement = (Element) j.next();
            String tmp = innerElement.getQualifiedName().replace("_", " ");

            attributeAL.add(tmp);

        }       
    }
}

String[] vec = convertArrayListToArray(attributeAL);

    return vec;
}

我能做什么?

最佳答案

我将创建一个以 id 属性为键的 Map,其中包含所有子元素的 ComboBoxModel

当第一个组合框的选择项发生变化时,我会简单地在Map中查找值,并将第二个组合框的模型设置为检索到的值

示例

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SwitchComboBoxModels {

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

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

                JFrame frame = new JFrame("Testing");
                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 Map<String, ComboBoxModel> models;
        private JComboBox cbMain;
        private JComboBox cbSub;

        public TestPane() {
            models = new HashMap<>(25);
            models.put("Kitchen", createComboBoxModel("espresso_machine",
                    "coffee_machine",
                    "coffee_pot",
                    "kettle",
                    "toaster",
                    "microwave",
                    "oven",
                    "frying_pan",
                    "stand_mixer",
                    "extrator_fan",
                    "tv",
                    "compact_flurescent",
                    "flurescent_tube",
                    "dishwasher",
                    "freezer",
                    "blender",
                    "can_opener",
                    "cooking_range",
                    "popcorn_popper"));
            models.put("Laundry", createComboBoxModel("washing_machine",
                    "clothes_dryer",
                    "vacuum_handler",
                    "compact_fluorescent",
                    "iron"));

            ComboBoxModel mainModel = createComboBoxModel("Kitchen", "Laundry");

            cbMain = new JComboBox();
            cbSub = new JComboBox();
            cbMain.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    cbSub.setModel(models.get((String) cbMain.getSelectedItem()));
                }
            });
            cbMain.setModel(mainModel);
            cbSub.setModel(models.get((String) cbMain.getSelectedItem()));

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(cbMain, gbc);
            add(cbSub, gbc);

        }

        protected ComboBoxModel createComboBoxModel(String... values) {

            return new DefaultComboBoxModel(values);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }
    }
}

其他示例

从您的示例代码中,您已经在内存中拥有了模型。在此阶段您有两个选择。

您可以通过解析内存文档来构建一系列 ComboBoxModel,或者在每次更改时从 XML 动态构建模型。

我会在开始时解析模型并缓存结果,因为 XML DOM 占用内存

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Map;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class SwitchComboBoxModels {

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

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

                JFrame frame = new JFrame("Testing");
                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 Document xmlDoc;
        private JComboBox cbMain;
        private JComboBox cbSub;
        private XPathFactory xFactory;
        private XPath xPath;

        public TestPane() {

            try {

                readModel();
                ComboBoxModel mainModel = createComboBoxModelByID(find("/components/house[@id]"));

                cbMain = new JComboBox();
                cbSub = new JComboBox();
                cbMain.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        updateSubModel();
                    }
                });
                cbMain.setModel(mainModel);
                updateSubModel();

                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                add(cbMain, gbc);
                add(cbSub, gbc);

            } catch (XPathExpressionException | ParserConfigurationException | SAXException | IOException exp) {
                exp.printStackTrace();
            }

        }

        protected void updateSubModel() {
            try {
                String key = (String) cbMain.getSelectedItem();
                Node parent = findFirst("/components/house[@id='" + key + "']");
                ComboBoxModel subModel = createComboBoxModel(parent.getChildNodes());
                cbSub.setModel(subModel);
            } catch (XPathExpressionException exp) {
                exp.printStackTrace();
            }
        }

        protected void readModel() throws ParserConfigurationException, SAXException, IOException {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            xmlDoc = factory.newDocumentBuilder().parse(getClass().getResourceAsStream("/Model.xml"));
        }

        protected NodeList find(String xPathQuery) throws XPathExpressionException {
            XPathExpression xExpress = getXPath().compile(xPathQuery);
            return (NodeList) xExpress.evaluate(xmlDoc.getDocumentElement(), XPathConstants.NODESET);
        }

        protected Node findFirst(String xPathQuery) throws XPathExpressionException {
            XPathExpression xExpress = getXPath().compile(xPathQuery);
            return (Node) xExpress.evaluate(xmlDoc.getDocumentElement(), XPathConstants.NODE);
        }

        public XPath getXPath() {
            if (xPath == null) {
                xPath = getXPathFactory().newXPath();
            }
            return xPath;
        }

        protected XPathFactory getXPathFactory() {

            if (xFactory == null) {

                xFactory = XPathFactory.newInstance();

            }

            return xFactory;

        }

        public String getAttributeValue(Node nNode, String sAttributeName) {
            Node nAtt = nNode.getAttributes().getNamedItem(sAttributeName);
            return nAtt == null ? null : nAtt.getNodeValue();
        }

        protected ComboBoxModel createComboBoxModelByID(NodeList nodeList) {

            DefaultComboBoxModel model = new DefaultComboBoxModel();
            for (int index = 0; index < nodeList.getLength(); index++) {
                Node node = nodeList.item(index);
                model.addElement(getAttributeValue(node, "id"));
            }

            return model;

        }

        protected ComboBoxModel createComboBoxModel(NodeList nodeList) {

            DefaultComboBoxModel model = new DefaultComboBoxModel();
            for (int index = 0; index < nodeList.getLength(); index++) {
                Node node = nodeList.item(index);
                if (node.getNodeType() == 1) {
                    model.addElement(node.getNodeName());
                }
            }

            return model;

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }
    }
}

关于java - 动态填充 JComboBox 而不使用关联数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17872888/

相关文章:

java - java里面的Scrapy?

java - 在 Maven 中使用不同版本的库构建模块

java - 如何在 Swing GUI 中遍历到下一页/上一页

Java:语法突出显示组件键事件

java - 让 JComboBox 在选择项目时更改显示的项目

java - 在生产中运行 Spring Boot 微服务是否需要大型企业的嵌入式 Tomcat 服务器的许可证?

java - 什么是平等契约(Contract)的重要字段(有效的 java 项目 8)

Java 单选按钮更改另一个面板中的按钮文本

java - 如何在 JComboBox 中显示自定义对象(使用 toString)

java - 使用 JComboBox 调整 JTextField