|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Jan 2006
Messaggi: 38
|
[JAVA]Drag & Drop di oggetti fra finestre
Dunque...sono due giorni che ci sto sbattendo la capoccia
![]() ![]() Precondizioni: Ho una finestra (JFrame) che a sua volta continene un JDesktopPane, per effettuare operazioni di MDI (Multi Document Interface). Quello che vorrei realizzare è che i documenti aperti dentro il DesktopPane contenessero degli oggetti, visualizzati tramite icone che: 1)Si possano muovere liberamente all'interno di uno spazio delimitato. 2)Si possano copiare/spostare da un internal frame all'altro, portandosi appresso tutte le informazioni che l'oggetto contiene. Ho letto vari tutorial, ma devo ammettere che non ci ho capito molto ![]() ![]() ![]() (per maggiore chiarezza allego un'immagine di come vorrei realizzare il tutto ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Non è complicato tuttavia un esempio significativo richiede qualche articolazione. Se hai tempo vedo di mettere insieme qualcosa entro sera.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#3 | |
Member
Iscritto dal: Jan 2006
Messaggi: 38
|
Quote:
![]() |
|
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
E' un po' rapido ma dovrebbe rendere l'idea.
La storia è questa. C'è un desktop pane con dei JInternalFrame. All'interno di ognuno di questi JInternalFrame c'è un panello. Questo pannello contiene delle cose. Col drag and drop queste passano da un pannello all'altro, tra i JInternalFrame. Puoi trasferire di tutto. Nell'esempio il trasferendo è Sprite. Codice:
import java.awt.*; import java.awt.image.*; public class Sprite { private Point location = new Point(); private BufferedImage image; public Sprite(BufferedImage image) { this.image = image; } public Point getLocation() { return (Point)location.clone(); } public boolean contains(Point p) { return p.x >= location.x && p.x < location.x + image.getWidth() && p.y >= location.y && p.y < location.y + image.getHeight(); } public void setLocation(Point p) { location.setLocation(p); } public void paint(Graphics g) { g.drawImage(image, location.x, location.y, null); } } ![]() Ciò che trasferisci con il Drag And Drop AWT è incapsulato in un oggetto di tipo Transferable (Trasferibile). L'incapsulamento è richiesto anche se si tratti, come nel nostro caso, di cose arcinote e immutabili. Se guardi, l'interfaccia Transferable è molto semplice. Fa due cose: è in grado di dire se quello che contiene è compatibile con un certo DataFlavor (isDataFlavorSupported) e può restituirle quel qualcosa in una forma compatibile con un DataFlavor, se questo sia supportato (getTransferData(DataFlavor)). Noi vogliamo trasferire uno Sprite (tu vorrai trasferire qualcos'altro, il modus operandi è lo stesso), ci serve una capsula Transferable. E' questione di poche righe. Codice:
import java.awt.datatransfer.*; /** Capsula per il trasferimento di uno Sprite nella stessa JVM */ public class SpriteTransferable implements Transferable { /* Identifica un Transferable che trasporta uno Sprite */ public static final DataFlavor SPRITE_FLAVOR = new DataFlavor( Sprite.class , "sprite"); /* Sprite trasferito */ private final Sprite SPRITE; /** Crea un Transferable che incapsula lo Sprite in argomento */ public SpriteTransferable(Sprite sprite) { SPRITE = sprite; } /** Restituisce un oggetto SPRITE se la classe di rappresentazione del DataFlavor in argomento sia compatibile in assegnamento con Sprite.class */ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if(flavor.getRepresentationClass().isAssignableFrom(Sprite.class)) { return SPRITE; } else { throw new UnsupportedFlavorException(flavor); } } /* True se la classe di rappresentazione del DataFlavor in argomento sia compatibile in assegnamento con Sprite.class */ public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.getRepresentationClass().isAssignableFrom(Sprite.class); } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] { SPRITE_FLAVOR }; } } A questo punto è tutto fatto. Il Drag And Drop funziona come fosse un MouseListener. In particolare, quello che a noi interessa di più è l'esistenza di un metodo "dragMouseMoved". E' l'alter ego di "mouseDragged" solo che è invocato quando il trascinamento del mouse è quello che corrisponde ad un drag and drop in corso. La cosa comunque funziona così. Il componente che voglia iniziare un "Drag" viene agganciato ad un DragSource (solitamente il DragSource predefinito della piattaforma) attraverso il metodo createDragGestureRecognizer di quest'ultimo. Al DragSource puoi agganciare un DragSourceListener, che registra in particolare un evento "qualcosa di trascinato sta entrando" e un DragSourceMotionListener, che registra l'evento "qualcosa di trascinato si sta muovendo". Il componente che vuole ricevere un drop, l'atto terminale del drag and drop, può farlo usando DropTarget. DropTarget ha un costruttore che richiede un Component e un DropTargetListener. Il component è quello su cui avverrà il drop e il DropTargetListener è l'oggetto il cui metodo drop è invocato quando avviene il rilascio. Riassunto. Per fare di un Component l'attivatore di un Drag: Codice:
DragSource source = DragSource.getDefaultDragSource(); DragGestureRecognizer dgr = source.createDragGestureRecognizer( IL_COMPONENTE, uno dei valori di DnDConstants, ad esempio MOVE, l'ascoltatore di eventi DragSourceListener); ![]() Per attivare il drop: Codice:
DropTarget dropTarget = new DropTarget(COMPONENTE, DropTargetListener); Codice:
import java.awt.*; import java.awt.dnd.*; import java.awt.datatransfer.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; public class FloatingPanel extends JPanel { private ArrayList<Sprite> sprites = new ArrayList<Sprite>(); private DropTarget dropTarget; private DragSource dragSource = DragSource.getDefaultDragSource(); public FloatingPanel() { setBackground(Color.WHITE); /* Quando si rilascia qualcosa è invocato il metodo drop di dropManager */ dropTarget = new DropTarget(this, dropManager); /* Quando un "droppable" entra nella regione di questo componente è invocato il metodo dragEnter */ dragSource.addDragSourceListener(dragProgressManager); /* Quando il mouse si muove in corrispondenza di un evento drag and drop è invocato il metodo dragMouseMoved */ dragSource.addDragSourceMotionListener(dragProgressManager); DragGestureRecognizer dragStarter = dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_MOVE, dragManager); } /** Aggiunge lo sprite in argomento (non accetta duplicati) */ public void addSprite(Sprite sprite) { if(sprites.contains(sprite) == false) { sprites.add(sprite); repaint(); } } /** Rimuove uno sprite */ public void removeSprite(Sprite sprite) { int index = sprites.indexOf(sprite); if(index >= 0) { sprites.remove(index); repaint(); } } /** Restituisce lo sprite in posizione location o null, se non ci siano sprite in quella posizione */ public Sprite getSpriteAt(Point location) { for(Sprite s : sprites) { if(s.contains(location)) { return s; } } return null; } /** Disegna gli sprite */ protected void paintComponent(Graphics g) { super.paintComponent(g); for(Sprite s : sprites) { s.paint(g); } } /** Gestisce l'avvio del drag */ private DragGestureListener dragManager = new DragGestureListener() { public void dragGestureRecognized(DragGestureEvent dge) { Point p = dge.getDragOrigin(); Sprite sprite = getSpriteAt(p); if(sprite != null) { dge.startDrag(DragSource.DefaultMoveDrop, new SpriteTransferable(sprite)); } } }; /** Gestisce il drop */ private DropTargetAdapter dropManager = new DropTargetAdapter() { public void drop(DropTargetDropEvent e) { if(e.isDataFlavorSupported(SpriteTransferable.SPRITE_FLAVOR)) { e.acceptDrop(DnDConstants.ACTION_MOVE); dropSprite(e); } else { e.rejectDrop(); } } }; /** Gestisce il movimento in drag */ private DragSourceAdapter dragProgressManager = new DragSourceAdapter() { public void dragMouseMoved(DragSourceDragEvent e) { DragSourceContext context = e.getDragSourceContext(); Transferable t = context.getTransferable(); if(t.isDataFlavorSupported(SpriteTransferable.SPRITE_FLAVOR)) { moveSprite(t, e.getLocation()); } } public void dragEnter(DragSourceDragEvent e) { DragSourceContext context = e.getDragSourceContext(); Transferable t = context.getTransferable(); if(t.isDataFlavorSupported(SpriteTransferable.SPRITE_FLAVOR)) { acquireSprite(t, e.getLocation()); } } }; /* Invocato quando lo sprite trascinato entra nel pannello */ private void acquireSprite(Transferable t, Point p) { try { SwingUtilities.convertPointFromScreen(p, this); Sprite sprite = (Sprite)t.getTransferData(SpriteTransferable.SPRITE_FLAVOR); sprite.setLocation(p); addSprite(sprite); } catch(Exception ex) { System.err.println(ex.getMessage()); } } /* Invocato quando lo sprite trascinato esce dal pannello */ private void releaseSprite(Transferable t) { try { Sprite sprite = (Sprite)t.getTransferData(SpriteTransferable.SPRITE_FLAVOR); removeSprite(sprite); } catch(Exception ex) { System.err.println(ex.getMessage()); } } /* Invocato durante il trascinamento di uno sprite */ private void moveSprite(Transferable t, Point p) { try { Rectangle bounds = getBounds(); //JComponent Point onScreen = getLocationOnScreen(); //JComponent bounds.x += onScreen.x; bounds.y += onScreen.y; Sprite sprite = (Sprite)t.getTransferData(SpriteTransferable.SPRITE_FLAVOR); /* Se il movimento avviene all'interno del componente, muove lo sprite */ if(bounds.contains(p)) { p.x -= onScreen.x; p.y -= onScreen.y; sprite.setLocation(p); repaint(); } else { /* Se il movimento avviene al di fuori del componente, lo sprite viene rimosso */ removeSprite(sprite); } } catch(Exception ex) { System.err.println(ex.getMessage()); } } /* Azioni conseguenti ad una richiesta di rilascio */ private void dropSprite(DropTargetDropEvent e) { try { Transferable t = e.getTransferable(); Sprite sprite = (Sprite)t.getTransferData(SpriteTransferable.SPRITE_FLAVOR); addSprite(sprite); repaint(); e.dropComplete(true); } catch(Exception ex) { e.dropComplete(false); } } } Per provare si possono creare due pannelli, infilarli in altrettanti JInternalFrame, creare uno sprite e infilarlo in uno dei due pannelli. Apri un finestrone e potrai trascinare l'icona da un pannello all'altro. Oltre che sperimentare un tot di problemi. Codice:
import java.awt.*; import java.awt.image.*; import javax.swing.*; import javax.imageio.*; import java.util.*; import java.io.*; public class Main implements Runnable { public static void main(String[] args) { SwingUtilities.invokeLater(new Main()); } private final String IMAGE_PATH = "/icon.png"; public void run() { Dimension panelSize = new Dimension(200, 200); FloatingPanel firstPanel = new FloatingPanel(); firstPanel.setPreferredSize(panelSize); JInternalFrame firstFrame = new JInternalFrame( "First Frame", true, false, true, false); firstFrame.add(firstPanel, BorderLayout.CENTER); FloatingPanel secondPanel = new FloatingPanel(); secondPanel.setPreferredSize(panelSize); JInternalFrame secondFrame = new JInternalFrame( "Second Frame", true, false, true, false); secondFrame.add(secondPanel, BorderLayout.CENTER); JDesktopPane desktop = new JDesktopPane(); desktop.add(firstFrame); desktop.add(secondFrame); JFrame window = new JFrame("Sample"); window.add(desktop, BorderLayout.CENTER); window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); window.pack(); /* Carica uno sprite e lo introduce nel primo pannello */ GraphicsConfiguration screenConfig = window.getGraphicsConfiguration(); Sprite sprite = loadSprite(screenConfig, IMAGE_PATH); sprite.setLocation(new Point(5, 5)); firstPanel.addSprite(sprite); window.setSize(640, 480); window.setVisible(true); firstFrame.pack(); firstFrame.setLocation(new Point(300, 50)); firstFrame.setVisible(true); secondFrame.pack(); secondFrame.setLocation(new Point(20, 50)); secondFrame.setVisible(true); } private Sprite loadSprite(GraphicsConfiguration cfg, String iconPath) { try { InputStream in = getClass().getResourceAsStream(iconPath); BufferedImage image = ImageIO.read(in); BufferedImage fastImage = cfg.createCompatibleImage( image.getWidth(), image.getHeight()); fastImage.getGraphics().drawImage(image, 0, 0, null); return new Sprite(fastImage); } catch(IOException ex) { throw new RuntimeException(ex); } } } La cosa un po' meno agevole da risolvere è il fatto che nel passaggio tra un frame e l'altro l'icona scompare. Deriva da ciò che la proiezione dell'icona avviene sui pannelli e non è associata al cursore del trascinamento. C'è un metodo di DragGestureEvent che potrebbe farlo ma non lo fa in tutte le piattaforme dunque è da scartare. C'è più di una soluzione all'ultimo e più consistente problema. Si può usare il DesktopPane come ulteriore oggetto bersaglio del drop e disegnare su di esso l'icona quando si trovi a svolazzare tra due pannelli oppure si può passare per il glass pane della finestra. A dirla tutta l'opzione GlassPane è appettibile per gestire tutto l'ambaradan perchè ha notevoli potenzialità "artistiche". Tuttavia non saremmo più nel campo del drag and drop, almeno non in senso comune. Ma, se vuoi, possiamo provare a vedere cosa si cava da questa seconda opzione.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Jan 2006
Messaggi: 38
|
Innanzitutto grazie davvero di cuore.
Ammetto di essere troppo stanco ora per leggere il tutto, ma domani con mente lucida mi ci metto e mi studio tutto per bene. Inoltre sono strabiliato con la facilità con la quale hai scritto (e descritto) questo codice, per me ancora oscuro, ma per te contenente concetti ormai chiari. Beato te! Sinceramente la storia del GlassPane mi incuriosisce, visto che gli oggetti che porti da un frame all'altro dovranno anche avere un collegamento fra di loro tramite linee definite in una certa maniera......ma questa è un'altra storia, per ora vedo di riuscire a risolvere questa. Ancora grazie ![]() |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Ho provato a farlo in versione "glass pane" e viene molto più carino e direi anche meno complicato. Se ti interessa incollo il codice in un messaggio. Prima devo dargli una sistemata perchè è 'na schifezza
![]()
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#7 | |
Member
Iscritto dal: Jan 2006
Messaggi: 38
|
Quote:
![]() Solo che non sono riuscito a provare a mettterci un oggetto dentro perché non ho avuto tanto tempo oggi. ![]() PS Io uso NetBeans 5.0.....mi ci trovo molto bene, tu che hai sicuramente piu' esperienza di me , se lo hai usato,come lo valuti? |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Conosco NetBeans e mi piace tuttavia io programmo con un editor che una sorta di Notepad con le schede, senza evidenziazione del codice, indentazione, compilazione o ammennicoli del genere. Preferisco così, non lo consiglio a nessuno. Capirai che io non sia la persona più indicata per valutare la bontà di un IDE
![]() Ho tradotto in qualcosa di usabile il drag and drop tramite glass pane. Funziona e apre un tot di possibilità molto simpatiche, graficamente parlando. Qui sotto c'è il minimo sindacale. Non si vede il cursore del mouse perchè "stamp" non lo prende, ma c'è. Partenza ![]() Trascinamento ![]() Arrivo ![]() L'ambaradan si appoggia a tre elementi. Due interfacce e un JComponent da usare come pannello trasparente. L'interfaccia DragData dichiara le capacità di qualcosa che può essere "trascinato". DragData.java Codice:
package softdnd; /** Dati trasferiti attraverso il soft drag and drop */ public interface DragData { /** Restituisce la sorgente dei dati trasferiti o null */ <T> T getSource(Class<T> type); /** Restituisce i dati trasferiti o null */ <T> T getData(Class<T> type); /** Restituisce il punto di origine dei dati nel sistema di coordinate dello schermo */ java.awt.Point getOriginOnScreen(); /** Restituisce l'icona dei dati trasferiti */ java.awt.Image getImage(); } Le proprietà di chi può fornire e ricevere un DragData sono dichiarare nell'interfaccia che segue. DDUnit.java Codice:
package softdnd; import java.awt.Point; /** Sorgente, bersaglio e destinazione del "soft" drag and drop */ public interface DDUnit { /** Estrae i dati trasferibili dal punto screenPoint. Il sistema di coordinate di screenPoint è quello dello schermo. Restituisce null se non ci siano dati da trasferire. */ DragData carve(Point screenPoint); /** Riceve una notifica di trascinamento dei dati trasferiti. Il punto screenPoint è la posizione attuale del trascinamento nel sistema di coordinate dello schermo. data sono i dati in trasferimento. */ void drag(Point screenPoint, DragData data); /* Richiesta di rilascio dei dati data nel punto screenPoint. Il punto screenPoint è relativo al sistema di coordinate dello schermo. Restituisce true se il drop sia avvenuto con successo. */ boolean drop(Point screenPoint, DragData data); } La classe che segue concretizza DragData. Lo fa semplicemente fornendo un get ed un set per ogni proprietà che eredita. DefaultMutableDragData.java Codice:
package softdnd; import java.awt.*; public class DefaultMutableDragData implements DragData { private Object source; private Object data; private Image image; private Point originOnScreen; public Image getImage() { return image; } public void setImage(Image image) { this.image = image; } public void setOriginOnScreen(Point p) { originOnScreen = (Point)p.clone(); } public Point getOriginOnScreen() { return originOnScreen; } public void setSource(Object source) { this.source = source; } public void setData(Object data) { this.data = data; } public <T> T getSource(Class<T> type) { if(source != null && type.isAssignableFrom(source.getClass())) { return type.cast(source); } else { return null; } } public <T> T getData(Class<T> type) { if(data != null && type.isAssignableFrom(data.getClass())) { return type.cast(data); } else { return null; } } } PointService.java Codice:
package softdnd; import java.awt.*; public class PointService { /* Restituisce la conversione di un punto dal sistema di coordinate del componente source a quello dello schermo */ public static Point convertPointToScreen(Point p, Component source) { Point location = source.getLocationOnScreen(); return new Point(p.x + location.x, p.y + location.y); } /* Restituisce la conversione di un punto dal sistema di coordinate dello schermo a quello di questo componente */ public static Point convertPointFromScreen(Point p, Component source) { Point location = source.getLocationOnScreen(); return new Point(p.x - location.x, p.y - location.y); } } La classe UnitPane è un JPanel che concretizza l'interfaccia DDUnit. Cioè un JPanel da cui si può estrarre e su cui si può rilasciare un certo DragData. Il DragData prodotto e acquisibile è un DragData che contenga un Component. UnitPane.java Codice:
package softdnd; import java.awt.*; import java.awt.image.*; import javax.swing.*; import static softdnd.PointService.convertPointToScreen; import static softdnd.PointService.convertPointFromScreen; /** Unità soft drag and drop JPanel */ public class UnitPane extends JPanel implements DDUnit { public UnitPane() {} public UnitPane(LayoutManager layout) { super(layout); } /** @inheritDoc */ public DragData carve(Point screenPoint) { /* Cerca un Component nel punto corrispondente a screenPoint. Se lo trova lo impacchetta in un DefaultMutableDragData e lo restituisce. Elimina da sè il componente trasferito */ DragData answer = null; Point location = convertPointFromScreen(screenPoint, this); Component component = getComponentAt(location); if(component != null && component != this) { answer = packComponent(component); remove(component); revalidate(); } return answer; } /** Inerte */ public void drag(Point screenPoint, DragData data) {} /** @inheritDoc */ public boolean drop(Point screenPoint, DragData data) { /* Se data contiene un Component allora questo pannello ingloba quel componente. */ boolean answer = false; Component component = data.getData(Component.class); if(component != null) { add(component); revalidate(); answer = true; } return answer; } /* Incapsula un componente in un DefaultMutableDragData. Crea uno "screenshot" del componente come immagine da usare per il trasferimento */ private DragData packComponent(Component c) { BufferedImage image = newBuffer(c.getWidth(), c.getHeight()); c.print(image.getGraphics()); DefaultMutableDragData data = new DefaultMutableDragData(); data.setSource(this); data.setData(c); data.setOriginOnScreen(c.getLocationOnScreen()); data.setImage(image); return data; } /* Crea un buffer di formato compatibile con lo schermo */ private BufferedImage newBuffer(int width, int height) { GraphicsConfiguration config = getGraphicsConfiguration(); BufferedImage image = config.createCompatibleImage( width, height, Transparency.TRANSLUCENT); return image; } } DesktopUnit.java Codice:
package softdnd; import java.awt.*; import java.awt.event.*; import javax.swing.*; import static softdnd.PointService.convertPointToScreen; import static softdnd.PointService.convertPointFromScreen; /** Unità drag and drop associata ad un JDesktopPane */ public class DesktopUnit implements DDUnit { private JDesktopPane desktopPane = new JDesktopPane(); /** Restituisce il DesktopPane associato a questo DesktopUnit */ public JDesktopPane getDesktopPane() { return desktopPane; } /** @inheritDoc */ public DragData carve(Point screenPoint) { /* Per estrarre un DragData questo DesktopUnit interroga i JInternalFrame contenuti nel suo desktopPane. */ DragData answer = null; DDUnit unit = ddUnitAt(screenPoint); if(unit != null) { answer = unit.carve(screenPoint); } return answer; } /** Inerte. */ public void drag(Point screenPoint, DragData data) {} /** @inheritDoc */ public boolean drop(Point screenPoint, DragData data) { /* Se c'è un DDUnit che può ricevere il drop allora lascia quell'unità il compito di gestire l'acquisizione. Altrimenti annulla il trasferimento. Per farlo usa la proprietà "source" del DragData (sorgente del trasferimento). */ DDUnit unit = ddUnitAt(screenPoint); if(unit == null || !unit.drop(screenPoint, data)) { undoCarving(data); } return true; } /** Annulla, se possibile, l'operazione di drag and drop rappresentata dal DragData in argomento */ private void undoCarving(DragData data) { /* Se il DragData ha un contentire di origine e trasporta un Component allora aggiunge il componente al contenitore originale. */ Container container = data.getSource(Container.class); Component component = data.getData(Component.class); if(component != null && container != null) { container.add(component); container.validate(); } } /** Restituisce l'unità drag and drop che si trova nel punto screenPoint o null se non ve ne sia una. */ private DDUnit ddUnitAt(Point screenPoint) { /* Tutto si fonda sull'assunto che il pannello del contenuto di ogni JInternalFrame sia un DDUnit. */ DDUnit answer = null; Point point = convertPointFromScreen(screenPoint, desktopPane); Component component = desktopPane.getComponentAt(point); if(component instanceof JInternalFrame) { JInternalFrame frame = (JInternalFrame)component; Container contentPane = frame.getContentPane(); if(contentPane instanceof DDUnit) { answer = (DDUnit)contentPane; } } return answer; } } L'ultimo partecipante al magheggio è DDGlass. DDGlass è un JComponent che sarà usato come glass pane di una finestra. Un glass pane è un componente idealmente trasparente che viene proiettato sopra al pannello del contenuto della finestra. DDGlass.java Codice:
package softdnd; import java.awt.*; import java.awt.event.*; import javax.swing.*; import static java.awt.AWTEvent.*; import static java.awt.event.MouseEvent.*; import static softdnd.PointService.convertPointToScreen; import static softdnd.PointService.convertPointFromScreen; /** Pannello trasparente che gestisce il "soft" drag and drop */ public class DDGlass extends JComponent implements AWTEventListener { /* Punto di trascinamento corrente */ private Point currentDataPoint; /* Dati in trasferimento */ private DragData dragData; /* Sorgente e destinazione dei dati trasferibili */ private DDUnit ddUnit; /* May throw a SecurityException */ public DDGlass(DDUnit ddUnit) { this.ddUnit = ddUnit; setOpaque(false); Toolkit.getDefaultToolkit().addAWTEventListener( this, MOUSE_EVENT_MASK | MOUSE_MOTION_EVENT_MASK); } /** Called by constructor */ public void setOpaque(boolean val) { super.setOpaque(val); } /** Riceve gli eventi AWT ovunque siano generati */ public void eventDispatched(AWTEvent e) { if(e.getID() == MOUSE_PRESSED) { handleMousePressed((MouseEvent)e); } else if(dragData != null && e.getID() == MOUSE_DRAGGED) { handleMouseDragged((MouseEvent)e); } else if(dragData != null && e.getID() == MOUSE_RELEASED) { handleMouseReleased((MouseEvent)e); } } /* Gestisce la pressione del mouse estraendo da ddUnit i dati da trascinare */ private void handleMousePressed(MouseEvent e) { Point screenPoint = convertPointToScreen( e.getPoint(), e.getComponent()); dragData = ddUnit.carve(screenPoint); if(dragData != null) { setVisible(true); currentDataPoint = convertPointFromScreen(screenPoint, this); repaint(); } } /* Gestice il trascinamento del mouse spostando i dati estratti */ private void handleMouseDragged(MouseEvent e) { Point screenPoint = convertPointToScreen( e.getPoint(), e.getComponent()); ddUnit.drag(screenPoint, dragData); currentDataPoint = convertPointFromScreen(screenPoint, this); repaint(); } /** Gestice il rilascio del mouse rilasciando i dati estratti e spostati */ private void handleMouseReleased(MouseEvent e) { Point screenPoint = convertPointToScreen( e.getPoint(), e.getComponent()); ddUnit.drop(screenPoint, dragData); dragData = null; repaint(); } @Override protected void paintComponent(Graphics g) { if(dragData != null) { paintDragData(g); } } /** Disegna l'immagine associata a dragData nel punto di trascinamento corrente */ private void paintDragData(Graphics g) { g.drawImage( dragData.getImage(), currentDataPoint.x, currentDataPoint.y, null); } } La classe Main che mette insieme il tutto in un esempio è molto semplice. Crea un'etichetta con un'immagine come icona. Poi crea due JInternalFrame e imposta per ognuno di essi uno UnitPane come pannello del contenuto. Così facendo DesktopUnit sarà il grando di prelevare e rilasciare oggetti nelle finestre. Main crea uno DesktopUnit, gli aggiunge i due JInternalFrame, crea una finestra, crea un DDGlass lo imposta come glass pane della finestra, si apre e via. Main.java Codice:
package softdnd; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Main implements Runnable { public static void main(String...args) { SwingUtilities.invokeLater(new Main()); } private final String ICON_PATH = "/icons/icon.png"; private final Dimension PANEL_SIZE = new Dimension(200, 200); public void run() { /* Icona usata per l'etichetta trascinabile */ ImageIcon icon = new ImageIcon(getClass().getResource(ICON_PATH)); /* Etichetta trascinabile */ JLabel label = new JLabel(icon); /* Pannello del contenuto del primo frame interno */ UnitPane firstPane = new UnitPane(new FlowLayout()); /* che contiene l'etichetta trascinabile */ firstPane.add(label); /* Pannello del contenuto del secondo frame interno */ UnitPane secondPane = new UnitPane(new FlowLayout()); /* Assegna una dimensione predefinita ai due pannelli del contenuto. */ firstPane.setPreferredSize(PANEL_SIZE); secondPane.setPreferredSize(PANEL_SIZE); /* DesktopUnit il cui desktop pane contiene i due frame interni e che sarà usato come DDUnit per il glass pane DDGlass */ DesktopUnit desktop = new DesktopUnit(); /* Frame interno che contiene il primo UnitPane */ JInternalFrame firstFrame = new JInternalFrame( "First frame", true, false, true); /* Frame interno che contiene il secondo UnitPane */ JInternalFrame secondFrame = new JInternalFrame( "Second frame", true, false, true); /* Imposta i pannelli del contenuto per i due JInternalFrame */ firstFrame.setContentPane(firstPane); secondFrame.setContentPane(secondPane); /* Aggiunge i due frame interni al desktop dello DesktopUnit */ desktop.getDesktopPane().add(firstFrame); desktop.getDesktopPane().add(secondFrame); /* Assegna una dimensione ai due frame interni e li rende visibili */ firstFrame.pack(); firstFrame.setVisible(true); secondFrame.pack(); secondFrame.setVisible(true); /* Crea il glass pane usando il desktop come sua DDUnit */ DDGlass glass = new DDGlass(desktop); /* Crea una finestra */ JFrame window = new JFrame(); /* le assegna un glass pane e lo rende visibile */ window.setGlassPane(glass); glass.setVisible(true); /* apre la finestra sullo schermo */ window.add(desktop.getDesktopPane(), BorderLayout.CENTER); window.setSize(640, 480); window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); window.setVisible(true); } }
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#9 |
Member
Iscritto dal: Jan 2006
Messaggi: 38
|
Ancora una volta grazie;
devo ammettere pero' che, al momento, trovo piu' facile l'altro codice, mi da l'idea di riuscire a gestirlo meglio. Questo ultimo l'ho appena letto, ma non ti nascondo che ho trovato notevoli difficoltà anche solo nel leggere il codice (I feel noob! ![]() ![]() Ancora una volta grazie per la tua disponibilità! ![]() |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: May 2005
Città: Roma
Messaggi: 7938
|
mi inserisco solo per dire
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
__________________
My gaming placement |
![]() |
![]() |
![]() |
#11 | |
Senior Member
Iscritto dal: Mar 2004
Messaggi: 2992
|
Riporto in alto tale topic per chiedere come si deve procedere in tal caso:
Quote:
![]() |
|
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Oct 2006
Città: milano
Messaggi: 1439
|
Wow. Questo me l'ero perso, ai tempi non seguivo. PGI
![]() ![]() |
![]() |
![]() |
![]() |
#13 |
Member
Iscritto dal: Jan 2006
Messaggi: 38
|
Eccomi...il "destinatario" del codice tre anni dopo....
Ancora oggi, dopo tre anni di lavoro pieno su Java e WebTechnology ,lo ringrazio ![]() ![]() Grazie a lui la mia tesi è letteralmente volata ed è stata valutata con il massimo dei punti... ![]() |
![]() |
![]() |
![]() |
#14 | ||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Comunque pare che PGI sia in vacanza o comunque lontano dal forum, almeno per un po'. [FAN MODE ON] Mitico questo thread, non l'avevo ancora letto. ![]() E grande PGI!
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
||
![]() |
![]() |
![]() |
#15 | |
Senior Member
Iscritto dal: Mar 2004
Messaggi: 2992
|
Quote:
![]() Mi aggiungo al fatto che questo sia uno di quei topic da mettere tra le guide. |
|
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Oct 2006
Città: milano
Messaggi: 1439
|
La cosa che più stupisce è la sua incredibile conoscenza della libreria standard di Java. Non pensavo nemmeno si potesse fare qualcosa del genere
![]() |
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
@nucarote: piccolo update.
Ovviamente non so se nel frattempo hai già risolto oppure abbandonato. Oggi mentre cercavo delle info nella bug parade, ho buttato l'occhio e ho visto che tra le 25 più votate, in prima posizione c'era una di queste due entry; contengo informazioni che potrebbero esserti utili (butta un occhio sui work-around): - No way to set drag icon: TransferHandler.getVisualRepresentation() is not used - invoking DragSource's startDrag with an Image renders no image on drag
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 08-09-2010 alle 13:24. |
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: Mar 2004
Messaggi: 2992
|
Per il momento tutto il "progettino" è fermo, comunque è molto più pulita della "soluzione" (a base di Observer) che avevo cominciato a pensare, ti ringrazio molto, ho provato il workaround proposto e mi sembra una buona soluzione, appena avrò un pò di tempo cercherò di svilupparlo meglio.
Comunque sarei nucarote ![]() |
![]() |
![]() |
![]() |
#20 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Facciamo caronte e non se ne parli più
![]() (spiacente per il typo, ho corretto ![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 15:27.