java - 在 Graphics2D 中将鼠标监听器与多边形相结合

标签 java swing paintcomponent graphics2d mouselistener

我尝试为我选择的数据类扩展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/

相关文章:

java - Pair 类 getPair 方法

java - Java 中的 ConnectFour 程序问题

java - 如何在 JScrollPane 中启用滚动?

java - 如何停止在 JFrame 中调整 JPanel 的大小

java - 油漆组件是如何工作的?

java - 使用 skmap 的 FileNotFoundException

java - BufferedImage 产生黑色输出

java - PaintComponent 未被调用 - Java

java - Jpanel 和 Jframe 的重绘方法有何不同?

java - Apache POI : change page format for Excel worksheet