2012-03-29 24 views
5

Tôi có hai JTrees với một số dữ liệu mô phỏng trong đó, những gì tôi đang tìm kiếm là có thể lấy từng 'Công việc' (15663-1, 15663-2, vv) và tạo một nút cho mỗi nút cho mỗi phần bên dưới nó và các thành phần được gắn vào mỗi phần bên dưới. Trong hai cây, như thế này:Làm cách nào để triển khai kéo và thả thông minh từ JTree này sang JTree khác?

+------------------------------+------------------------------+ 
| 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] | 
+------------------------------+------------------------------+ 

Vì vậy mà giả sử tôi có hai ốc vít ở trang bìa trong công việc Một trong 'bộ phận sẽ được xuất xưởng' JTree và tôi không có bất cứ điều gì trong jobA trong hộp vận chuyển, khi tôi kéo các vít vào hộp vận chuyển, nó sẽ tạo một mục nhập cho jobA, tạo một mục nhập cho phần A và tạo mục nhập cho thành phần, sau đó tôi muốn nó nhắc số lượng cho thành phần đó và trừ số lượng đó khỏi các bộ phận được vận chuyển jtree. Vì vậy, nếu tôi có một công việc được gọi là 1553-4 và nó có một bìa với bốn ốc vít và tôi kéo các ốc vít vào hộp vận chuyển sau đó nó sẽ làm cho một mục trong hộp vận chuyển mà nói, "x ốc vít" sau đó nhắc để người dùng nhập số lượng vít mà họ vừa đóng gói, nếu họ đóng gói hai ốc vít thì jtree sẽ thay đổi để phản ánh 2 vít còn lại cho công việc đó.

Tôi đã đọc một loạt các hướng dẫn kéo và thả khác nhau và tôi có một số ví dụ nhưng tôi dường như không thể có được nó. Bất kỳ lời khuyên hoặc trợ giúp nào sẽ được đánh giá cao.

Tôi biết rằng tôi cần phải thực hiện một TranferHandler nhưng tôi không chắc chắn chính xác như thế nào, có vẻ như có quá nhiều giao diện 'ma thuật' xảy ra và tôi thực sự không hiểu nó.

Đây là những gì tôi có, tôi hiểu làm nút và như vậy, đây là những gì tôi có:

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

Tôi chỉ tìm kiếm một kéo súc tích và thả ví dụ về cách kéo vào một JTree và kéo từ một JTree.

Trả lời

3

Giới thiệu ngắn gọn, đơn giản về Kéo và Thả theo các từ của riêng tôi và dựa trên kinh nghiệm của riêng tôi (chủ yếu là kéo và thả trong JDK1.5, vì vậy chức năng mới có thể đã có).

Có hai phần trong thao tác kéo và thả. Đầu tiên là kéo từ thành phần nguồn. TransferHandler of the source component tạo một Transferable, là vùng chứa cho dữ liệu sẽ được trao đổi trong hoạt động kéo và thả. Tùy thuộc vào dữ liệu, có thể có các biểu diễn dữ liệu khác nhau (được gọi là DataFlavor s). Ví dụ: nếu bạn kéo và thả URL vào trình chỉnh sửa văn bản, rất có thể sẽ thêm URL vào tài liệu hiện tại. Nhưng nếu bạn thả nó vào trình duyệt web, bạn hy vọng nó sẽ mở URL đó. Vì vậy, nơi đầu tiên là chỉ quan tâm đến văn bản thuần túy, thứ hai có thể quan tâm đến một đối tượng phức tạp hơn.

Phần thứ hai là phần thả. Đầu tiên nó được quyết định cho dù vị trí hiện tại là một mục tiêu thả tốt. Điều này tùy thuộc vào trình xử lý chuyển giao của thành phần đích để quyết định xem nó có chấp nhận sự giảm xuống hay không. Thông thường, điều này đạt được bằng cách kiểm tra xem liệu nó có thể xử lý dữ liệu có trong số Transferable bằng cách yêu cầu Transferable cho dữ liệu cho một số cụ thể DataFlavor (lưu ý: Flavor phải được biết là thành phần nguồn và đích). Khi nó chấp nhận thả và người dùng thả chuột, nó có thể tiến hành xử lý dữ liệu trong Transferable, và hy vọng làm điều gì đó hữu ích với nó.

Nhưng như mọi khi, Swing tutorials là điểm khởi đầu rất tốt.Sau khi bạn trải qua chúng, bạn có thể đưa ra một câu hỏi chi tiết hơn (nếu bạn vẫn có bất kỳ điều gì, vì yêu cầu của bạn là không đáng kể)

+0

Đây là giải thích tuyệt vời. Tôi biết tôi cần phải mở rộng TransferHandler nhưng tôi có cần mở rộng DataFlavor không? Vì vậy, tôi cần mở rộng Handler Transfer trên danh sách nguồn của mình và làm cho nó biết phải làm gì để gói nó vào một phiên bản có thể chuyển nhượng (là một lớp sở hữu một đối tượng và mở rộng Transferable) và sau đó viết một trình xử lý truyền thứ hai cho đích (trừ khi tất nhiên người xử lý chuyển giao đầu tiên biết cách làm cả hai)? Dataflavors ở đâu? – davidahines

+1

DataFlavor chỉ là một cách để chỉ ra 'loại dữ liệu' có sẵn trong 'Có thể truyền' (cho người gửi), và cho người nhận yêu cầu một loại dữ liệu cụ thể. Hãy suy nghĩ về nó như một loại nhãn như trên một cuốn sách thư viện, nơi bạn có thể nói "cho tôi cuốn sách bí ẩn" vs "cho tôi những thứ lãng mạn" – Robin

+0

Cảm ơn, tôi sẽ xem các hướng dẫn này. – davidahines

2

Về lý thuyết, tôi nghĩ Robin đã trả lời câu hỏi của bạn tốt. Vì vậy, dưới đây là việc thực hiện mà tôi đã thực hiện. Để tóm tắt, việc triển khai bao gồm hai nhãn hàng đầu và hai thanh cuộn dưới cùng, kéo từ trái sang phải. Vẫn còn những điều nhỏ nhặt như trước khi việc nhập xảy ra, một hộp thoại sẽ xuất hiện và hỏi người dùng số lượng cần giảm (và sau đó thực hiện phép tính số học) nhưng tôi nghĩ rằng đó có thể là bài tập về nhà của bạn? ;-) Hãy cho tôi biết nếu bạn cần thêm trợ giúp.

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

Giải pháp này hoạt động rất tốt cho các chuỗi và cho tôi thấy thực thi tốt importData và canImport làm gì, nhưng nếu các nút của tôi đang giữ các đối tượng (các phần) thì tôi cũng không cần triển khai exportData không? – davidahines

+2

dah, nó sẽ mất công sức và thời gian để tìm hiểu và thực hiện tất cả những điều này và bao gồm cả những gì tôi đã đề cập trong câu trả lời. Đó là cách chúng ta học hỏi và phát triển. Tôi chắc chắn sẽ thích hoàn thành mẫu mã này, thật không may đã có được lịch làm việc bận rộn. Nhưng tôi sẽ cập nhật mã trong câu trả lời ở trên với phần còn lại của các yêu cầu nếu tôi có thời gian rảnh. – Jasonw

+0

Yup, đó là quá đủ, tôi đã tự làm việc còn lại. Những gì tôi thực sự không hiểu là những phương pháp để thực hiện/ghi đè lên vì nó có vẻ như là có những cách khác nhau để làm kéo và thả. – davidahines

Các vấn đề liên quan