2010-02-09 4 views
1

J'ai deux fenêtres enfants que je veux accepter en drop-to + drop de deux manières différentes.java/swing: faites glisser et déposez des problèmes avec deux fenêtres enfants

On est un JPanel que je veux accepter une liste de fichiers. Ça fonctionne bien.

L'autre est un JTable que je veux accepter une liste de chaînes. Cela fonctionne correctement si je n'accepte pas le JPanel comme cible de dépôt. Lorsque j'essaie d'activer les deux, la cible de dépôt JPanel semble masquer la cible de dépôt JTable, même si le JTable n'est pas une fenêtre enfant du JPanel et que les deux composants se trouvent dans des zones non chevauchantes.

Aussi le JFrame qui contient les deux semble avoir l'icône de dépôt ... je ne sais pas pourquoi.

Un conseil? C'est difficile à déboguer. Exemple d'application, qui est similaire, suit, ici je ne peux pas obtenir le JTable pour accepter des gouttes du tout. Il y a une autre question que j'aimerais comprendre: si je glisse de "drag source 1" sur "drop target 1" mais que je ne relâche pas la souris, mon curseur scintille chaque fois que l'étiquette de source drag 1 change (une fois par seconde dans cette application de test). Pourquoi fait-il cela? Y a-t-il un moyen de l'empêcher de scintiller?

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

Pouvez-vous poster un code simplifié? Même si ce sont les extraits de votre code DnD, cela vous sera utile. Utilisez un pastebin si c'est beaucoup de code. Avec le code de l'interface utilisateur, si je peux le construire et l'exécuter, je peux le déboguer beaucoup plus rapidement. – Kylar

+0

travaillant dessus maintenant .... (btw qu'est-ce qu'un pastebin?) –

+0

Un site où vous pouvez coller de plus grands extraits de code, et ils vous donnent un URL http://mysticpaste.com/new ou http: // pastebin.com/. De cette façon, votre question est toujours lisible sans 2 pages de code en ligne. – Kylar

Répondre

2

Ajouter l'auditeur goutte à la place JScrollPane. La table est imbriquée, donc elle ne reçoit pas les événements. En outre, dans votre méthode addBean(), vous devez ajouter un fichier table.revalidate() ou il n'affichera pas les données mises à jour dans votre modèle de tableau.

+0

En outre, je ne ressens pas le scintillement que vous voyez. – Kylar

+0

Merci. J'ai utilisé le JPanel contenant la table + scrollpane à la place, a également passé de l'implémentation de TableModel à étendre AbstractTableModel et en utilisant un appel à fireTableRowsInserted(). –

Questions connexes