2010-02-09 7 views
1

두 개의 다른 방법으로 끌어서 놓기 개체에서 놓기를 허용 할 두 개의 자식 창이 있습니다.자바/스윙 : 두 자식 창에 드래그 앤 드롭 문제가 발생했습니다.

하나는 파일 목록을 허용하려는 JPanel입니다. 그것은 잘 작동합니다.

다른 하나는 문자열 목록을 허용하려는 JTable입니다. JPanel을 드롭 대상으로 사용하지 않으면 잘 작동합니다.

둘 다 사용하려고하면 JPanel 놓기 대상이 JTable 놓기 대상을 가리는 것 같습니다. JTable이 JPanel의 자식 창이 아니며 두 구성 요소가 겹치지 않는 영역에도 있습니다.

또한 JFrame 둘 다 포함 된 드롭 아이콘이 표시됩니다. 이유는 확실하지 않습니다.

어떤 조언이 필요합니까? 이것은 디버그하기가 어렵습니다.


샘플 응용 프로그램은 다음과 유사합니다. 여기서는 JTable에서 드랍을 받아 들일 수 없습니다. :/

내가 알고 싶은 또 다른 질문이 있습니다. "소스 1 끌어 오기"에서 "드롭 대상 1"로 드래그하지만 마우스를 놓지 않으면 끌기 소스 1 레이블이 변경 될 때마다 내 커서가 깜박입니다 (이 테스트 응용 프로그램에서 초당 한 번). 왜 이렇게합니까? 깜박임을 막을 수있는 방법이 있습니까?

package com.example.test.gui; 

import java.awt.Component; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.Transferable; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.awt.dnd.DnDConstants; 
import java.awt.dnd.DragGestureEvent; 
import java.awt.dnd.DragGestureListener; 
import java.awt.dnd.DragGestureRecognizer; 
import java.awt.dnd.DragSource; 
import java.awt.dnd.DragSourceDragEvent; 
import java.awt.dnd.DragSourceDropEvent; 
import java.awt.dnd.DragSourceEvent; 
import java.awt.dnd.DragSourceListener; 
import java.awt.dnd.DropTarget; 
import java.awt.dnd.DropTargetDragEvent; 
import java.awt.dnd.DropTargetDropEvent; 
import java.awt.dnd.DropTargetEvent; 
import java.awt.dnd.DropTargetListener; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import java.util.Random; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.ScheduledThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 
import javax.swing.BorderFactory; 
import javax.swing.BoxLayout; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.event.TableModelListener; 
import javax.swing.table.TableModel; 

public class DragAndDropQuestion { 
    public enum Color { 
     RED, ORANGE, YELLOW, GREEN, BLUE, VIOLET, WHITE, BLACK; 
     @Override public String toString() 
      { return this.name().toLowerCase(); } 
     static public Color randomColor(Random r) 
     { 
      Color[] colors = Color.values(); 
      return colors[r.nextInt(colors.length)]; 
     } 
    } 
    public static class SampleBean 
    { 
     final private Color color; 
     final private char letter; 
     final static public DataFlavor dataFlavor = 
      new DataFlavor(SampleBean.class, "SampleBean"); 
     public Color getColor() { return this.color; } 
     public char getLetter() { return this.letter; } 
     private SampleBean(Color color, char letter) 
     { 
      this.color = color; 
      this.letter = letter; 
     } 
     static public SampleBean randomBean(Random r) 
     { 
      String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
      return new SampleBean(Color.randomColor(r), 
        letters.charAt(r.nextInt(letters.length()))); 
     } 
     @Override public String toString() { 
      return this.color.toString()+" "+this.letter; 
     } 
    } 
    public static class BorderPanel extends JPanel { 
     public BorderPanel(String title) 
     { 
      setBorder(BorderFactory.createTitledBorder(title)); 
     } 
    } 
    public static class BeanTransferable implements Transferable 
    { 
     final private SampleBean value; 
     static final private List<DataFlavor> flavors = Arrays.asList(
       DataFlavor.stringFlavor, 
       SampleBean.dataFlavor 
      ); 
     public BeanTransferable(SampleBean x) { this.value=x; } 
     @Override public Object getTransferData(DataFlavor flavor) 
     throws UnsupportedFlavorException, IOException { 
      if (flavors.get(0).equals(flavor)) 
      { 
       return this.value.toString(); 
      } 
      else if (flavors.get(1).equals(flavor)) 
      { 
       return this.value; 
      } 
      else 
      { 
       throw new UnsupportedFlavorException(flavor); 
      } 
     } 

     @Override public DataFlavor[] getTransferDataFlavors() { 
      return flavors.toArray(new DataFlavor[0]); 
     } 
     @Override public boolean isDataFlavorSupported(DataFlavor flavor) { 
      return flavors.contains(flavor); 
     } 
    } 
    public abstract static class SimpleDropTarget 
     implements DropTargetListener 
    { 
     final private String debugString; 
     public SimpleDropTarget(String debugString) { 
      this.debugString=debugString; 
     } 
     @Override public void dragEnter(DropTargetDragEvent event) 
      { System.out.println(this.debugString+":dragEnter"); } 
     @Override public void dragExit(DropTargetEvent event) {} 
      { System.out.println(this.debugString+":dragExit"); } 
     @Override public void dragOver(DropTargetDragEvent event) {}  
     @Override public void dropActionChanged(DropTargetDragEvent event) {} 
     public void install(JComponent component) { 
      new DropTarget(component, this); 
     } 
    } 
    public abstract static class SimpleDragSource 
     implements DragSourceListener, DragGestureListener 
    { 
     final private String debugString; 
     final private DragSource ds = new DragSource(); 
     public SimpleDragSource(String debugString) { 
      this.debugString=debugString; 
     } 
     @Override public void dragDropEnd(DragSourceDropEvent event) {} 
     @Override public void dragEnter(DragSourceDragEvent event) 
     { System.out.println(this.debugString+":dragEnter"); } 
     @Override public void dragExit(DragSourceEvent event) 
     { System.out.println(this.debugString+":dragExit"); } 
     @Override public void dragOver(DragSourceDragEvent event) {} 
     @Override public void dropActionChanged(DragSourceDragEvent event) {} 
     public void install(JComponent component) { 
      DragGestureRecognizer dgr = 
       this.ds.createDefaultDragGestureRecognizer(component, 
         DnDConstants.ACTION_COPY, this); 
     } 
     abstract public Transferable prepareTransferable(); 
     @Override public void dragGestureRecognized(DragGestureEvent dge) 
     { 
      this.ds.startDrag(dge, 
        DragSource.DefaultCopyDrop, prepareTransferable(), this); 
     } 
    } 
    public static class BeanListModel implements TableModel { 
     final private List<SampleBean> list = new ArrayList<SampleBean>(); 
     enum ColumnType { 
      COLOR(Color.class, "color") { 
       @Override public Color extractValue(SampleBean sampleBean) { 
        return sampleBean.getColor(); 
       } 
      }, 
      LETTER(String.class, "letter") { 
       @Override public String extractValue(SampleBean sampleBean) { 
        return Character.toString(sampleBean.getLetter()); 
       } 
      }, 
      ; 
      final private Class<?> cl; 
      final private String name; 
      public Class<?> getColumnClass() { return this.cl; } 
      public String getColumnName() { return this.name; } 
      ColumnType(Class<?> cl, String name) 
      { this.cl=cl; this.name=name; } 
      abstract public Object extractValue(SampleBean sampleBean); 
     } 
     final static private ColumnType[] columns 
      = new ColumnType[]{ColumnType.COLOR, ColumnType.LETTER}; 

     @Override 
      public void addTableModelListener(TableModelListener arg0) {} 
     @Override 
      public void removeTableModelListener(TableModelListener arg0) {} 

     @Override public Class<?> getColumnClass(int column) { 
      return columns[column].getColumnClass(); 
     } 
     @Override public int getColumnCount() { 
      return columns.length; 
     } 
     @Override public String getColumnName(int column) { 
      return columns[column].getColumnName(); 
     } 
     @Override public int getRowCount() { return list.size(); } 
     @Override public Object getValueAt(int row, int column) { 
      return columns[column].extractValue(list.get(row)); 
     } 

     @Override public boolean isCellEditable(int row, int column) { 
      return false; 
     } 

     @Override public void setValueAt(Object obj, int row, int column) { 
      throw new UnsupportedOperationException(); 
     }  

     public void addBean(SampleBean bean) 
     { 
      this.list.add(bean); 
     } 
    } 
    public static class BeanTablePanel extends BorderPanel { 
     final private JTable table; 
     final private BeanListModel tableModel; 

     public BeanTablePanel(String title) 
     { 
      super(title); 
      this.table = new JTable(); 
      this.tableModel = new BeanListModel(); 
      this.table.setModel(this.tableModel); 
      add(new JScrollPane(this.table)); 
      SimpleDropTarget dt = new SimpleDropTarget("BeanTable"){ 
       @Override public void drop(DropTargetDropEvent dtde) { 
        Transferable tr = dtde.getTransferable(); 
        if (tr.isDataFlavorSupported(SampleBean.dataFlavor)) 
        { 
         try { 
          SampleBean b = (SampleBean) 
           tr.getTransferData(SampleBean.dataFlavor); 
          addBean(b); 
         } 
         catch (UnsupportedFlavorException e) { 
          e.printStackTrace(); 
         } 
         catch (IOException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }; 
      dt.install(this.table); 
      // !!! This doesn't seem to work... 
     } 
     void addBean(SampleBean b) { 
      this.tableModel.addBean(b);   
     } 
    } 
    public static class BeanLabelPanel extends BorderPanel { 
     final private JLabel label; 
     public BeanLabelPanel(String title) 
     { 
      super(title); 
      this.label = new JLabel("drop item here"); 
      add(this.label); 
      SimpleDropTarget dt = new SimpleDropTarget("BeanLabel"){ 
       @Override public void drop(DropTargetDropEvent dtde) { 
        Transferable tr = dtde.getTransferable(); 
        if (tr.isDataFlavorSupported(DataFlavor.stringFlavor)) 
        { 
         try { 
          String s = (String) 
           tr.getTransferData(DataFlavor.stringFlavor); 
          setLabel(s); 
         } 
         catch (UnsupportedFlavorException e) { 
          e.printStackTrace(); 
         } 
         catch (IOException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }; 
      dt.install(this.label); 
     }  
     void setLabel(String s) { this.label.setText(s); } 
    } 
    public static class BeanSourcePanel extends BorderPanel { 
     final private JLabel label; 
     final private Random randomizer; 
     private SampleBean x; 

     public BeanSourcePanel(
     String title, ScheduledExecutorService scheduler) 
     { 
      super(title); 
      this.label = new JLabel(" "); 
      this.randomizer = new Random(); 
      add(this.label); 

      scheduler.scheduleAtFixedRate(new Runnable() 
      { public void run() { changeBean(); } }, 
      0, 1000, TimeUnit.MILLISECONDS); 

      (new SimpleDragSource("RandomBean"){ 
       @Override public Transferable prepareTransferable() { 
        return new BeanTransferable(getBean()); 
       } 
      }).install(this.label); 
     }  
     public SampleBean getBean() { return this.x; } 
     void changeBean() 
     { 
      this.x = SampleBean.randomBean(this.randomizer); 
      this.label.setText(this.x.toString()); 
     }  
    } 

    public static class DNDQFrame extends JFrame 
    { 
     public DNDQFrame(String title, ScheduledExecutorService scheduler) 
     { 
      setTitle(title); 
      getContentPane().setLayout(
        new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS) 
      ); 
      add(new JLabel("Drag and Drop Question")); 
      add(new BeanSourcePanel("drag source 1", scheduler)); 
      add(new BeanLabelPanel("drop target 1")); 
      add(new BeanTablePanel("drop target 2")); 
     } 
     @Override public Component add(Component component) 
     { 
      if (component instanceof JComponent) 
       ((JComponent) component).setAlignmentX(0.0f); 
      return super.add(component);    
     }  
    } 

    static public void main(String[] args) 
    { 
     ScheduledExecutorService scheduler = 
      new ScheduledThreadPoolExecutor(1); 
     DNDQFrame frame = new DNDQFrame("DragAndDropQuestion", scheduler); 
     frame.pack(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 
} 
+0

간단한 코드를 게시 할 수 있습니까? DnD 코드의 발췌 부분 일지라도 도움이 될 것입니다. 많은 코드가 있다면 pastebin을 사용하십시오. UI 코드를 사용하여 빌드하고 실행할 수 있다면 더 빨리 디버깅 할 수 있습니다. – Kylar

+0

지금 작업 중입니다. (btw은 무엇입니까?) –

+0

더 많은 코드 발췌 부분을 붙여 넣을 수있는 사이트이며 http://mysticpaste.com/new 또는 http : //와 같은 URL을 제공합니다. pastebin.com/. 이렇게하면 인 페이지 코드 2 페이지가 없어도 질문을 읽을 수 있습니다. – Kylar

답변

2

드롭 리스너를 JScrollPane에 대신 추가하십시오. 테이블을 중첩시켜 이벤트를 수신하지 못합니다. 또한 addBean() 메서드에서 table.revalidate()를 추가해야합니다. 그렇지 않으면 업데이트 된 데이터가 테이블 모델에 표시되지 않습니다.

+0

또한, 나는 당신이보고있는 깜박임을 경험하지 않습니다. – Kylar

+0

감사합니다. table + scrollpane을 포함하는 JPanel을 사용했고, TableModel 구현에서 AbstractTableModel 확장과 fireTableRowsInserted() 호출을 사용했다. –