我尝试为我选择的数据类扩展Polygon
(实现MouseListener
)。我在父 JPanel
中的 paintComponent
覆盖正在使用 渲染扩展的
- 它渲染得很好!Polygon
类(我将其称为 Hexagon
) >.fillPolygon
但它不允许我与它的代码中实现的 MouseListener
交互。我是否缺少某个阶段?
环顾四周寻找灵感,得出了这个:
https://docs.oracle.com/javase/tutorial/2d/advanced/user.html
不幸的是,这限制了应用程序 - 它可以很好地处理事件点击,但是对于使用悬停事件,应用于父容器的 MouseListener
意味着它仅跟踪进入/退出该容器。没有办法让它在进入/退出该容器内的 Shape
时工作。
六边形
(抽象类):
import java.awt.Polygon;
import java.util.ArrayList;
import spare.Theme;
public abstract class Hexagon extends Polygon {
private static final long serialVersionUID = 1L;
public enum HEX_TYPE { ALIVE, INFECTED, DEAD };
public enum SELECTION_TYPE { SELECTED, GROUPED, NONE };
private int hexEdgeWidth = 20;
private int hexBorderWidth = 3;
private ArrayList<Hexagon> children;
private Theme theme;
private boolean hover = false;
private boolean selected = false;
public ArrayList<Hexagon> getChildren() {
return children;
}
public int getHexEdgeWidth() {
return hexEdgeWidth;
}
public void setHexEdgeWidth(int hexEdgeWidth) {
this.hexEdgeWidth = hexEdgeWidth;
}
public int getHexBorderWidth() {
return hexBorderWidth;
}
public void setHexBorderWidth(int hexBorderWidth) {
this.hexBorderWidth = hexBorderWidth;
}
public void setChildren(ArrayList<Hexagon> children) {
this.children = children;
}
public Theme getTheme() {
return theme;
}
public void setTheme(Theme theme) {
this.theme = theme;
}
public boolean isHover() {
return hover;
}
public void setHover(boolean hover) {
this.hover = hover;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
BasicHexagon
(具体子类):
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import spare.Theme;
public class BasicHexagon extends Hexagon implements MouseListener {
private static final long serialVersionUID = 1L;
public BasicHexagon() {
setChildren(null);
int n = 6;
int size = getHexEdgeWidth();
for (int i = 0; i < n; i++) {
// x + radius * cosine of angle * iteration in radians
// y + radius * sine of angle * iteration in radians
addPoint(
(int) (size * Math.cos(Math.toRadians(360 / n * i))),
(int) (size * Math.sin(Math.toRadians(360 / n * i))));
}
setTheme(new Theme(
new Color(255, 255, 255, 180), // primary
new Color(255, 255, 255, 255), // primary hover
new Color(255, 0, 0, 180), // secondary
new Color(255, 0, 0, 255), // secondary hover
new Color(255, 255, 100, 255), // border
new Color(255, 255, 100, 255))); // text
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("clicked");
BasicHexagon bH = (BasicHexagon) e.getSource();
if(bH.isSelected()) {
bH.setSelected(false);
} else {
bH.setSelected(true);
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
BasicHexagon bH = (BasicHexagon) e.getSource();
bH.setHover(true);
System.out.println("in the zone");
}
@Override
public void mouseExited(MouseEvent e) {
BasicHexagon bH = (BasicHexagon) e.getSource();
bH.setHover(false);
System.out.println("fleeing");
}
}
paintComponent
用于我的自定义 JPanel
:
@Override
public void paintComponent(Graphics g) {
Toolkit.getDefaultToolkit().sync();
super.paintComponent(g);
switch (getGameState()) {
case IN_GAME:
doIngameDrawing(g);
break;
case END_GAME:
break;
case PAUSED:
break;
case PRE_GAME:
break;
default:
break;
}
}
private void doIngameDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
for(Hexagon h : getTiles()) {
h.translate(getPreferredSize().width / 2, getPreferredSize().height / 2);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if(h.isHover() && h.isSelected()) {
g2d.setColor(h.getTheme().getSecondaryHover());
g2d.fillPolygon(h);
} else if(h.isHover()) {
g2d.setColor(h.getTheme().getPrimaryHover());
g2d.fillPolygon(h);
} else if(h.isSelected()) {
g2d.setColor(h.getTheme().getSecondary());
g2d.fillPolygon(h);
} else {
// draw the normal colours;
g2d.setColor(h.getTheme().getPrimary());
g2d.fillPolygon(h);
}
g2d.setStroke(new BasicStroke(h.getHexBorderWidth()));
g2d.setColor(h.getTheme().getBorder());
g2d.drawPolygon(h);
if(h.getChildren() != null) {
// child rendering goes here
}
}
g2d.dispose();
}
最佳答案
为此,您必须使用mouseMoved()
。然后您可以检查鼠标光标当前位于哪个形状并做出相应的 react 。你可以这样做:
// This is in your custom JPanel, which for simplicity is also its own MouseListener.
// Assuming getHexagons() returns Hexagon[].
// Assuming Hexagon implements MouseListener.
private Hexagon lastHovered;
public void mouseMoved(MouseEvent e) {
Hexagon current = null;
boolean changed = false;
for (Hexagon hex : getHexagons()) {
if (hex.contains(e.getX(), e.getY())) {
current = hex;
break;
}
}
if (lastHovered != current) {
changed = true;
if (lastHovered != null) {
lastHovered.mouseExited(e);
}
if (current != null) {
current.mouseEntered(e);
}
}
lastHovered = current;
if (changed) {
repaint();
}
}
由于 contains()
是 Shape
的一种方法,因此它适用于任何形状。由于您的形状实现了 MouseListener
,因此您可以实现进入/退出功能并将鼠标事件传递给它们。
关于java - 在 Graphics2D 中将鼠标监听器与多边形相结合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32848552/