問題描述
我有一個帶有列表和按鈕的面板.列表使用 mouseClick()
設置 MouseAdapter
.我用 mousePressed()
和 mouseReleased()
和 MouseMotionAdapter
添加到面板 MouseAdapter
和 mouseDragged代碼>.
I have a panel with lists and buttons. The lists set MouseAdapter
with mouseClick()
. I added to the panel MouseAdapter
with mousePressed()
and mouseReleased()
and MouseMotionAdapter
with mouseDragged
.
僅當您單擊面板時拖放才有效.
Drag and drop only works if you click on the panel.
即使我點擊了列表,如何使拖動工作?
How to make the drag work even if I clicked on the list?
簡單示例:
public class DragTest extends JFrame{
private boolean drag;
private Point btnCoord;
private Point startPoint;
public DragTest(){
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(500,500);
setLayout(null);
final JPanel panel = new JPanel();
final JButton button = new JButton();
button.setText("Button");
button.setSize(30,60);
button.setLocation(50, 50);
panel.setLayout(null);
setContentPane(panel);
panel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drag){
panel.setLocation(btnCoord.x-(startPoint.x-e.getX()),btnCoord.y-(startPoint.y-e.getY()));
}
}
});
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
drag = true;
startPoint = e.getPoint();
btnCoord = panel.getLocation();
}
@Override
public void mouseReleased(MouseEvent e) {
drag = false;
}
});
getContentPane().add(button);
}
public static void main(String[] args) {
JFrame frame = new DragTest();
frame.setVisible(true);
}
}
如果拖動面板,一切正常,如果開始拖動按鈕,則按鈕攔截事件.
If you drag panel, all work fine, if start drag button, then button intercept event.
推薦答案
上面的代碼有很多錯誤...
The above code has many errors...
- 不要使用
null
/Absolute
LayoutManager
.看看在容器中布局組件. - 不要在組件和
JFrame
上調用setSize
(如果實現了正確的布局管理器,您可以簡單地添加組件并在pack()
上調用 <代碼>JFrame. - 在 EDT 上創建和操作 Swing 組件.詳細了解 Swing 中的并發.
- 在可見容器中添加/刪除組件后,您應該在容器上調用
revalidate()
和repaint()
.
- Dont use
null
/Absolute
LayoutManager
. Have a look at Laying Out Components Within a Container. - Dont call
setSize
on components andJFrame
(if correct Layout Manager is implemented you can simply add components and callpack()
onJFrame
. - Create and manipulate Swing components on EDT. Read more on Concurrency in Swing.
- You should call
revalidate()
andrepaint()
on container after adding/removing components from a visible container.
我一直在開發自己的小 ComponentDrag
API,它允許我們將 Swing 組件拖到一個 JComponent
或多個 JComponent
上.雖然它絕不是沒有錯誤的(尤其是今天剛剛完成的多個組件部分,所以你永遠不會知道)
I have been working on my own little ComponentDrag
API which will allow us to drag Swing components across a JComponent
or over multiple JComponent
s. It is by no means error free though (especially the multiple components part just finished it today so you never know)
您將創建 JButton
并添加到 JPanel
:
You would create JButton
and add to JPanel
:
JButton button = new JButton("Text");
JPanel panel1 = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
panel1.add(button);
通過傳遞容器的參數來創建 ComponentDrag
類的實例,即 JFrame
/JDialog
或 JWindow
并注冊可拖動組件并在您的 JPanel
上調用 setName("Droppable")
以允許正確進行拖放,尤其是跨多個 JComponents 等,您只會這樣做對于 JPanel
等,您也希望能夠刪除 Swing 組件:
Than create an instance of ComponentDrag
class by passing argument of you container i.e JFrame
/JDialog
or JWindow
and register the draggable components and call setName("Droppable")
on your JPanel
to allow dragging and dropping to take place correctly especially across multiple JComponents etc, you would only do this for the JPanel
s etc that you want the ability to drop Swing components too:
JFrame frame=..;//has access to setGlassPane same applies for JDialog and JWindow
frame.add(panel1);
ComponentDrag cd=new ComponentDrag(frame);
cd.registerComponent(button);
panel1.setName("Droppable");//needed for the dragging and dropping to work correctly especailly over multiple components
祝你一切順利:).
這里有 2 個完整的示例供分析使用:
Here are 2 full examples for analysis purposes:
1) 顯示移動 JButton
并使用 ComponentDrag
并覆蓋其 componentDropped
方法相應地重新定位的邏輯:
1) Show the logic to move JButton
s and re-position the accordingly using ComponentDrag
and overriding its componentDropped
method:
拖動前:
4拖到1位置后:
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class DragButtonsTest {
ArrayList<JButton> buttons = new ArrayList<>();
public DragButtonsTest() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel(new GridLayout(2, 2));
ComponentDrag cd = new ComponentDrag(frame) {
@Override
protected void componentDropped(MouseEvent me) {
HashMap<Integer, JButton> collisions = new HashMap<>();
JButton draggedButton = (JButton) me.getSource();
for (JButton btn : buttons) {//iterate through all buttons and get the number of collsions of each
if (btn != draggedButton) {//dont chck button we were dragging
int col = checkPerPixelCollision(draggedButton, btn);
System.out.println("Button " + btn.getText());
System.out.println(col);
collisions.put(col, btn);
}
}
//lets get the button which had most collisions
int maxCollisions = 0;
JButton intersectingButton = null;
for (Map.Entry<Integer, JButton> entry : collisions.entrySet()) {
Integer collisionCount = entry.getKey();
JButton button = entry.getValue();
if (collisionCount > maxCollisions) {
maxCollisions = collisionCount;
intersectingButton = button;
}
}
boolean reLayout = false;
if (maxCollisions > 0) {//check if there was any
System.out.println("Button " + draggedButton.getText() + " is intersecting more of Button " + intersectingButton.getText());
System.out.println("Collisions: " + maxCollisions);
reLayout = true;
} else {
System.out.println("No change made");
reLayout = false;
}
ArrayList<JButton> tmpButtons = (ArrayList<JButton>) buttons.clone();//create clone of buttons
if (reLayout) {//a button as moved and panel needs to be layed out
buttons.clear();//clear old buttons
for (JButton b : tmpButtons) {//re-order jbuttons
if (b == intersectingButton) {
buttons.add(draggedButton);
} else if (b == draggedButton) {
buttons.add(intersectingButton);
} else {
buttons.add(b);
}
}
panel.removeAll();//remove all buttons
for (JButton btn : buttons) {//iterate through all buttons and get the number of collsions of each
panel.add(btn);//re-add buttons according to arraylist
}
panel.revalidate();
panel.repaint();
}
super.componentDropped(me);
}
};
for (int i = 0; i < 4; i++) {
JButton b = new JButton(String.valueOf(i + 1));
panel.add(b);
buttons.add(b);
cd.registerComponent(b);
}
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new DragButtonsTest();
}
});
}
public HashSet<String> getMask(JButton e) {
HashSet<String> mask = new HashSet<>();
int pixel, a;
BufferedImage bi = componentToImage(e); //gets the current image being shown
for (int i = 0; i < bi.getWidth(); i++) { // for every (x,y) component in the given box,
for (int j = 0; j < bi.getHeight(); j++) {
pixel = bi.getRGB(i, j); // get the RGB value of the pixel
a = (pixel >> 24) & 0xff;
if (a != 0) { // if the alpha is not 0, it must be something other than transparent
mask.add((e.getX() + i) + "," + (e.getY() - j)); // add the absolute x and absolute y coordinates to our set
}
}
}
return mask; //return our set
}
public static BufferedImage componentToImage(Component component) {
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
Graphics g = img.getGraphics();
component.paintAll(g);
return img;
}
// Returns true if there is a collision between object a and object b
public int checkPerPixelCollision(JButton b, JButton b2) {
// This method detects to see if the images overlap at all. If they do, collision is possible
int ax1 = (int) b2.getX();
int ay1 = (int) b2.getY();
int ax2 = ax1 + (int) b2.getWidth();
int ay2 = ay1 + (int) b2.getHeight();
int bx1 = (int) b.getX();
int by1 = (int) b.getY();
int bx2 = bx1 + (int) b.getWidth();
int by2 = by1 + (int) b.getHeight();
if (by2 < ay1 || ay2 < by1 || bx2 < ax1 || ax2 < bx1) {
return 0; // Collision is impossible.
} else { // Collision is possible.
// get the masks for both images
HashSet<String> maskPlayer1 = getMask(b2);
HashSet<String> maskPlayer2 = getMask(b);
maskPlayer1.retainAll(maskPlayer2); // Check to see if any pixels in maskPlayer2 are the same as those in maskPlayer1
if (maskPlayer1.size() > 0) { // if so, than there exists at least one pixel that is the same in both images, thus
return maskPlayer1.size();
}
}
return 0;
}
}
class ComponentDrag {
private MouseAdapter ma;
private ArrayList<JComponent> components = new ArrayList<>();
private int startingX, startingY;
private boolean autoLayout = true;
private final JFrame container;
private JPanel glassPane;
boolean firstTime = true;
private JComponent lastClickedContainer;
public ComponentDrag(final JFrame container) {
this.container = container;
glassPane = new JPanel();
glassPane.setOpaque(false);
glassPane.setLayout(null);
this.container.setGlassPane(glassPane);
new Timer(10, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
if (container.isVisible()) {
glassPane.setVisible(true);
((Timer) ae.getSource()).stop();
}
}
}).start();
ma = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
componentPressed(me);
}
@Override
public void mouseReleased(MouseEvent me) {
super.mouseReleased(me);
componentDropped(me);
}
@Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
componentDragged(me);
}
};
}
public JComponent findDroppableUnderGlassPane(Point p, Container container, Component source) {
JComponent c = null;
Component[] comps = container.getComponents();
for (Component com : comps) {
if (com.getName() != null) {
if (com.getName().equals("Droppable") && com instanceof JComponent) {
if (com.contains(SwingUtilities.convertPoint(source, p, com))) {
return (JComponent) com;
}
} else if (com instanceof Container) {
findDroppableUnderGlassPane(p, (Container) com, source);
}
}
}
return c;
}
public boolean isAutoLayout() {
return autoLayout;
}
public void setAutoLayout(boolean autoLayout) {
this.autoLayout = autoLayout;
}
protected void componentDropped(MouseEvent me) {
firstTime = true;
Component droppedComponent = (Component) me.getSource();
droppedComponent.setCursor(null);
JComponent jc = findDroppableUnderGlassPane(me.getPoint(), container.getContentPane(), (Component) me.getSource());
if (jc != null) {
glassPane.removeAll();
glassPane.revalidate();
glassPane.repaint();
jc.add(droppedComponent);
System.out.println("Removed from glasspane and added to: " + jc);
if (autoLayout) {
if (lastClickedContainer != null) {
lastClickedContainer.revalidate();
lastClickedContainer.repaint();
}
droppedComponent.revalidate();
droppedComponent.repaint();
jc.revalidate();
jc.repaint();
}
} else {
glassPane.removeAll();
glassPane.revalidate();
glassPane.repaint();
if (lastClickedContainer != null) {
lastClickedContainer.add(droppedComponent);
lastClickedContainer.revalidate();
lastClickedContainer.repaint();
}
}
}
protected void componentPressed(MouseEvent me) {
JComponent jc = findDroppableUnderGlassPane(me.getPoint(), container.getContentPane(), (Component) me.getSource());
if (jc != null && jc.getName().equals("Droppable")) {
lastClickedContainer = jc;
System.out.println("Pressed: " + lastClickedContainer);
}
boolean clickedRegisteredComponent = false;
Component clickedComponent = (Component) me.getSource();
for (Component component : ComponentDrag.this.components) {
if (component.equals(clickedComponent)) {
clickedRegisteredComponent = true;
break;
}
}
if (clickedRegisteredComponent) {
startingX = me.getX();
startingY = me.getY();
clickedComponent.setCursor(new Cursor(Cursor.MOVE_CURSOR));
}
}
protected void componentDragged(MouseEvent me) {
Component draggedComponent = (Component) me.getSource();
if (firstTime && lastClickedContainer != null) {
firstTime = false;
lastClickedContainer.remove(draggedComponent);
lastClickedContainer.revalidate();
lastClickedContainer.repaint();
glassPane.add(draggedComponent);
glassPane.revalidate();
glassPane.repaint();
System.out.println("Removed from: " + lastClickedContainer + "
And added to glasspane for dragging");
}
//MouseEvent will refire on each drag with the position being relative to the firing Component
draggedComponent.setLocation((me.getX() - startingX) + draggedComponent.getLocation().x, (me.getY() - startingY) + draggedComponent.getLocation().y);
}
void registerComponent(JComponent draggableComp) {
draggableComp.addMouseListener(ma);
draggableComp.addMouseMotionListener(ma);
components.add(draggableComp);
}
void deregisterComponent(JComponent draggableComp) {
draggableComp.removeMouseListener(ma);
draggableComp.removeMouseMotionListener(ma);
components.remove(draggableComp);
}
}
2) 簡單展示如何在JPanel
s
2) Simply shows how to drag 2 JLabel
s across JPanel
s
拖我標簽拖之前:
標簽拖動后:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
*
* @author David
*/
public class DragOverMultipleComponentsTest {
public DragOverMultipleComponentsTest() {
createAndShowUI();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new DragOverMultipleComponentsTest();
}
});
}
private void createAndShowUI() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel draggableLabel = new JLabel("<- Drag me");
JLabel draggableLabel2 = new JLabel("<- Drag me too");
JLabel labelPanel1 = new JLabel("Drag 'em here");
JPanel panel1 = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
panel1.add(labelPanel1);
panel1.setName("Droppable");
JLabel labelPanel2 = new JLabel("Drag 'em here");
JPanel panel2 = new JPanel();
panel2.add(labelPanel2);
panel2.add(draggableLabel);
panel2.add(draggableLabel2);
panel2.setName("Droppable");
JSeparator js = new JSeparator(JSeparator.VERTICAL);
ComponentDrag cd = new ComponentDrag(frame);
cd.registerComponent(draggableLabel);
cd.registerComponent(draggableLabel2);
frame.add(panel1, BorderLayout.WEST);
frame.add(js);
frame.add(panel2, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
}
}
class ComponentDrag {
private MouseAdapter ma;
private ArrayList<JComponent> components = new ArrayList<>();
private int startingX, startingY;
private boolean autoLayout = true;
private final JFrame container;
private JPanel glassPane;
boolean firstTime = true;
private JComponent lastClickedContainer;
public ComponentDrag(final JFrame container) {
this.container = container;
glassPane = new JPanel();
glassPane.setOpaque(false);
glassPane.setLayout(null);
this.container.setGlassPane(glassPane);
new Timer(10, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
if (container.isVisible()) {
glassPane.setVisible(true);
((Timer) ae.getSource()).stop();
}
}
}).start();
ma = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
componentPressed(me);
}
@Override
public void mouseReleased(MouseEvent me) {
super.mouseReleased(me);
componentDropped(me);
}
@Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
componentDragged(me);
}
};
}
public JComponent findDroppableUnderGlassPane(Point p, Container container, Component source) {
JComponent c = null;
Component[] comps = container.getComponents();
for (Component com : comps) {
if (com.getName() != null) {
if (com.getName().equals("Droppable") && com instanceof JComponent) {
if (com.contains(SwingUtilities.convertPoint(source, p, com))) {
return (JComponent) com;
}
} else if (com instanceof Container) {
findDroppableUnderGlassPane(p, (Container) com, source);
}
}
}
return c;
}
public boolean isAutoLayout() {
return autoLayout;
}
public void setAutoLayout(boolean autoLayout) {
this.autoLayout = autoLayout;
}
protected void componentDropped(MouseEvent me) {
firstTime = true;
Component droppedComponent = (Component) me.getSource();
droppedComponent.setCursor(null);
JComponent jc = findDroppableUnderGlassPane(me.getPoint(), container.getContentPane(), (Component) me.getSource());
if (jc != null) {
glassPane.removeAll();
glassPane.revalidate();
glassPane.repaint();
jc.add(droppedComponent);
System.out.println("Removed from glasspane and added to: " + jc);
if (autoLayout) {
if (lastClickedContainer != null) {
lastClickedContainer.revalidate();
lastClickedContainer.repaint();
}
droppedComponent.revalidate();
droppedComponent.repaint();
jc.revalidate();
jc.repaint();
}
} else {
glassPane.removeAll();
glassPane.revalidate();
glassPane.repaint();
if (lastClickedContainer != null) {
lastClickedContainer.add(droppedComponent);
lastClickedContainer.revalidate();
lastClickedContainer.repaint();
}
}
}
protected void componentPressed(MouseEvent me) {
JComponent jc = findDroppableUnderGlassPane(me.getPoint(), container.getContentPane(), (Component) me.getSource());
if (jc != null && jc.getName().equals("Droppable")) {
lastClickedContainer = jc;
System.out.println("Pressed: " + lastClickedContainer);
}
boolean clickedRegisteredComponent = false;
Component clickedComponent = (Component) me.getSource();
for (Component component : ComponentDrag.this.components) {
if (component.equals(clickedComponent)) {
clickedRegisteredComponent = true;
break;
}
}
if (clickedRegisteredComponent) {
startingX = me.getX();
startingY = me.getY();
clickedComponent.setCursor(new Cursor(Cursor.MOVE_CURSOR));
}
}
protected void componentDragged(MouseEvent me) {
Component draggedComponent = (Component) me.getSource();
if (firstTime && lastClickedContainer != null) {
firstTime = false;
lastClickedContainer.remove(draggedComponent);
lastClickedContainer.revalidate();
lastClickedContainer.repaint();
glassPane.add(draggedComponent);
glassPane.revalidate();
glassPane.repaint();
System.out.println("Removed from: " + lastClickedContainer + "
And added to glasspane for dragging");
}
//MouseEvent will refire on each drag with the position being relative to the firing Component
draggedComponent.setLocation((me.getX() - startingX) + draggedComponent.getLocation().x, (me.getY() - startingY) + draggedComponent.getLocation().y);
}
void registerComponent(JComponent draggableComp) {
draggableComp.addMouseListener(ma);
draggableComp.addMouseMotionListener(ma);
components.add(draggableComp);
}
void deregisterComponent(JComponent draggableComp) {
draggableComp.removeMouseListener(ma);
draggableComp.removeMouseMotionListener(ma);
components.remove(draggableComp);
}
}
這篇關于如何設置優先級鼠標偵聽器的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!