SSISO Community

시소당

JTree로 드래그-앤-드롭(Adding Drop Support with JTree) 추가



시간이  지남에  따라  Swing  구성요소  세트로  끌어서  놓기  기능이  많이  변경되었습니다.  이전  버전에서는  java.awt.dnd  패키지에  기본  API가  있었지만(java.awt.datatransfer의  지원)  초기  사용자  클릭에서  놓기  조작까지  끌기  작업의  모든  측면을  정의해야  했습니다.  J2SE  1.4는  기능  세트에  따라  향상되고  이전  팁  Dragging  Text  and  Images  with  Swing에  설명된  API를  업데이트합니다.

이전  API의  변경으로  끌어서  놓기  작업이  훨씬  쉬워졌습니다.  수많은  구성요소가  끌어서  놓기  작업을  내장  지원하기  때문입니다.  예를  들어,  JTextField에서  끌기  작업을  사용  가능하게  설정하려면  텍스트  구성요소에서  setDragEnabled(true)를  호출하기만  하면  됩니다.  그러면  사용자는  텍스트  구성요소의  텍스트를  끌어서,  놓기  지역  역할을  하는  다른  애플리케이션이나  텍스트  필드  자체  내에  놓을  수  있습니다.

텍스트  구성요소는  JColorChooser  구성요소와  같이  내장된  놓기  지원을  제공하지만  JList,  JTable  또는  JTree와  같은  다른  Swing  구성요소에  놓기  지원을  추가하려면  약간의  추가  작업을  수행해야  합니다.  작업이  복잡하게  들릴  수  있겠지만  TransferHandler의  1.6  내부  DropLocation  클래스의  새로운  기능  덕분에  이  작업은  비교적  쉬워졌습니다.  놓기  가능한  데이터  종류  및  일단  놓은  후에  수행해야  하는  작업에  대해  정의하는  JTree에  대한  TransferHandler를  생성하기만  하면  됩니다.  이러한  작업은  각각  canImport  및  importData  메소드로  제공됩니다.  TransferSupport  내부  클래스는  1.6의  새로운  기능으로,  전송  처리기를  정의하는  보다  간단한  방법을  제공해  줍니다.

이미지나  텍스트를  나뭇잎에  놓도록  허용하는  멋진  JTree를  작성할  수  있지만  다음  예제는  문자열만  수락합니다.  이미지도  수락하도록  예제를  활용해  보십시오.  문자열을  지원하려면  TransferHandler.TransferSupport  인수로  canImport  메소드를  정의해서  지원되는  데이터  유형(문자열)  및  작업  유형을  확인해야  합니다.  TransferSupport에는  작업의  TransferHandler.DropLocation을  가져오는  getDropLocation  메소드도  있습니다.  위치가  유효한  지점이면  canImport  메소드는  참을  반환해야  합니다.  다음은  널이  아닌  트리  경로에서  문자열  유형의  놓기  전송에  대해  참을  반환하는  메소드입니다.
    public  boolean  canImport(TransferHandler.TransferSupport  support)  {
        if  (!support.isDataFlavorSupported(DataFlavor.stringFlavor)  ||
                !support.isDrop())  {
            return  false;
        }

        JTree.DropLocation  dropLocation  =
            (JTree.DropLocation)support.getDropLocation();

        return  dropLocation.getPath()  !=  null;
    }
  

JTree.DropLocation은  JTree  구성요소에  대한  TransferHandler.DropLocation의  사전  정의된  구현입니다.  JList로  작업하기  위한  JList.DropLocation  및  JTree.DropLocation이  있는  JTree에  대한  다른  것도  있습니다.  기본  텍스트  구성요소  놓기  처리  동작을  원하지  않을  경우  JTextComponent.DropLocation에  네  번째  구현이  있습니다.

JTree에  놓기  지원을  추가하는  나머지  역할은  importData  메소드가  수행합니다.  importData  메소드의  이전  버전인  importData(JComponent  comp,  Transferable  t)는  직접  호출되지  않지만  여전히  지원됩니다.  새로운  처리기는  실제로  importData(TransferHandler.TransferSupport  support)  버전을  대신  구현해야  합니다.  이  메소드에서  전송된  데이터를  얻어  TreePath의  올바른  위치에  배치해야  합니다.

전송된  데이터를  얻어도  이전  importData  메소드에서  새  메소드로  이동하는  데는  실제로  영향을  주지  않습니다.  메소드에  Transferable  인수를  가지는  대신  support.getTransferable  메소드로  TransferSupport에서  가져옵니다.  그런  다음  적절한  유형의  데이터를  가져오기만  하면  됩니다.
    Transferable  transferable  =  support.getTransferable();

    String  transferData;
    try  {
        transferData  =  (String)transferable.getTransferData(
            DataFlavor.stringFlavor);
    }  catch  (IOException  e)  {
        return  false;
    }  catch  (UnsupportedFlavorException  e)  {
        return  false;
    }
  

놓기  작업의  위치를  결정하려면  JTree.DropLocation  클래스를  사용하십시오.  DropLocation의  getChildIndex  메소드를  호출하면  트리에  새  노드를  추가할  위치가  제공됩니다.  -1의  하위  인덱스  값은  사용자가  트리의  빈  부분에  노드를  놓았다는  의미입니다.  이  예제에서는  노드가  끝에  추가됩니다.  DropLocation의  getPath  메소드를  호출하면  놓기  위치에  대해  TreePath를  반환합니다.  그런  다음  놓기  위치와  연관된  상위  노드를  찾으려면  경로의  getLastPathComponent  메소드를  호출하십시오.
    JTree.DropLocation  dropLocation  =
        (JTree.DropLocation)support.getDropLocation();

    TreePath  path  =  dropLocation.getPath();

    int  childIndex  =  dropLocation.getChildIndex();
    if  (childIndex  ==  -1)  {
        childIndex  =  model.getChildCount(path.getLastPathComponent());
    }

    DefaultMutableTreeNode  newNode  =
        new  DefaultMutableTreeNode(transferData);
    DefaultMutableTreeNode  parentNode  =
        (DefaultMutableTreeNode)path.getLastPathComponent();
    model.insertNodeInto(newNode,  parentNode,  childIndex);
  

새  경로  요소가  표시되는지  확인하는  것도  도움이  됩니다.  전체  importData  메소드는  다음과  같습니다.
    public  boolean  importData(TransferHandler.TransferSupport  support)  {
        if  (!canImport(support))  {
            return  false;
        }

        JTree.DropLocation  dropLocation  =
            (JTree.DropLocation)support.getDropLocation();

        TreePath  path  =  dropLocation.getPath();

        Transferable  transferable  =  support.getTransferable();

        String  transferData;
        try  {
            transferData  =  (String)transferable.getTransferData(
                DataFlavor.stringFlavor);
        }  catch  (IOException  e)  {
            return  false;
        }  catch  (UnsupportedFlavorException  e)  {
            return  false;
        }

        int  childIndex  =  dropLocation.getChildIndex();
        if  (childIndex  ==  -1)  {
            childIndex  =  model.getChildCount(path.getLastPathComponent());
        }

        DefaultMutableTreeNode  newNode  =
            new  DefaultMutableTreeNode(transferData);
        DefaultMutableTreeNode  parentNode  =
            (DefaultMutableTreeNode)path.getLastPathComponent();
        model.insertNodeInto(newNode,  parentNode,  childIndex);

        TreePath  newPath  =  path.pathByAddingChild(newNode);
        tree.makeVisible(newPath);
        tree.scrollRectToVisible(tree.getPathBounds(newPath));

        return  true;
    }
  

완전히  작동하는  놓기  가능한  JTree를  가지도록  충분한  정보를  자세히  보여  드렸습니다.  여기서  놓기  지원에  관련된  중요한  정보인  DropMode에  대해  알려드리겠습니다.  DropMode는  구성요소에서  놓기  작업이  발생되는  위치를  표시하는  방식에  관한  모드를  열거한  것입니다.  JTree에  대해  다음  네  가지  모드가  지원됩니다.

        *  DropMode.USE_SELECTION
        *  DropMode.ON
        *  DropMode.INSERT
        *  DropMode.ON_OR_INSERT

그러나  열거는  다른  구성요소의  특정  모드에  대해  더  커집니다(JTable로  작업할  경우  INSERT_COLS  또는  INSERT_ROWS).

놓기  모드는  어떻게  처리할까요?  기본적으로  이  모드는  USE_SELECTION입니다.  이것은  JTree에서  선택된  항목을  더  이상  강조  표시하지  않음을  의미합니다.  대신  선택  메커니즘을  사용하여  놓기  위치를  강조  표시하십시오.  JTree가  놓기를  지원하면  기본값을  변경하는  것이  좋습니다.  더  나은  모드는  ON입니다.  이  모드를  사용하여  JTree  및  잠재적  놓기  위치에서  현재  선택을  모두  확인할  수  있습니다.  INSERT  모드를  사용하여  현재  선택  사항을  보면서  기존  노드  사이에  새  노드를  삽입할  수  있습니다.  ON_OR_INSERT는  후자  두  개를  결합한  것입니다.  다음  그림  4개는  네  가지  옵션을  보여  줍니다.  완료된  프로그램은  다른  동작을  시도하도록  모드  콤보  상자를  제공합니다.
Use  Selection
그림  1.  Use  Selection

On
그림  2.  On

Insert
그림  3.  Insert

On  or  Insert
그림  4.  On  or  Insert

다음은  놓기  가능한  전체  트리  프로그램입니다.  프로그램에는  중간에  선택하여  JTree에  놓을  수  있는  텍스트  항목의  맨  위에  텍스트  영역이  있습니다.  놓기  모드는  맨  아래의  콤보  상자에서  설정할  수  있습니다.  트리에  대한  데이터  모델은  JTree를  작성할  때  지정되지  않은  경우  작성된  기본  모델에서  나옵니다.
import  java.awt.*;
import  java.awt.datatransfer.*;
import  java.awt.event.*;
import  java.io.*;
import  javax.swing.*;
import  javax.swing.tree.*;

public  class  DndTree  {
    public  static  void  main(String  args[])  {
        Runnable  runner  =  new  Runnable()  {
            public  void  run()  {
                JFrame  f  =  new  JFrame("D-n-D  JTree");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JPanel  top  =  new  JPanel(new  BorderLayout());
                JLabel  dragLabel  =  new  JLabel("Drag  me:");
                JTextField  text  =  new  JTextField();
                text.setDragEnabled(true);
                top.add(dragLabel,  BorderLayout.WEST);
                top.add(text,  BorderLayout.CENTER);
                f.add(top,  BorderLayout.NORTH);

                final  JTree  tree  =  new  JTree();
                final  DefaultTreeModel  model  =  (DefaultTreeModel)tree.getModel();
                tree.setTransferHandler(new  TransferHandler()  {
                    public  boolean  canImport(TransferHandler.TransferSupport  support)  {
                        if  (!support.isDataFlavorSupported(DataFlavor.stringFlavor)  ||
                                !support.isDrop())  {
                            return  false;
                        }

                        JTree.DropLocation  dropLocation  =
                            (JTree.DropLocation)support.getDropLocation();

                        return  dropLocation.getPath()  !=  null;

                    }

                    public  boolean  importData(TransferHandler.TransferSupport  support)  {
                        if  (!canImport(support))  {
                            return  false;
                        }

                        JTree.DropLocation  dropLocation  =
                            (JTree.DropLocation)support.getDropLocation();

                        TreePath  path  =  dropLocation.getPath();

                        Transferable  transferable  =  support.getTransferable();

                        String  transferData;
                        try  {
                            transferData  =  (String)transferable.getTransferData(
                                DataFlavor.stringFlavor);
                        }  catch  (IOException  e)  {
                            return  false;
                        }  catch  (UnsupportedFlavorException  e)  {
                            return  false;
                        }

                        int  childIndex  =  dropLocation.getChildIndex();
                        if  (childIndex  ==  -1)  {
                            childIndex  =  model.getChildCount(path.getLastPathComponent());
                        }

                        DefaultMutableTreeNode  newNode  =
                            new  DefaultMutableTreeNode(transferData);
                        DefaultMutableTreeNode  parentNode  =
                            (DefaultMutableTreeNode)path.getLastPathComponent();
                        model.insertNodeInto(newNode,  parentNode,  childIndex);

                        TreePath  newPath  =  path.pathByAddingChild(newNode);
                        tree.makeVisible(newPath);
                        tree.scrollRectToVisible(tree.getPathBounds(newPath));

                        return  true;
                    }
                });

                JScrollPane  pane  =  new  JScrollPane(tree);
                f.add(pane,  BorderLayout.CENTER);

                JPanel  bottom  =  new  JPanel();
                JLabel  comboLabel  =  new  JLabel("DropMode");
                String  options[]  =  {"USE_SELECTION",
                                "ON",  "INSERT",  "ON_OR_INSERT"
                };
                final  DropMode  mode[]  =  {DropMode.USE_SELECTION,
                                DropMode.ON,  DropMode.INSERT,  DropMode.ON_OR_INSERT};
                final  JComboBox  combo  =  new  JComboBox(options);
                combo.addActionListener(new  ActionListener()  {
                    public  void  actionPerformed(ActionEvent  e)  {
                        int  selectedIndex  =  combo.getSelectedIndex();
                        tree.setDropMode(mode[selectedIndex]);
                    }
                });
                bottom.add(comboLabel);
                bottom.add(combo);
                f.add(bottom,  BorderLayout.SOUTH);
                f.setSize(300,  400);
                f.setVisible(true);
            }
        };
        EventQueue.invokeLater(runner);
    }
}
  

끌어서  놓기  지원  및  데이터  전송  API에  대한  자세한  내용은  자바  온라인  자습서의  Introduction  to  Drag  and  Drop  and  Data  Transfer  내역을  참조하십시오.

출처  :  네이버카페  http://cafe.naver.com/sharkjava.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=1684

981 view

4.0 stars