|
1. Introduction | |
2. Decision tree GUI code |
In this WWW page I have presented an entire GUI application example based on the decision tree example programme given earlier. I have included in the example a further illustration of the append method found in the JTextArea class and illustrated previously with respect to JButton Swing objects. I have also included a further example of the showMessageDialog method which I have used for error messaging. The example is no longer generic (as was the case for previous decision tree example) in that it operates with a hard coded tree, i.e. it cannot be passed a tree from an application class (although this would not be difficult to include).
The code presented in Table 1 is the main body of the decision tree example. An accompanying application class is given in Table 2 and some example output in Figure 1. An example of the error message window produced using the showMessageDialog method is given in Figure 2.
// DECISION TREE // Frans Coenen // Thursday 15 August 2002 // Revised Thursday 20 March 2003 // Department of Computer Science, University of Liverpool import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DecisionTreeGui extends JFrame implements ActionListener { /* ------------------------------- */ /* */ /* FIELDS */ /* */ /* ------------------------------- */ /* NESTED CLASS */ private class BinTree { /* FIELDS */ private int nodeID; private String questOrAns = null; private BinTree yesBranch = null; private BinTree noBranch = null; /* CONSTRUCTOR */ public BinTree(int newNodeID, String newQuestAns) { nodeID = newNodeID; questOrAns = newQuestAns; } } /* GUI FIELDS */ private JTextArea aTextArea = new JTextArea(20,40); private JButton pushButtonYes = new JButton("Yes"); private JButton pushButtonGenerate = new JButton("Generate"); private JButton pushButtonQuery = new JButton("Query"); private JButton pushButtonOutput = new JButton("Output"); private JButton pushButtonNo = new JButton("No"); private int numButtonPresses = 0; /* OTHER FIELDS */ // Reference to start Node of decision tree BinTree rootNode = null; // Marker reference BinTree currentNode = null; /* ------------------------------------ */ /* */ /* CONSTRUCTORS */ /* */ /* ------------------------------------ */ /* Default Constructor */ public DecisionTreeGui(String text) { super(text); Container container = getContentPane(); container.setLayout(new FlowLayout()); container.setBackground(Color.yellow); /// Text fields container.add(new JScrollPane(aTextArea)); // Button container.add(pushButtonYes); container.add(pushButtonGenerate); container.add(pushButtonQuery); container.add(pushButtonOutput); container.add(pushButtonNo); // Register event handlers pushButtonYes.addActionListener(this); pushButtonGenerate.addActionListener(this); pushButtonQuery.addActionListener(this); pushButtonOutput.addActionListener(this); pushButtonNo.addActionListener(this); } /* ----------------------------------------------- */ /* */ /* GUI METHODS */ /* */ /* ----------------------------------------------- */ /* ACTION PERFORMED */ /* Process button press events */ public void actionPerformed(ActionEvent event) { numButtonPresses++; if (event.getActionCommand().equals("Yes")) yesButtonPressed(); else if (event.getActionCommand().equals("Generate")) GenerateButtonPressed(); else if (event.getActionCommand().equals("Query")) QueryButtonPressed(); else if (event.getActionCommand().equals("Output")) outputButtonPressed(); else if (event.getActionCommand().equals("No")) noButtonPressed(); } /* YES BUTTON PRESSED */ private void yesButtonPressed() { // Check if tree exists if (rootNode == null) { noTreeToQueryErrorMessage(); return; } // Check if query process has been initialised if (currentNode == null) { noCurrentNodeErrorMessage(); return; } // If tree exists process response aTextArea.append("Yes\n"); currentNode = currentNode.yesBranch; outputNode(); } /* GENERATE BUTTON PRESSED */ private void GenerateButtonPressed() { aTextArea.append("GENERATE DECISION TREE\n"); aTextArea.append("================\n"); createRoot(1,"Does animal eat meat?"); addYesNode(1,2,"Does animal have stripes?"); addNoNode(1,3,"Does animal have stripes?"); addYesNode(2,4,"Animal is a Tiger"); addNoNode(2,5,"Animal is a Leopard"); addYesNode(3,6,"Animal is a Zebra"); addNoNode(3,7,"Animal is a Horse"); aTextArea.append("\n"); } /* QUERY BUTTON PRESSED */ private void QueryButtonPressed() { // Check if tree exists if (rootNode == null) { noTreeToQueryErrorMessage(); return; } // If tree exists commence query process. currentNode = rootNode; aTextArea.append("QUERY DECISION TREE\n"); aTextArea.append("=============\n"); outputNode(); } /* OUTPUT BUTTON PRESSED */ private void outputButtonPressed() { // Check if tree exists if (rootNode == null) { noTreeToOutputErrorMessage(); return; } // If tree exists output aTextArea.append("OUTPUT DECISION TREE\n"); aTextArea.append("================\n"); outputBinTree(); aTextArea.append("\n"); } /* NO BUTTON PRESSED */ private void noButtonPressed() { // Check if tree exists if (rootNode == null) { noTreeToQueryErrorMessage(); return; } // Check if query process has been initialised if (currentNode == null) { noCurrentNodeErrorMessage(); return; } // If tree exists process response aTextArea.append("No\n"); currentNode = currentNode.noBranch; outputNode(); } /* ----------------------------------------------- */ /* */ /* TREE BUILDING METHODS */ /* */ /* ----------------------------------------------- */ /* CREATE ROOT NODE */ public void createRoot(int newNodeID, String newQuestAns) { rootNode = new BinTree(newNodeID,newQuestAns); aTextArea.append("Created root node " + newNodeID + "\n"); } /* ADD YES NODE */ public void addYesNode(int existingNodeID, int newNodeID, String newQuestAns) { // Check if root node exists if (rootNode == null) { noRootNodeErrorMessage(); return; } // Query tree if (searchTreeAndAddYesNode(rootNode,existingNodeID,newNodeID,newQuestAns)) { aTextArea.append("Added node " + newNodeID + " onto \"yes\" branch of node " + existingNodeID + "\n"); } else aTextArea.append("Node " + existingNodeID + " not found\n"); } /* SEARCH TREE AND ADD YES NODE */ private boolean searchTreeAndAddYesNode(BinTree currentNode, int existingNodeID, int newNodeID, String newQuestAns) { if (currentNode.nodeID == existingNodeID) { // Found node if (currentNode.yesBranch == null) currentNode.yesBranch = new BinTree(newNodeID,newQuestAns); else { aTextArea.append("WARNING: Overwriting previous node " + "(id = " + currentNode.yesBranch.nodeID + ") linked to yes branch of node " + existingNodeID + "\n"); currentNode.yesBranch = new BinTree(newNodeID,newQuestAns); } return(true); } else { // Try yes branch if it exists if (currentNode.yesBranch != null) { if (searchTreeAndAddYesNode(currentNode.yesBranch, existingNodeID,newNodeID,newQuestAns)) { return(true); } else { // Try no branch if it exists if (currentNode.noBranch != null) { return(searchTreeAndAddYesNode(currentNode.noBranch, existingNodeID,newNodeID,newQuestAns)); } else return(false); // Not found here } } return(false); // Not found here } } /* ADD NO NODE */ public void addNoNode(int existingNodeID, int newNodeID, String newQuestAns) { // Check if root node exists if (rootNode == null) { noRootNodeErrorMessage(); return; } // Search tree if (searchTreeAndAddNoNode(rootNode,existingNodeID,newNodeID,newQuestAns)) { aTextArea.append("Added node " + newNodeID + " onto \"no\" branch of node " + existingNodeID + "\n"); } else aTextArea.append("Node " + existingNodeID + " not found\n"); } /* SEARCH TREE AND ADD NO NODE */ private boolean searchTreeAndAddNoNode(BinTree currentNode, int existingNodeID, int newNodeID, String newQuestAns) { if (currentNode.nodeID == existingNodeID) { // Found node if (currentNode.noBranch == null) currentNode.noBranch = new BinTree(newNodeID,newQuestAns); else { aTextArea.append("WARNING: Overwriting previous node " + "(id = " + currentNode.noBranch.nodeID + ") linked to no branch of node " + existingNodeID + "\n"); currentNode.noBranch = new BinTree(newNodeID,newQuestAns); } return(true); } else { // Try yes branch if it exists if (currentNode.yesBranch != null) { if (searchTreeAndAddNoNode(currentNode.yesBranch, existingNodeID,newNodeID,newQuestAns)) { return(true); } else { // Try no branch if it exists if (currentNode.noBranch != null) { return(searchTreeAndAddNoNode(currentNode.noBranch, existingNodeID,newNodeID,newQuestAns)); } else return(false); // Not found here } } else return(false); // Not found here } } /* --------------------------------------------- */ /* */ /* TREE QUERY METHODS */ /* */ /* --------------------------------------------- */ /* OUTPUT NODE: First check: 1. That we have not arrived at the answer --- if so output result. 2. That no error has occurred in the construction of the tree (the tree must be balanced, e.g. body nodes must have "yes" and "no" branches) --- if so error. Otherwise output question. */ private void outputNode() { // Test for leaf node (answer) and missing branches if (currentNode.yesBranch==null) { if (currentNode.noBranch==null) aTextArea.append(currentNode.questOrAns + "\nEND\n\n"); else missingYesBranchErrorMessage(currentNode.questOrAns); // Return currentNode=null; return; } if (currentNode.noBranch==null) { missingNoBranchErrorMessage(currentNode.questOrAns); // Return currentNode=null; return; } // Question aTextArea.append(currentNode.questOrAns + " (enter \"Yes\" or \"No\")\n"); } /* ----------------------------------------------- */ /* */ /* TREE OUTPUT METHODS */ /* */ /* ----------------------------------------------- */ /* OUTPUT BIN TREE */ private void outputBinTree() { outputBinTree("1",rootNode); } private void outputBinTree(String tag, BinTree currentNode) { // Check for empty node if (currentNode == null) return; // Output aTextArea.append("[" + tag + "] nodeID = " + currentNode.nodeID + ", question/answer = " + currentNode.questOrAns + "\n"); // Go down yes branch outputBinTree(tag + ".1",currentNode.yesBranch); // Go down no branch outputBinTree(tag + ".2",currentNode.noBranch); } /* ------------------------------------------------------ */ /* */ /* ERROR MESSAGES */ /* */ /* ------------------------------------------------------ */ private void noRootNodeErrorMessage() { JOptionPane.showMessageDialog(null,"ERROR 1: No root node! " + "Decision tree must include a single root node.\n\n"); } private void noTreeToQueryErrorMessage() { JOptionPane.showMessageDialog(null,"ERROR 2: No decision tree " + "created. To query a decision tree you must\nfirst create " + " a tree using the \"Generate\" button.\n\n"); } private void noTreeToOutputErrorMessage() { JOptionPane.showMessageDialog(null,"ERROR 3: No decision tree " + "created. To output a decision tree you must\nfirst create " + "a tree using the \"Generate\" button.\n\n"); } private void missingYesBranchErrorMessage(String text) { JOptionPane.showMessageDialog(null,"Error 4: Missing \"Yes\" " + "branch at \"" + text + "\" question.\n\n"); aTextArea.append("END\n\n"); } private void missingNoBranchErrorMessage(String text) { JOptionPane.showMessageDialog(null,"Error 5: Missing \"No\" " + "branch at \"" + text + "\" question.\n\n"); aTextArea.append("END\n\n"); } private void noCurrentNodeErrorMessage() { JOptionPane.showMessageDialog(null,"Error 6: False start. To query " + "the decision tree initialise the process\nusing the " + "\"query\" button.\n\n"); } } |
Table 1:Decision tree GUI (Swing example)
// DECISION TREE GUI APPLICATION // Frans Coenen // Thursday 15 August 2002 // Revised Thursday 20 March 2003 // Department of Computer Science, University of Liverpool import java.io.*; import javax.swing.*; class DecisionTreeGuiApp { /* ------------------------------- */ /* */ /* FIELDS */ /* */ /* ------------------------------- */ static BufferedReader keyboardInput = new BufferedReader(new InputStreamReader(System.in)); static DecisionTreeGui newTree; /* --------------------------------- */ /* */ /* METHODS */ /* */ /* --------------------------------- */ /* MAIN */ public static void main(String[] args) throws IOException { // Create instance of class DecisionTreeGui newTree = new DecisionTreeGui("Decision Tree Gui"); // Make window vissible newTree.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); newTree.setSize(500,400); newTree.setVisible(true); } } |
Table 2:Decision tree GUI Application Class
Figure 1: Some output produced by code presented in Tables 1 and 2
Figure 2: Example error message window
Created and maintained by Frans Coenen. Last updated 21 March 2003