2014-02-28 76 views
0

我已經設置了一個拖動JComponents的快速演示,但從鼠標拖動開始時,始終從e.getPoint()開始的(0,0)將JComponent拖放到絕對位置容器

App.java

import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 

public class App extends JFrame { 
    private static final long serialVersionUID = 7935470621073141683L; 
    private static final String TITLE = "Test"; 
    private static AbsolutePanel panel; 
    private static App frame; 

    public App() { 
     this(TITLE); 
    } 

    public App(String title) { 
     super(title); 

     setSize(800, 500); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLocationRelativeTo(null); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       panel = new AbsolutePanel(); 
       frame = new App("Component Test"); 

       frame.setContentPane(panel); 
       frame.setVisible(true); 

       doStuff(); 
      } 
     }); 
    } 

    public static void doStuff() { 
     JNode[] nodes = { 
       new JNode("A", 50, 50, 20), 
       new JNode("B", 100, 50, 20), 
       new JNode("C", 50, 100, 20), 
       new JNode("D", 100, 100, 20), 
       new JNode("E", 50, 150, 20), 
       new JNode("F", 100, 150, 20) 
     }; 

     for (JNode node : nodes) { 
      panel.addNode(node); 
     } 
    } 
} 

AbsolutePanel.java

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Insets; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JPanel; 

public class AbsolutePanel extends JPanel { 
    private static final long serialVersionUID = -2783388377109130628L; 

    private List<JNode> nodes; 

    public AbsolutePanel() { 
     super(null); 

     nodes = new ArrayList<JNode>(); 
    } 

    public List<JNode> getNodes() { 
     return nodes; 
    } 

    public void addNode(JNode node) { 
     nodes.add(node); 
     add(node); 

     Insets insets = this.getInsets(); 
     Dimension size = node.getPreferredSize(); 

     node.setBounds(node.getX() + insets.left, node.getY() + insets.top, 
       size.width, size.height); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     g.setColor(Color.WHITE); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     for (JNode node : getNodes()) { 
      node.paint(g); 
     } 
    } 
} 

JNode.java

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 

public class JNode extends Draggable { 
    private static final long serialVersionUID = 4342026645661510597L; 

    private String label; 

    public JNode(String label, int x, int y, int size) { 
     super(x, y, size); 

     this.label = label; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     Dimension size = this.getPreferredSize(); 

     g.setColor(Color.YELLOW); 
     g.fillOval(getX(), getY(), size.width, size.height); 

     g.setColor(Color.BLUE); 
     g.drawOval(getX(), getY(), size.width, size.height); 

     g.drawString(label, getX() + size.width/2 - 2, getY() + size.height/2 + 4); 
    } 
} 

Draggable.java

import java.awt.Cursor; 
import java.awt.Dimension; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 

import javax.swing.JComponent; 

public class Draggable extends JComponent implements MouseListener, MouseMotionListener { 
    private static final long serialVersionUID = 8036176852541863898L; 

    private boolean dragging = false; 

    public Draggable(int x, int y, int size) { 
     super(); 

     setPreferredSize(new Dimension(size, size)); 
     setBounds(x, y, size, size); 

     addMouseListener(this); 
     addMouseMotionListener(this); 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 
     if (dragging) { 
      int oldX = this.getX(); 
      int oldY = this.getY(); 
      int newX = e.getPoint().y; 
      int newY = e.getPoint().x; 

      System.out.printf("(%03d, %03d) -> (%03d, %03d)\n", oldX, oldY, newX, newY); 

      setLocation(e.getPoint()); 
      repaint(); 
     } 
    } 

    @Override 
    public void mouseMoved(MouseEvent e) { } 

    @Override 
    public void mouseClicked(MouseEvent e) { } 

    @Override 
    public void mousePressed(MouseEvent e) { 
     dragging = true; 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     dragging = false; 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 
     setCursor(new Cursor(Cursor.HAND_CURSOR)); 
    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
     setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 
    } 
} 

回答

3

我用Component Mover來拖動組件。

編輯:

我正在重繪的問題。

這是因爲fillOval/drawOval方法實際上應該使用的寬度/高度比組件的大小小1。如果仔細觀察你的繪畫,你會發現右邊/底部節點的邊緣不完全是圓的。少用1會導致繪畫出現在組件的邊界內。

g.setColor(Color.YELLOW); 
    g.fillOval(getX(), getY(), size.width-1, size.height-1); 

    g.setColor(Color.BLUE); 
    g.drawOval(getX(), getY(), size.width-1, size.height-1); 

說了代碼實際上比需要的更復雜。當我測試你的代碼時,我擺脫了Draggable類,因爲當你使用ComponentMover時你不再需要它。所以現在你的JNode可以直接擴展JComponent。由於它是一個組件,因此您可以讓Swing自己繪畫,以便您的AbsolutePanel不需要任何自定義繪畫。它只是成爲一個持有Swing組件的面板。由於您使用的是空佈局,因此您需要設置每個JNode的邊界。此外,JNode中的繪畫代碼將需要更改,因爲所有繪畫現在都相對於(0,0),而不是getX()和getY()。

+0

謝謝,這很好,但我正在重新繪製問題。見[image](http://i.imgur.com/h2kZ1ip.png)。無論如何解決這個問題? –

+1

@ Mr.Polywhirl,見編輯。 – camickr

+0

感謝您解決繪畫問題。我從面板中刪除了組件繪畫,並將節點相對於(0,0)和[一切都很好]定位(http://weknowgifs.com/wp-content/uploads/2013/04/its-happening-ron-保羅 - gif.gif)。 –