Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
JTreeModel and do the same * thing in getChildCount(). Or, if you aren't using TreeNode you could * write your own TreeModel implementation. * Another solution would be to listen for TreeNodeExpansion events and * the first time a node has been expanded post the appropriate insertion * events. I would not recommend this approach though, the other two * are much simpler and cleaner (and are faster from the perspective of * how tree deals with it). * * NOTE: getAllowsChildren() can be messaged before getChildCount(). * For this example the nodes always allow children, so it isn't * a problem, but if you do support true leaf nodes you may want * to check for loading in getAllowsChildren too. * * @version 1.9 06/13/02 * @author Scott Violet */ public class DynamicTreeNode extends DefaultMutableTreeNode { // // Class stuff. /** Number of names. */ static protected float nameCount; /** Names to use for children. */ static protected String[] names; /** Used to generate the names. */ static protected Random nameGen; /** Number of children to create for each node. */ static protected final int DefaultChildrenCount = 7; static { { names = new String[] {"Mark Andrews", "Tom Ball", "Alan Chung", "Rob Davis", "Jeff Dinkins", "Amy Fowler", "James Gosling", "David Karlton", "Dave Kloba", "Dave Moore", "Hans Muller", "Rick Levenson", "Tim Prinzing", "Chester Rose", "Ray Ryan", "Georges Saab", "Scott Violet", "Kathy Walrath", "Arnaud Weber" }; } nameCount = (float)names.length; nameGen = new Random(System.currentTimeMillis()); } /** Have the children of this node been loaded yet? */ protected boolean hasLoaded; /** * Constructs a new DynamicTreeNode instance with o as the user * object. */ public DynamicTreeNode(Object o) { super(o); } public boolean isLeaf() { return false; } /** * If hasLoaded is false, meaning the children have not yet been * loaded, loadChildren is messaged and super is messaged for * the return value. */ public int getChildCount() { if(!hasLoaded) { loadChildren(); } return super.getChildCount(); } /** * Messaged the first time getChildCount is messaged. Creates * children with random names from names. */ protected void loadChildren() { DynamicTreeNode newNode; int randomIndex; for(int counter = 0; counter < DynamicTreeNode.DefaultChildrenCount; counter++) { randomIndex = (int)(nameGen.nextFloat() * nameCount); newNode = new DynamicTreeNode(names[randomIndex]); /* Don't use add() here, add calls insert(newNode, getChildCount()) so if you want to use add, just be sure to set hasLoaded = true first. */ insert(newNode, counter); } /* This node has now been loaded, mark it so. */ hasLoaded = true; } } ---------- END SOURCE ---------- (Review ID: 178832) ====================================================================== Name: jk109818 Date: 01/09/2003 FULL PRODUCT VERSION : java version "1.4.1" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21) Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode) FULL OPERATING SYSTEM VERSION : Microsoft Windows 2000 [Version 5.00.2195] A DESCRIPTION OF THE PROBLEM : Internal frames bugs: A. The initial focus value is lost B. The focus is lost when minimizing or closing an internal frame C. The "Alt-T" does not work when minimizing or closing an internal frame REGRESSION. Last worked in version 1.4.1 STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : A. The initial focus value is lost 1. Open a frame "New Tree/attributes". 2. Go to the field "show root". 3. Open anoter frame 4. Go back to the previous frame -> the focus is set back to the tree-field B. The focus is lost when iconify or closing an internal frame 1. Open a frame "New Tree attributes" or "NewSpilt Tree/attributes" 2. Open a frame "New Tree attributes" or "NewSpilt Tree/attributes" 3. Switch one frame to another and select a component. 4. Iconify or closing one frame. There is no focus anymore in the other frame. Even "Alt-T" does not work. C. The "Alt-T" does not work when minimizing or closing an internal frame 1. Open a frame "New Tree attributes" or "NewSplit Tree/attributes". 2. Minimize the frame 3. Press "Alt-T" to open the menu "Tree" --> Does not work EXPECTED VERSUS ACTUAL BEHAVIOR : A. The initial focus value is lost The expected result is that the focus will be on the field where you left latest. B. The focus is lost when minimizing or closing an internal frame The expected result is that the focus will be on the field where you left latest. C. The "Alt-T" does not work when minimizing or closing an internal frame The menu "Tree" must be opened. REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- //The code is taken from the demo version of JDK 1.4 "SampleTree" //SampleTee.java /* * Copyright (c) 2002 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * -Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduct the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that Software is not designed, licensed or intended for * use in the design, construction, operation or maintenance of any nuclear * facility. */ /* * Changes made, to generate some bugs * The Tree is now under MyInternalFrame */ /* * @(#)SampleTree.java 1.21 02/06/13 */ import javax.swing.JDesktopPane; import javax.swing.JInternalFrame; import javax.swing.DefaultDesktopManager; import java.awt.Container; import javax.swing.*; import javax.swing.event.*; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.*; import javax.swing.tree.*; /** * A demo for illustrating how to do different things with JTree. * The data that this displays is rather boring, that is each node will * have 7 children that have random names ... * * @version 1.21 06/13/02 * @author Scott Violet */ public class SampleTree { protected JFrame frame; private JDesktopPane desktop = new JDesktopPane(); //a specialized layered pane /** * Constructs a new instance of SampleTree. */ public SampleTree() { // Force SampleTree to come up in the Cross Platform L&F try { UIManager.setLookAndFeel (UIManager.getCrossPlatformLookAndFeelClassName()); // If you want the System L&F instead, comment out the above line and // uncomment the following: // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName ()); } catch (Exception exc) { System.err.println("Error loading L&F: " + exc); } JMenuBar menuBar = constructMenuBar(); frame = new JFrame("SampleTree"); frame.setJMenuBar(menuBar); frame.setBackground(Color.lightGray); desktop.setDesktopManager(new DefaultDesktopManager()); setContentPane(frame, desktop); frame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);}}); // frame.pack(); // this.createFrame(); frame.setSize(500, 500); frame.show(); } /** Construct a menu. */ private JMenuBar constructMenuBar() { JMenu menu; JMenuBar menuBar = new JMenuBar(); JMenuItem menuItem; /* Good ol exit. */ menu = new JMenu("File"); menuBar.add(menu); menuItem = menu.add(new JMenuItem("Exit")); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); }}); menu = new JMenu("Tree"); menu.setMnemonic('T'); menuBar.add(menu); menuItem = menu.add(new JMenuItem("New Tree")); menuItem.addActionListener(new NewOnlyTreeAction()); menuItem = menu.add(new JMenuItem("New Tree attributes")); menuItem.addActionListener(new NewAction()); menuItem = menu.add(new JMenuItem("NewSpilt Tree/attributes")); menuItem.addActionListener(new NewSplitAction()); return menuBar; } class NewOnlyTreeAction extends Object implements ActionListener { public void actionPerformed(ActionEvent e) { SampleTree.this.createFrame(true, false); } } class NewAction extends Object implements ActionListener { public void actionPerformed(ActionEvent e) { SampleTree.this.createFrame(false, false); } } class NewSplitAction extends Object implements ActionListener { public void actionPerformed(ActionEvent e) { SampleTree.this.createFrame(false, true); } } static public void main(String args[]) { new SampleTree(); } private void setContentPane(JFrame frame, Container contentPane) { frame.getRootPane().setContentPane(contentPane); } private void createFrame(boolean onlyTree, boolean split) { MyInternalFrame frame = new MyInternalFrame(onlyTree, split); frame.setVisible(true); //necessary as of 1.3; OK to use before desktop.add(frame); try { frame.setSelected(true); } catch (java.beans.PropertyVetoException e) {} } } //MyInternalFrame.java /** * Created for generating testing purposes * Most of the code is taken fram SampleTree */ import java.awt.event.*; import java.awt.*; import java.beans.PropertyVetoException; import javax.swing.*; import javax.swing.event.*; import javax.swing.JDesktopPane; import javax.swing.JInternalFrame; import javax.swing.DefaultDesktopManager; import java.awt.Container; import java.util.*; import javax.swing.tree.*; public class MyInternalFrame extends JInternalFrame { static int openFrameCount = 0; static final int xOffset = 30, yOffset = 30; /* Create the tree. */ protected JTree tree; /** Tree model. */ protected DefaultTreeModel treeModel; public MyInternalFrame(boolean onlyTree, boolean split) { super("Document #" + (++openFrameCount), true, //resizable true, //closable true, //maximizable true);//iconifiable //...Create the GUI and put it in the window... //...Then set the window size or call pack... setSize(300,300); //Set the window's location. setLocation(xOffset*(openFrameCount % 8), yOffset*(openFrameCount%8)); try { jbInit(onlyTree, split); } catch(Exception e) { e.printStackTrace(); } } private void jbInit(boolean onlyTree, boolean split) throws Exception { /* Create the JTreeModel. */ DefaultMutableTreeNode root = createNewNode("Root"); treeModel = new DefaultTreeModel(root); /* Create the tree. */ tree = new JTree(treeModel); /* Enable tool tips for the tree, without this tool tips will not be picked up. */ ToolTipManager.sharedInstance().registerComponent(tree); /* Make the tree use an instance of SampleTreeCellRenderer for drawing. */ /* Make tree ask for the height of each row. */ tree.setRowHeight(-1); Container cont = this.getContentPane(); cont.setLayout(new BorderLayout()); JScrollPane sp = new JScrollPane(); sp.setPreferredSize(new Dimension(300, 300)); sp.getViewport().add(tree); if (onlyTree) { cont.add("Center", sp); } else if (split) { /* Put the Tree in a scroller. */ JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); cont.add(splitPane, BorderLayout.CENTER); splitPane.setContinuousLayout(true); splitPane.setDividerSize(3); cont.add(splitPane, BorderLayout.CENTER); splitPane.add(sp, JSplitPane.TOP); splitPane.setDividerLocation(200); splitPane.add(constructOptionsPanel(), JSplitPane.BOTTOM); } else { cont.add("Center", sp); cont.add("South", constructOptionsPanel()); } } /** Constructs a JPanel containing check boxes for the different * options that tree supports. */ private JPanel constructOptionsPanel() { JCheckBox aCheckbox; JPanel retPanel = new JPanel(false); JPanel borderPane = new JPanel(false); borderPane.setLayout(new BorderLayout()); retPanel.setLayout(new FlowLayout()); aCheckbox = new JCheckBox("show handles"); aCheckbox.setSelected(tree.getShowsRootHandles()); aCheckbox.addChangeListener(new ShowHandlesChangeListener()); retPanel.add(aCheckbox); aCheckbox = new JCheckBox("show root"); aCheckbox.setSelected(tree.isRootVisible()); aCheckbox.addChangeListener(new ShowRootChangeListener()); retPanel.add(aCheckbox); borderPane.add(retPanel, BorderLayout.CENTER); return borderPane; } /** * ShowHandlesChangeListener implements the ChangeListener interface * to toggle the state of showing the handles in the tree. */ class ShowHandlesChangeListener extends Object implements ChangeListener { public void stateChanged(ChangeEvent e) { tree.setShowsRootHandles(((JCheckBox)e.getSource()).isSelected()); } } // End of class SampleTree.ShowHandlesChangeListener /** * ShowRootChangeListener implements the ChangeListener interface * to toggle the state of showing the root node in the tree. */ class ShowRootChangeListener extends Object implements ChangeListener { public void stateChanged(ChangeEvent e) { tree.setRootVisible(((JCheckBox)e.getSource()).isSelected()); } } // End of class SampleTree.ShowRootChangeListener protected DefaultMutableTreeNode createNewNode(String name) { return new DynamicTreeNode(name); } } //DynamicTree.java /* * Copyright (c) 2002 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * -Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduct the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that Software is not designed, licensed or intended for * use in the design, construction, operation or maintenance of any nuclear * facility. */ /* * @(#)DynamicTreeNode.java 1.9 02/06/13 */ import javax.swing.tree.DefaultMutableTreeNode; import java.awt.Color; import java.awt.Font; import java.awt.Toolkit; import java.util.Random; /** * DynamicTreeNode illustrates one of the possible ways in which dynamic * loading can be used in tree. The basic premise behind this is that * getChildCount() will be messaged from JTreeModel before any children * are asked for. So, the first time getChildCount() is issued the * children are loaded.<p> * It should be noted that isLeaf will also be messaged from the model. * The default behavior of TreeNode is to message getChildCount to * determine this. As such, isLeaf is subclassed to always return false.<p> * There are others ways this could be accomplished as well. Instead of * subclassing TreeNode you could subclass
|