89758

Design: 2 jcomboboxes, box 2 list depends on selection from box 1, data from XML

Question:

I'm overwhelmed with attempting to design a solution for this problem - it's a by-product of inexperience.

My goal is to read an XML input file, store the information from the XML and populate two combo boxes with data from the XML. The content of the second combo box will change based on the selection in the first.

Given this XML structure:

<?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>

First combo box: Must contain only the unique values found in the the Kind section.

Second combo box: Contains ALL of the Name entries from every Node whose Kind equals the Kind selected in the first combo box.

Regarding the XML source: It is externally maintained and generated. The values in the ID section are always going to be unique. The values in the Name section are always going to be unique. The schema will (supposedly) never change. New unique values may appear in the Kind section in the future.

My proposed solution: Create a class XMLNode to represent a Node from the XML source. Members of class XMLNode correspond to the tags in each Node. Loop through all the Nodes and create an XMLNode for each one. While looping through nodes: Add XMLNode objects in a hash map, with Keys = XMLNode.ID and vals = the XMLNode. Create an array of unique Kinds.

Populate combo box one from the array of Kind entries. Populate combo box two from the Name data for each .

Is this an appropriate approach, or have I overlooked a better/easier/more elegant solution? If I'm on the right track, are there any obvious flaws to my proposed solution?

Answer1:

<ul><li>

use <a href="http://docs.oracle.com/javase/6/docs/api/javax/swing/ComboBoxModel.html" rel="nofollow">ComboBoxModel (Java6)</a> for storing Items for <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html" rel="nofollow">JComboBox</a>

</li> <li>

a<a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html" rel="nofollow">ll updates to the JComboBox and its ComboBoxModel must be done on EDT</a>

</li> <li>

redirect all FileIO or Database event to the Runnable#Thread or SwingWorker

</li> <li>

maybe this logics can help you,

</li> </ul>

code

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

Answer2:

I ended up with a class NodeImporter and a class Node. Node represents a node, NodeImporter parses the XML. In the NodeImporter, the XML source is parsed and represented as a HashMap of HashMaps. The outer HashMap (Key,Value) is (Kind,(HashMap(Key,Value)). The inner HashMap (Key,Value) is (UinqueID,Node) for a final result of (Kind,(UniqueID,Node)). I call the final result "filteredMap". All of NodeImporter's fields and methods are private, except for the constructor, and a getter for filteredMap. The class that needs the data to build the combo boxes gets filteredMap from an instance of NodeImporter. It can then get the keys of the outer HashMap to build the first ComboBoxModel. It can just as easily get the inner HashMap to be used as the HashMap for the second combo box.

pseudo code for setup:

Class NodeImporter built with class members:

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

Class NodeImporter constructor:

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

Recommend

  • Buttons are being hidden by background image
  • Validating form fields before submit
  • How IvyDE can coexist with command-line Ant and Ivy?
  • Vector erase function in for loop is not erasing vector of classes properly
  • Gson and Google
  • How to fix NotOfficeXmlFileException in java Apache POI?
  • How to set Spark configuration properties using Apache Livy?
  • Check if number is in range on 8051
  • How to get Eclipse to show Javadoc for javax annotations
  • Hashtable. How it works?
  • Android 6.0 USB Mass Storage
  • python cyclic shifting of the characters in the string
  • Android: Setting List Adapter for a ListFragment after Orientation Change Results in an Empty List
  • Avoid Veracode CWE-80: Improper Neutralization of Script-Related HTML in jquery htm() method
  • Grails filters: can't make it work !
  • How to get poltergeist/PhantomJS to delay returning the page to Capybara until AJAX is loaded?
  • Tkinter Grid Columnspan ignored
  • Visual Studio 2017 Javascript How to set 'experimentaldecorators'
  • sed - removing last comma from listed value after doing a replace
  • Capture literal brackets inside brackets in pyparsing
  • Declaring a type class for multiplication of an N-by-N-element matrix and an N-element column vector
  • Error “undefined variable at noteLine” in FLWOR expression when returning multiple nodes
  • How can I transform an array of characters with a few lines of code to a data.frame?
  • ruby - lazily iterate through an array
  • FParsec: how to combine parsers so that they will be matched in arbitrary order
  • JProgressBar text overflow
  • Aspect ratio behaviour of - internal dimensions and element size
  • Change color of row programmatically in WatchKit
  • Level-order tree traversal
  • Pandas v0.20 returns NotImplemented when multiplying dataframe columns
  • Can't connect Entity Framework to local SQL Server Express
  • Whats the right place for testhelper-classes? (phpunit/best practise)
  • Sympy: working with equalities manually
  • Stitching 2 images (OpenCV)
  • SQL query to group by maximal sets of a column having inner consecutive distances below a threshold
  • Efficient User-Agent Regex to find Safari in Python
  • Is it possible to get the word under the mouse cursor in a ``?
  • Possible to get mouse events fired when cursor is outside page?
  • How does this usort cmp function actually work?
  • Calling Worksheet functions from vba in foreign language versions of Excel