seleccionar - simple jtree example in java
¿Cómo implemento la función de arrastrar y soltar inteligente de un JTree a otro? (2)
Tengo dos JTrees con algunos datos simulados, lo que estoy buscando hacer es poder tomar cada ''Trabajo'' (15663-1, 15663-2, etc.) y hacer un nodo para cada uno, con un nodo para cada parte debajo de ella y los componentes unidos a cada parte debajo de eso. En dos árboles, como este:
+------------------------------+------------------------------+
| PARTS TO BE SHIPPED | SHIPPING BOX |
+------------------------------+------------------------------+
|[JOB] |[JOB] |
|+------[part] |+------[part] |
| +------[component] | +------[component] |
| +------[component] | +------[component] |
|+------[part] |+------[part] |
| +------[component] | +------[component] |
|[JOB] |[JOB] |
|+------[part] |+------[part] |
| +------[component] | +------[component] |
| +------[component] | +------[component] |
|+------[part] |+------[part] |
| +------[component] | +------[component] |
+------------------------------+------------------------------+
Entonces, supongamos que tengo dos tornillos en la cubierta en el trabajo A en las piezas que se enviarán y no tengo nada en el trabajo. En la caja de envío, cuando arrastre los tornillos a la caja de envío, debería hacer un entrada para jobA, haga una entrada para la parte A y haga una entrada para el componente, luego quiero que solicite la cantidad para ese componente y reste esa cantidad de las partes que se enviarán jtree.
Entonces, si tengo un trabajo llamado 1553-4 y tiene una cubierta con cuatro tornillos y los arrastre a la caja de envío, debe hacer una entrada en la caja de envío que diga "x tornillos" y luego solicite al usuario ingrese la cantidad de tornillos que acaba de empaquetar; si empacan dos tornillos, el jtree debe cambiar para reflejar los 2 tornillos restantes para ese trabajo.
He leído un montón de diferentes tutoriales de arrastrar y soltar y tengo algunos ejemplos, pero parece que no puedo obtenerlo. Cualquier consejo o ayuda será apreciada.
Sé que tengo que implementar un TranferHandler, pero no estoy seguro de cómo, parece que hay demasiada ''magia'' de interfaz y realmente no lo estoy entendiendo.
Esto es lo que tengo, entiendo hacer nodos y tal, esto es lo que tengo:
package com.protocase.examples;
import java.awt.Dimension;
import java.awt.HeadlessException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
/**
* @author DavidH
*/
public class JTreeExample {
public static void main(String[] args) {
addTreesAndDisplay();
}
private static void addTreesAndDisplay() throws HeadlessException {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JTree tree = new JTree(getTreeModel());
tree.setDragEnabled(true);
tree.setPreferredSize(new Dimension(200,400));
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(tree);
panel.add(scroll);
JTree secondTree = new JTree(getTreeModel());
secondTree.setPreferredSize(new Dimension(200,400));
secondTree.setDragEnabled(true);
JScrollPane secondScroll = new JScrollPane();
secondScroll.setViewportView(secondTree);
panel.add(secondScroll);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static DefaultTreeModel getTreeModel() {
MutableTreeNode root = new DefaultMutableTreeNode("15663-1");
DefaultMutableTreeNode cover = new DefaultMutableTreeNode("Cover");
DefaultMutableTreeNode base = new DefaultMutableTreeNode("Base");
root.insert(cover, 0);
root.insert(base, 0);
cover.insert(new DefaultMutableTreeNode("2x PEMS"), 0);
cover.insert(new DefaultMutableTreeNode("2x SCREWS"), 0);
base.insert(new DefaultMutableTreeNode("4x SCREWS"), 0);
base.insert(new DefaultMutableTreeNode("4x HANDLES"), 0);
DefaultTreeModel model = new DefaultTreeModel(root);
return model;
}
}
Solo estoy buscando un ejemplo conciso de arrastrar y soltar arrastrando en un JTree y arrastrándolo desde un JTree.
En teoría, creo que Robin ha respondido bien a tu pregunta. Así que abajo está la implementación que hice. Para resumir, la implementación incluye las dos etiquetas principales y las dos pantallas deslizantes inferiores, arrastre de izquierda a derecha. Todavía hay algo menor como que antes de que suceda la importación, debería aparecer un diálogo y preguntarle al usuario cuánta cantidad debe soltar (y luego hacer la operación aritmética) pero creo que esa puede ser su tarea. ;-) Avíseme si necesita ayuda adicional.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
public class JTreeExample extends JPanel
{
private JTree tree;
private DefaultTreeModel treeModel;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("My Warehouse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTreeExample newContentPane = new JTreeExample();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public JTreeExample()
{
setLayout(new GridLayout(1, 3));
JLabel lbl_parts = new JLabel("PARTS TO BE SHIPPED");
tree = new JTree(getTreeModel());
tree.setDragEnabled(true);
tree.setPreferredSize(new Dimension(200,400));
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(tree);
JLabel lbl_ship = new JLabel("SHIPPING BOX");
treeModel = getTreeModel();
JTree secondTree = new JTree(treeModel);
secondTree.setPreferredSize(new Dimension(200,400));
secondTree.setTransferHandler(new TransferHandler() {
@Override
public boolean importData(TransferSupport support)
{
if (!canImport(support))
{
return false;
}
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
TreePath path = dl.getPath();
int childIndex = dl.getChildIndex();
String data;
try
{
data = (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
}
catch (UnsupportedFlavorException e)
{
return false;
}
catch (IOException e)
{
return false;
}
if (childIndex == -1)
{
childIndex = tree.getModel().getChildCount(path.getLastPathComponent());
}
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(data);
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent();
treeModel.insertNodeInto(newNode, parentNode, childIndex);
tree.makeVisible(path.pathByAddingChild(newNode));
tree.scrollRectToVisible(tree.getPathBounds(path.pathByAddingChild(newNode)));
return true;
}
public boolean canImport(TransferSupport support)
{
if (!support.isDrop())
{
return false;
}
support.setShowDropLocation(true);
if (!support.isDataFlavorSupported(DataFlavor.stringFlavor))
{
System.err.println("only string is supported");
return false;
}
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
TreePath path = dl.getPath();
if (path == null)
{
return false;
}
return true;
}
});
JScrollPane secondScroll = new JScrollPane();
secondScroll.setViewportView(secondTree);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(lbl_parts, BorderLayout.NORTH);
topPanel.add(scroll, BorderLayout.CENTER);
JPanel btmPanel = new JPanel(new BorderLayout());
btmPanel.add(lbl_ship, BorderLayout.NORTH);
btmPanel.add(secondScroll, BorderLayout.CENTER);
add(topPanel);
add(btmPanel);
}
private static DefaultTreeModel getTreeModel()
{
MutableTreeNode root = new DefaultMutableTreeNode("15663-1");
DefaultMutableTreeNode cover = new DefaultMutableTreeNode("Cover");
cover.insert(new DefaultMutableTreeNode("2x PEMS"), 0);
cover.insert(new DefaultMutableTreeNode("2x SCREWS"), 0);
root.insert(cover, 0);
DefaultMutableTreeNode base = new DefaultMutableTreeNode("Base");
base.insert(new DefaultMutableTreeNode("4x SCREWS"), 0);
base.insert(new DefaultMutableTreeNode("4x HANDLES"), 0);
root.insert(base, 0);
DefaultTreeModel model = new DefaultTreeModel(root);
return model;
}
}
Una introducción muy breve y simple a Arrastrar y soltar en Swing en mis propias palabras y en base a mi propia experiencia (que fue principalmente con arrastrar y soltar en JDK1.5, por lo que la nueva funcionalidad ya podría estar presente).
Hay dos partes en una operación de arrastrar y soltar. Primero está el arrastre del componente fuente. TransferHandler
del componente fuente crea un Transferable
, que es un contenedor para los datos que se intercambiarán en la operación de arrastrar y soltar. Dependiendo de los datos, puede haber diferentes representaciones de los datos (que se llaman DataFlavor
s). Por ejemplo, si arrastra y suelta una URL en un editor de texto, lo más probable es que agregue la URL al documento actual. Pero si lo coloca en un navegador web, espera que abra esa URL. Entonces, cuando el primero solo está interesado en texto plano, el segundo podría estar interesado en un objeto más complejo.
La segunda parte es la gota. Primero, se decide si la ubicación actual es un buen objetivo de caída. Depende del controlador de transferencia del componente de destino decidir si acepta la caída. Por lo general, esto se logra al verificar si puede manejar los datos contenidos en el Transferable
pidiendo al Transferable
los datos para un DataFlavor
específico (nota: el Flavor
debe ser conocido como el componente fuente y el componente objetivo). Cuando acepta la caída y el usuario suelta el mouse, puede continuar con el manejo de los datos en el Transferable
y, con suerte, hacer algo útil con él.
Pero, como siempre, los tutoriales de Swing son un muy buen punto de partida. Después de que los revisó, probablemente pueda hacer una pregunta más detallada (si aún la tiene, ya que su requisito es bastante trivial)