Дизайн: 2 jcombobox, список блока 2 зависит от выбора из блока 1, данные из XML

Я ошеломлен попыткой найти решение этой проблемы - это побочный продукт неопытности.

Моя цель - прочитать входной файл XML, сохранить информацию из XML и заполнить два поля со списком данными из XML. Содержимое второго поля со списком будет меняться в зависимости от выбора в первом.

Учитывая эту структуру XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Node>
    <ID>Unique string</ID>
    <Name>Unique string</Name>
    <Code>Generic string<Code>
    <Kind>Generic string</Kind>
    <Frame>Generic string</Frame>
            ...
</Node>
    ...
</Category>

Первое поле со списком: должно содержать только уникальные значения, найденные в разделе «Вид».

Второе поле со списком: содержит ВСЕ записи имени от каждого узла, вид которого равен виду, выбранному в первом поле со списком.

Что касается источника XML: он поддерживается и генерируется извне. Значения в разделе идентификаторов всегда будут уникальными. Значения в разделе Имя всегда будут уникальными. Схема (предположительно) никогда не изменится. Новые уникальные значения могут появиться в разделе Kind в будущем.

Мое предлагаемое решение: создать класс XMLNode для представления узла из источника XML. Члены класса XMLNode соответствуют тегам в каждом узле. Переберите все узлы и создайте XMLNode для каждого. При прохождении по узлам: добавьте объекты XMLNode в хэш-карту, указав Keys = XMLNode.ID и vals = XMLNode. Создайте массив уникальных видов.

Заполните поле со списком один из массива записей вида. Заполните поле со списком два из данных имени для каждого.

Это подходящий подход, или я упустил лучшее / более легкое / более элегантное решение? Если я на правильном пути, есть ли очевидные недостатки в моем предложенном решении?

 NickAbbey16 окт. 2012 г., 18:53
Предложение mKorbel, приведенное ниже, помогает понять логику зависимости второго поля от выбора первого, что очень полезно. Однако я все еще не уверен, есть ли лучший способ импортировать данные XML и представлять их внутри моей программы. Некоторые отзывы по этому поводу были бы оценены разумом улья stackoverflow ...

Ответы на вопрос(2)

ComboBoxModel (Java6) для хранения предметов дляJComboBox

aВсе обновления JComboBox и его ComboBoxModel должны выполняться на EDT

перенаправить всеFileIO или жеDatabase событие вRunnable#Thread или жеSwingWorker

может быть, эта логика может помочь вам,

код

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class ComboBoxTwo extends JFrame implements ActionListener, ItemListener {

    private static final long serialVersionUID = 1L;
    private JComboBox mainComboBox;
    private JComboBox subComboBox;
    private Hashtable<Object, Object> subItems = new Hashtable<Object, Object>();

    public ComboBoxTwo() {
        String[] items = {"Select Item", "Color", "Shape", "Fruit"};
        mainComboBox = new JComboBox(items);
        mainComboBox.addActionListener(this);
        mainComboBox.addItemListener(this);
        //prevent action events from being fired when the up/down arrow keys are used
        //mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
        getContentPane().add(mainComboBox, BorderLayout.WEST);
        subComboBox = new JComboBox();//  Create sub combo box with multiple models
        subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
        subComboBox.addItemListener(this);
        getContentPane().add(subComboBox, BorderLayout.EAST);
        String[] subItems1 = {"Select Color", "Red", "Blue", "Green"};
        subItems.put(items[1], subItems1);
        String[] subItems2 = {"Select Shape", "Circle", "Square", "Triangle"};
        subItems.put(items[2], subItems2);
        String[] subItems3 = {"Select Fruit", "Apple", "Orange", "Banana"};
        subItems.put(items[3], subItems3);
//      mainComboBox.setSelectedIndex(1);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String item = (String) mainComboBox.getSelectedItem();
        Object o = subItems.get(item);
        if (o == null) {
            subComboBox.setModel(new DefaultComboBoxModel());
        } else {
            subComboBox.setModel(new DefaultComboBoxModel((String[]) o));
        }
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            if (e.getSource() == mainComboBox) {
                if (mainComboBox.getSelectedIndex() != 0) {
                    FirstDialog firstDialog = new FirstDialog(ComboBoxTwo.this,
                            mainComboBox.getSelectedItem().toString(), "Please wait,  Searching for ..... ");
                }
            } 
        }
    }

    private class FirstDialog extends JDialog {

        private static final long serialVersionUID = 1L;

        FirstDialog(final Frame parent, String winTitle, String msgString) {
            super(parent, winTitle);
            setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
            JLabel myLabel = new JLabel(msgString);
            JButton bNext = new JButton("Stop Processes");
            add(myLabel, BorderLayout.CENTER);
            add(bNext, BorderLayout.SOUTH);
            bNext.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent evt) {
                    setVisible(false);
                }
            });
            javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    setVisible(false);
                }
            });
            t.setRepeats(false);
            t.start();
            setLocationRelativeTo(parent);
            setSize(new Dimension(400, 100));
            setVisible(true);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new ComboBoxTwo();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
 NickAbbey16 окт. 2012 г., 18:47
Это очень полезно для понимания того, как заставить эти два блока взаимодействовать друг с другом, спасибо. Один вопрос, что делает эта строка:subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4?
 mKorbel16 окт. 2012 г., 19:27
setPreferredSize требуемый размер на экране, принятыйLayoutManagers
Решение Вопроса

NodeImporter анализирует XML. В NodeImporter источник XML анализируется и представляется как HashMap из HashMaps. Внешний HashMap (Key, Value) - (Kind, (HashMap (Key, Value)). Внутренний HashMap (Key, Value) - (UinqueID, Node) для конечного результата (Kind, (UniqueID, Node)). Я называю окончательный результат «FilterMap». Все поля и методы NodeImporter являются частными, за исключением конструктора и метода получения для FilterMap. Класс, которому нужны данные для построения комбинированных блоков, получает FilterMap из экземпляра NodeImporter. затем получите ключи внешнего HashMap для создания первой ComboBoxModel, которая может с такой же легкостью получить внутренний HashMap, который будет использоваться в качестве HashMap для второго поля со списком.

псевдокод для настройки:

Класс NodeImporter, созданный из членов класса:

arrayList(String) uniqueKinds = null  
arrayList(Node) allNodes  = null  
HashMap(String, HashMap(String,Node))) filteredNodes = null  

Класс NodeImporter конструктор:

open XML  
while xml source has next  
  {  
  add next node to allNodes, key = node.uniqueId, Val = node  
  if next node.kind not in uniqueKinds, add node.kind to uniqueKinds  
  }



ClassNodeImporter method makeFilteredeMap:  

    private boolean makeFilteredeMap() {
        if (uniqueKinds.isEmpty()) {
            return false;
        } else {
            for (String k : uniqueKinds) {
                HashMap<String, Node> aMap = new HashMap<String, Node>();
                for (Node n : allNodes) {
                    if (n.getKind().equals(k)) {
                        aMap.put(n.getCode(), n);
                    }
                }
                filteredNodes.put(k, aMap);
            }
            return true;
        }
    }

Ваш ответ на вопрос