我正在用Java开发游戏,面临以下挑战。
我有2个JPanels
,需要在视觉上将形状从一个拖动JPanel
到另一个。我有使用这个工作GlassPane
从JFrame
。当我按下鼠标拖动形状时,GlassPane
激活该形状并将其转移到glassPane。因此,您需要将mousePressed
状态从转移JPanels mouseAdapter
到glassPanes mouseAdapter
。我通过使用Robot类解决了这个问题,该类模拟mousePressed
了glassPane被激活后的另一个事件。
现在出现了问题,此解决方法仅在Windows上有效,而不适用于mac osx,在osx上JPanels mouseAdapter
,只要按下mousebutton
,鼠标就会一直与通话。那么,有谁知道如何以适当的方式在按下鼠标按钮时将mousePressed
状态从一个状态转移mouseAdapter
到另一个状态?(释放该按钮并再次按下它是不可行的,因为这样做会破坏拖动的目的。)
为什么不将MouseListener仅添加到玻璃板上,并在mousePressed方法中获取鼠标的位置(点),然后通过在保存组件的容器上调用getComponentAt(Point
p)来获取可拖动组件?然后,您可以将组件放入玻璃板并将其拖到那里。
或另一个想法:为什么不简单地在拖动的组件本身上添加MouseAdapter并将其保留在组件上?只要注意使鼠标相对于屏幕定位并相对于其容器移动组件,则组件位于contentPane还是玻璃窗格中都应该没有问题。
编辑:或与MeBigFatGuy的出色建议。
编辑2:半醉半夜尝试一个不像我那么简单的概念证明程序,该程序通过仅将MouseListener添加到玻璃窗格来移动形状。
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
@SuppressWarnings("serial")
public class DragShapesMainPanel extends JPanel {
private static final Dimension RIGHT_PANEL_SIZE = new Dimension(300, 450);
private static final int SHAPE_COUNT = 10;
private static final int SHAPE_WIDTH = 40;
private static final int SHAPE_HEIGHT = SHAPE_WIDTH;
private Shape draggedShape = null;
private DragShapesPanel leftPanel = new DragShapesPanel(Color.blue, Color.black);
private DragShapesPanel rightPanel = new DragShapesPanel(Color.blue, Color.black);
private DragShapesGlassPanel glassPanel = new DragShapesGlassPanel(Color.pink, Color.gray);
private Random random = new Random();
public DragShapesMainPanel() {
setLayout(new GridLayout(1, 0));
setBackground(Color.black);
rightPanel.setPreferredSize(RIGHT_PANEL_SIZE);
leftPanel.setPreferredSize(RIGHT_PANEL_SIZE);
rightPanel.setBorder(BorderFactory.createLineBorder(Color.black, 1));
leftPanel.setBorder(BorderFactory.createLineBorder(Color.black, 1));
add(leftPanel);
add(rightPanel);
MouseAdapter myMouseAdapter = new MyMouseAdapter();
glassPanel.addMouseListener(myMouseAdapter);
glassPanel.addMouseMotionListener(myMouseAdapter);
glassPanel.setOpaque(false);
glassPanel.setVisible(true);
for (int i = 0; i < SHAPE_COUNT; i++) {
leftPanel.addShape(createRandomShape(i));
}
}
private Shape createRandomShape(int i) {
Dimension size = rightPanel.getPreferredSize();
int x = random.nextInt(size.width - SHAPE_WIDTH);
int y = random.nextInt(size.height - SHAPE_HEIGHT);
switch (i % 3) {
case 0:
return new Ellipse2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT);
case 1:
return new Rectangle2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT);
case 2:
return new RoundRectangle2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT, 15, 15);
default:
break;
}
return null;
}
public JPanel getGlassPanel() {
return glassPanel;
}
private class MyMouseAdapter extends MouseAdapter {
Point initialLocation = null;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
Component componentAt = getComponentAt(e.getPoint());
if (!(componentAt instanceof DragShapesPanel)) {
return;
}
initialLocation = e.getPoint();
DragShapesPanel dsPanel = (DragShapesPanel) getComponentAt(initialLocation);
int x = initialLocation.x - dsPanel.getLocation().x;
int y = initialLocation.y - dsPanel.getLocation().y;
Point p = new Point(x, y);
Shape shape = dsPanel.getShapeAtPoint(p);
if (shape == null) {
initialLocation = null;
return;
}
dsPanel.removeShape(shape);
dsPanel.repaint();
int tx = dsPanel.getLocation().x;
int ty = dsPanel.getLocation().y;
draggedShape = AffineTransform.getTranslateInstance(tx, ty).createTransformedShape(shape);
glassPanel.setShape(draggedShape);
glassPanel.repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (initialLocation == null) {
return;
}
Point currentLocation = e.getPoint();
int x = currentLocation.x - initialLocation.x;
int y = currentLocation.y - initialLocation.y;
glassPanel.translate(new Point(x, y));
glassPanel.repaint();
}
@Override
public void mouseReleased(final MouseEvent e) {
if (initialLocation == null) {
return;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Component componentAt = getComponentAt(e.getPoint());
if (!(componentAt instanceof DragShapesPanel)) {
return;
}
DragShapesPanel dsPanel = (DragShapesPanel) getComponentAt(e.getPoint());
Point currentLocation = e.getPoint();
int x = currentLocation.x - initialLocation.x;
int y = currentLocation.y - initialLocation.y;
Point dspPoint = dsPanel.getLocation();
int tx = x - dspPoint.x;
int ty = y - dspPoint.y;
draggedShape = AffineTransform.getTranslateInstance(tx, ty).createTransformedShape(
draggedShape);
dsPanel.addShape(draggedShape);
dsPanel.repaint();
initialLocation = null;
glassPanel.setShape(null);
glassPanel.translate(new Point(0, 0));
}
});
}
}
private static void createAndShowUI() {
DragShapesMainPanel dragShapesMain = new DragShapesMainPanel();
JFrame frame = new JFrame("DragShapes");
frame.getContentPane().add(dragShapesMain);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setGlassPane(dragShapesMain.getGlassPanel());
frame.getGlassPane().setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
@SuppressWarnings("serial")
class DragShapesPanel extends JPanel {
private static final float STROKE_WIDTH = 3;
private static final Stroke SHAPE_STROKE = new BasicStroke(STROKE_WIDTH);
private List<Shape> shapeList = new ArrayList<Shape>();
private Color shapeFillColor;
private Color shapeBorderColor;
public DragShapesPanel(Color fillColor, Color borderColor) {
this.shapeFillColor = fillColor;
this.shapeBorderColor = borderColor;
}
public void addShape(Shape s) {
shapeList.add(s);
}
public void removeShape(Shape s) {
shapeList.remove(s);
}
public Shape getShapeAtPoint(Point p) {
Shape shapeAtPoint = null;
for (int i = shapeList.size() - 1; i >= 0; i--) {
if (shapeList.get(i).contains(p)) {
return shapeList.get(i);
}
}
return shapeAtPoint;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Shape shape : shapeList) {
g2.setColor(shapeFillColor);
g2.fill(shape);
g2.setStroke(SHAPE_STROKE);
g2.setColor(shapeBorderColor);
g2.draw(shape);
}
}
}
@SuppressWarnings("serial")
class DragShapesGlassPanel extends JPanel {
private static final float STROKE_WIDTH = 1.5f;
private static final Stroke SHAPE_STROKE = new BasicStroke(STROKE_WIDTH);
private Shape shape = null;
private Color shapeFillColor;
private Color shapeBorderColor;
private AffineTransform transform = new AffineTransform();
public DragShapesGlassPanel(Color fillColor, Color borderColor) {
this.shapeFillColor = fillColor;
this.shapeBorderColor = borderColor;
}
public void setShape(Shape shape) {
this.shape = shape;
}
public void translate(Point p) {
transform = AffineTransform.getTranslateInstance(p.x, p.y);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (shape == null) {
return;
}
Graphics2D g2 = (Graphics2D) g;
g2.transform(transform);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(shapeFillColor);
g2.fill(shape);
g2.setStroke(SHAPE_STROKE);
g2.setColor(shapeBorderColor);
g2.draw(shape);
}
}
我有一个子类JPanel的PointPanel,我想在其中实现以下行为:如果鼠标悬停在实例上,按下shift键,鼠标光标变为手光标;如果松开shift键,鼠标光标将变回默认光标。 为了实现这一点,我尝试在构造函数中添加一个: 这种方法不起作用。 包含此面板的窗口应该具有焦点,因为它是应用程序的唯一可见窗口。 我错过了什么?
} 完整错误消息:
我试图在单击时更改底部导航栏中FloatingActionButton()的图标。它工作得很好,但只有当我离开屏幕回来的时候?有人知道出什么事了吗?调用changeIcon()中的Setstate应该强制重新呈现,还是我错了? 我真的很感激你的帮助:)
问题内容: 有没有一种方法可以检测JavaScript中的鼠标按钮当前是否处于按下状态? 我知道“ mousedown”事件,但这不是我所需要的。按下鼠标按钮后的一段时间,我希望能够检测它是否仍被按下。 这可能吗? 问题答案: 关于Pax的解决方案:如果用户有意或无意地单击了多个按钮,则该按钮将不起作用。不要问我我怎么知道:-(。 正确的代码应如下所示: 通过这样的测试: 如果您想知道按下了什么按
问题内容: 我在JList中有一个单词列表。每次将鼠标光标指向一个单词时,我都希望光标变为手形光标。现在我的问题是该怎么做? 有人可以帮我解决这个问题吗? 问题答案: 在JList上使用MouseMotionListener来检测鼠标何时输入,然后调用将其转换为。 样例代码:
单击并按住向上/向下箭头按钮时,微调器更新的速度很慢。有没有办法提高更换速度? 当我用鼠标单击、单击、单击时,旋转器值的变化和我单击一样快。如果我每次按下键盘上的上/下箭头,或者如果我按住上/下箭头键,它也会快速变化。我希望当我单击并按住箭头按钮时,值能快速更改。 有人知道怎么做吗?