2013-01-24 33 views
0

我有一個擴展了JPanel的類的ExamplePanel,它由2個JPanels- labelsPanel和subPanel組成。 Labelspanel包含任意JLabels,而subPanel包含ExamplePanel嵌套實例的不同實例。Java在拖動時總是將JLabel保留在JPanels上

我想能夠將JLabel拖動到嵌套的實例,但是當我這樣做時,它們最終會落在子面板後面。 我相信答案在於setComponentZOrder方法,但我沒有取得任何進展。它使得JLabel被繪製在labelsPanel中的其他JLabel之上,但是一旦JLabel超出該面板的範圍,JLabel就不會起作用。我試過把JLabel和JPanel都帶到Z序位0和1,並且首先繪製子面板,但是沒有一個具有預期的效果。 簡化代碼如下。 (我試着切出儘可能多的,所以請原諒我,如果有剩餘的代碼中的一些反常段)

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Rectangle; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.util.ArrayList; 

import javax.swing.BorderFactory; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 


public class ExamplePanel extends JPanel implements MouseListener, 
    MouseMotionListener { 

public JPanel labelsPanel; 
public JPanel subPanel; 

public ArrayList<JLabel> labels; 
public ArrayList<ExamplePanel> panels; 


private int xOffset = 0, yOffset = 0; 
private Rectangle prevBounds = null; 

private boolean isDragged; 

public ExamplePanel(ArrayList<JLabel> labels, ArrayList<ExamplePanel> panels) { 
    this.invalidate(); 

    this.labels = labels; 
    this.panels = panels; 
    addMouseListener(this); 
    this.setBorder(BorderFactory.createCompoundBorder(
      BorderFactory.createLineBorder(Color.GRAY), 
      BorderFactory.createEmptyBorder(10, 10, 10, 10))); 
    this.setLayout(new BorderLayout()); 
    this.setAlignmentX(Component.LEFT_ALIGNMENT); 
    addLabels(); 
    addPanels(); 
    this.validate(); 

} 

public void addLabels() { 
    if (labelsPanel != null) { 
     this.remove(labelsPanel); 
    } 

    labelsPanel = new JPanel(new GridBagLayout()); 
    labelsPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN)); 


    GridBagConstraints c = new GridBagConstraints(); 
    c.anchor = GridBagConstraints.CENTER; 
    c.ipadx = 50; 
    c.ipady = 30; 
    c.gridx = 0; 
    c.gridy = 0; 

    System.out.println("labels size: " + labels.size()); 

    for (int i = 0; i < labels.size(); i++) { 
     c.gridx = i; 

     labels.get(i).addMouseListener(this); 
     labels.get(i).addMouseMotionListener(this); 

     labelsPanel.add(labels.get(i), c); 
    } 

    this.add(labelsPanel, BorderLayout.NORTH); 
} 

public void addPanels() { 

    System.out.println("panels size: " + panels.size()); 
    if (subPanel != null) { 
     this.remove(subPanel); 
    } 

    subPanel = new JPanel(new BorderLayout()); 
    subPanel.setBorder(BorderFactory.createLineBorder(Color.RED)); 
    subPanel.setAlignmentX(Component.LEFT_ALIGNMENT); 

    subPanel.setOpaque(false); 

    for (ExamplePanel panel : panels) { 
     subPanel.add(panel); 
     this.validate(); 
    } 

    this.add(subPanel, BorderLayout.CENTER); 
} 

public void addLabel(JLabel label) { 
    labels.add(label); 
} 

public void addPanel(ExamplePanel panel) { 
    panels.add(panel); 
} 

@Override 
public void mouseDragged(MouseEvent e) { 
    isDragged = true; 
    JLabel dragged = (JLabel) e.getSource(); 

    int newX = (e.getX() + dragged.getBounds().x - xOffset < 0) ? 0 : e 
      .getX() + dragged.getBounds().x - xOffset; 
    int newY = (e.getY() + dragged.getBounds().y - yOffset < 0) ? 0 : e 
      .getY() + dragged.getBounds().y - yOffset; 
    dragged.setLocation(newX, newY); 

} 

@Override 
public void mouseMoved(MouseEvent e) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mouseClicked(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mouseEntered(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mouseExited(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mousePressed(MouseEvent arg0) { 
    System.out.println("++++++ Start Of Pressed ++++++"); 

    System.out.println("Mouse Pressed At: " + arg0.getX() + " " 
      + arg0.getY()); 

    // Collect the clicked source and return if it's 
    // not a JLabel (might have to be modified if we 
    // want to click on other things than JLabels. 
    Object source = (Object) arg0.getSource(); 

    if (source instanceof JLabel) { 
     JLabel jlb = (JLabel) arg0.getSource(); 
     prevBounds = jlb.getBounds(); 
     xOffset = arg0.getX(); 
     yOffset = arg0.getY(); 

     ((JLabel) arg0.getSource()).getParent().setComponentZOrder(
       ((JLabel) arg0.getSource()), 0); 

    } 
    JLabel clicked = null; 
    if (source instanceof JLabel) { 
     clicked = (JLabel) source; 
    } else { 
     System.out.println("++++++ End Of Pressed ++++++"); 
     return; 
    } 

    System.out.println("++++++ End Of Pressed ++++++"); 

} 

@Override 
public void mouseReleased(MouseEvent arg0) { 
    System.out.println("++++++ Start Of Released ++++++"); 


    if (!isDragged) { 
     System.out.println("++++++ End Of Released, not dragging ++++++"); 
     return; 
    } 

    isDragged = false; 
    xOffset = yOffset = 0; 

    // The object being dragged 
    JLabel source = (JLabel) arg0.getSource(); 
    System.out.println("Source is: " + source.toString()); 

    source.setBounds(prevBounds); 


    System.out.println("++++++ End Of Released ++++++"); 

} 
} 

一個基本的主類是如下;

import java.awt.Dimension; 
import java.util.ArrayList; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 


public class Main extends JFrame { 

public Main() { 
    setSize(new Dimension(600, 600)); 

    ArrayList<JLabel> labels = new ArrayList<JLabel>(); 
    JLabel label1 = new JLabel("Example 1"); 
    JLabel label2 = new JLabel("Example 2"); 
    labels.add(label1); 
    labels.add(label2); 

    ArrayList<ExamplePanel> panels = new ArrayList<ExamplePanel>(); 
    ArrayList<ExamplePanel> panels2 = new ArrayList<ExamplePanel>(); 
    System.out.println("LAbels size = " + labels.size()); 
    ExamplePanel secondPanel = new ExamplePanel(labels, panels2); 
    panels.add(secondPanel); 

    ExamplePanel firstPanel = new ExamplePanel(labels, panels); 

    this.add(firstPanel); 
    this.setVisible(true); 
} 

public static void main (String [] args) { 
    Main main = new Main(); 
} 
} 

我省略了代碼實際添加JLabel以子面板,並刷新面板,因爲它是沒有必要這個問題。

三江源提前任何幫助

+0

爲了更好地幫助越早,張貼[SSCCE(http://sscce.org/) –

+0

所包含的代碼是最小的,我可以得到它,我很害怕。問題可以從這兩個類中運行。謝謝你的回覆 – Bruce0

+0

*「包含的代碼是我能得到的最小的代碼」*'短'只是SSCCE的第一個任期,人們對它過分關注。如果他們是**源文件**(這是SSCCE的另一個條件),我會認爲這些代碼是潛在的SSCCE。 –

回答

3

最簡單的選擇是從當前包裝箱中取出標籤,並將其移動到框架的玻璃面板,允許標籤隔着玻璃窗格中移動並添加回到它被丟棄的容器。

退房how to use glass panes瞭解更多信息

+2

+1爲建議glasspane .. @布魯斯0看到這個答案[這裏](http://stackoverflow.com/questions/14273923/how-can-i-set-the-priority-鼠標監聽器/ 14276466#14276466)(特別是最後一批代碼),它顯示了我使用* glasspane *的自定義類,因此可以拖動多個容器。 –

+2

謝謝你的建議。這實現了我想要的一切。 @DavidKroukamp你鏈接的例子確實非常有幫助。 – Bruce0