当前位置: 首页 > 知识库问答 >
问题:

如何在我的矩形(自定义按钮)中添加mouselistener,以便在Java中重新执行paintcomponent?

谯德佑
2023-03-14

我的脚本生成了一个带有随机选择的资源和骰子数分配的六边形瓷砖的游戏板。我想添加一个按钮到GUI重新生成板。因为我在JPanel中使用paintcomponent,所以我必须使用我创建的自定义button类。该类只是根据指定的参数绘制矩形。我想在这个矩形中添加一个mouselistener,它清除JPanel内容并重新执行drawGUI()方法。该板生成完全罚款,但mouselistener我目前没有做任何事情。我在代码中是否将mouselstener放在了正确的位置?我把mouselistener写对了吗?我做错了什么?下面是我的代码:

主窗口的java:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SettlersofCatan extends JPanel {

    private static final long serialVersionUID = 1L;
    private final int WIDTH = 1200;
    private final int HEIGHT = 800;
    private ArrayList<String> resources = new ArrayList();
    private Hashtable<String, Integer> colors = new Hashtable();
    public ArrayList<Integer> diceSpaces = new ArrayList<>();
    public Tile[] tiles = new Tile[19];
    public Object[] rsrcs;
    public CButton regenerate = new CButton();

    private Font font = new Font("Arial", Font.BOLD, 18);
    FontMetrics metrics;

    public SettlersofCatan() {
        setPreferredSize(new Dimension(WIDTH, HEIGHT));

        resources.add("Brick");
        resources.add("Brick");
        resources.add("Brick");
        resources.add("Wool");
        resources.add("Wool");
        resources.add("Wool");
        resources.add("Wool");
        resources.add("Lumber");
        resources.add("Lumber");
        resources.add("Lumber");
        resources.add("Lumber");
        resources.add("Stone");
        resources.add("Stone");
        resources.add("Stone");
        resources.add("Wheat");
        resources.add("Wheat");
        resources.add("Wheat");
        resources.add("Wheat");

        colors.put("Brick", 0x990000);
        colors.put("Wool", 0xFFFFFF);
        colors.put("Lumber", 0x006600);
        colors.put("Stone", 0x666666);
        colors.put("Wheat", 0xFFFF33);
        colors.put("Wasteland", 0xCC9966);

        diceSpaces.add(2);
        diceSpaces.add(3);
        diceSpaces.add(3);
        diceSpaces.add(4);
        diceSpaces.add(4);
        diceSpaces.add(5);
        diceSpaces.add(5);
        diceSpaces.add(6);
        diceSpaces.add(6);
        diceSpaces.add(8);
        diceSpaces.add(8);
        diceSpaces.add(9);
        diceSpaces.add(9);
        diceSpaces.add(10);
        diceSpaces.add(10);
        diceSpaces.add(11);
        diceSpaces.add(11);
        diceSpaces.add(12);

        long seed = System.nanoTime();
        Collections.shuffle(resources, new Random(seed));
        Collections.shuffle(diceSpaces, new Random(seed));

        int index = ThreadLocalRandom.current().nextInt(0, 18 + 1);

        resources.add(index, "Wasteland");
        diceSpaces.add(index, 7);

    }

    @Override
    public void paintComponent(Graphics g) {

        drawGUI(g);

    }

    public void drawGUI(Graphics g){

        Graphics2D g2d = (Graphics2D) g;
        Point origin = new Point(WIDTH / 2, HEIGHT / 2);

        g2d.setStroke(new BasicStroke(4.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER));
        g2d.setFont(font);
        metrics = g.getFontMetrics();

        drawCircle(g2d, origin, 380, true, true, 0x4488FF, 0);
        drawHexGridLoop(g2d, origin, 5, 50, 8);

        regenerate.Background = 0x000000;
        regenerate.Foreground = 0xFFFFFF;
        regenerate.Padding = "7 15";
        regenerate.Text = "Regenerate Board";
        regenerate.Position = new double[] {25, 25};
        regenerate.FontFamily = "Arial";
        regenerate.draw(g2d);
    }

    private class MyMouseListener extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
                if (regenerate.rect.contains(e.getPoint())) {
                    repaint();
                    return;
                }
        }
    }

    private void drawHexGridLoop(Graphics g, Point origin, int size, int radius, int padding) {

        String rsrc;

        double ang30 = Math.toRadians(30);
        double xOff = Math.cos(ang30) * (radius + padding);
        double yOff = Math.sin(ang30) * (radius + padding);
        int half = size / 2;

        int i = 0;
        for (int row = 0; row < size; row++) {

            int cols = size - java.lang.Math.abs(row - half);

            for (int col = 0; col < cols; col++) {

                int xLbl = row < half ? col - row : col - half;
                int yLbl = row - half;
                int x = (int) (origin.x + xOff * (col * 2 + 1 - cols));
                int y = (int) (origin.y + yOff * (row - half) * 3);

                int diceNum = diceSpaces.get(i);
                rsrc = resources.get(i);
                drawHex(g, xLbl, yLbl, x, y, radius, i, colors.get(rsrc), diceNum);
                tiles[i] = new Tile(i, xLbl, yLbl, rsrc, diceSpaces.get(i));
                i++;
            }
        }
    }

    private void drawHex(Graphics g, int posX, int posY, int x, int y, int r, int id, int color, int diceSpace) {
        Graphics2D g2d = (Graphics2D) g;

        Hexagon hex = new Hexagon(x, y, r);
        String text = String.format("%s", diceSpace);
        int w = metrics.stringWidth(text);
        int h = metrics.getHeight();

        hex.draw(g2d, x, y, 0, color, true);
        hex.draw(g2d, x, y, 4, 0xFFDD88, false);

        g.setColor(new Color(0x000000));
        g.drawString(text, x - w/2, y + h/2);
    }

    private String coord(int value) {
        return (value > 0 ? "+" : "") + Integer.toString(value);
    }

    public void drawCircle(Graphics2D g, Point origin, int radius,
            boolean centered, boolean filled, int colorValue, int lineThickness) {
        // Store before changing.
        Stroke tmpS = g.getStroke();
        Color tmpC = g.getColor();

        g.setColor(new Color(colorValue));
        g.setStroke(new BasicStroke(lineThickness, BasicStroke.CAP_ROUND,
                BasicStroke.JOIN_ROUND));

        int diameter = radius * 2;
        int x2 = centered ? origin.x - radius : origin.x;
        int y2 = centered ? origin.y - radius : origin.y;

        if (filled)
            g.fillOval(x2, y2, diameter, diameter);
        else
            g.drawOval(x2, y2, diameter, diameter);

        // Set values to previous when done.
        g.setColor(tmpC);
        g.setStroke(tmpS);
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        SettlersofCatan p = new SettlersofCatan();

        f.setContentPane(p);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}
import java.awt.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;

public class CButton {
    public int Background, Foreground;
    public int Width = 0;
    public int Height = 0;
    public String Padding;
    public int BorderWidth = 0;
    public int BorderColor = 0x000000;
    public double[] Position;
    public String FontFamily;
    public String Text = "";
    public Rectangle rect;

    CButton(){
    }

    public void draw(Graphics2D g2d){


        Font font = new Font(FontFamily, Font.BOLD, 18);
        FontMetrics metrics;
        metrics = g2d.getFontMetrics(font);

        int paddingTop, paddingRight, paddingBottom, paddingLeft, rx, ry, rw, rh, tx, ty, tw, th;
            String[] padding = Padding.split(" ");
            if(padding.length > 2){
                paddingTop = Integer.parseInt(padding[0]);
                paddingRight = Integer.parseInt(padding[1]);
                paddingBottom = Integer.parseInt(padding[2]);
                paddingLeft = Integer.parseInt(padding[3]);
            } else if(padding.length == 2){
                paddingTop = Integer.parseInt(padding[0]);
                paddingRight = Integer.parseInt(padding[1]);
                paddingBottom = Integer.parseInt(padding[0]);
                paddingLeft = Integer.parseInt(padding[1]);
            } else {
                paddingTop = Integer.parseInt(padding[0]);
                paddingRight = Integer.parseInt(padding[0]);
                paddingBottom = Integer.parseInt(padding[0]);
                paddingLeft = Integer.parseInt(padding[0]);
            }

        if(BorderWidth != 0){
            g2d.setColor(new Color(BorderColor));
            g2d.drawRect((int)Position[0], (int)Position[1], Width, Height);
        }

        tw = metrics.stringWidth(Text);
        th = metrics.getHeight();

        rx = (int) Position[0];
        ry = (int) Position[1];
        if(Padding != null){
            rw = tw + paddingLeft + paddingRight;
            rh = th + paddingTop + paddingBottom;
        } else if(Width != 0 && Height != 0){
           rw = Width;
           rh = Height;
        } else {
            rw = tw;
            rh = th;
        }

        Rectangle rect = new Rectangle(rx, ry, rw, rh);
        g2d.setColor(new Color(Background));
        g2d.fillRect((int) rect.getX(), (int) rect.getY(), (int) rect.getWidth(), (int) rect.getHeight());

        int x = ((rect.width - metrics.stringWidth(Text)) / 2) + (int) Position[0];
        int y = ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent() + (int) Position[1];

        g2d.setColor(new Color(Foreground));
        g2d.drawString(Text, x, y);

    }


}

共有1个答案

章嘉致
2023-03-14

您应该调用组件上的AddMouseListener(yourMouseListener)来接收鼠标事件。

您可以使用JPanel执行此操作,因为监听器已经检查了感兴趣的矩形部分是否位于单击的下:

addMouseListener(new MyMouseListener());

但是,由于监听器在面板上而不是在“按钮”上,您可能必须根据按钮的位置转换,例如:

private class MyMouseListener extends MouseAdapter {
    @Override
    public void mousePressed(final MouseEvent e) {
        Point clickedPoint = e.getPoint();
        if (regenerate.rect.contains(new Point(clickedPoint.x - regenerate.Position[0], clickedPoint.y - regenerate.Position[1]))) {
            repaint();
            return;
        }
    }
}

注意,在mousepress中不需要return;语句。

 类似资料:
  • 问题内容: 我想制作一个简单的表,其中包含一行自定义按钮。当按下按钮时,我想弹出一个“警告”框。我已经阅读了一些关于此的文章,我不明白为什么我的代码无法正常工作。绘制了按钮,但按下按钮无效。 我在这里描述了三种尝试。 版本1。单击按钮不会触发: HTML代码: 编辑8/2/12-自从我的原始文章以来,我已经学到了一些东西,在这里我描述了另外两次尝试。 版本2:我使用onCellSelect。这行得

  • 我已经搜索并尝试了每个论坛和例子。 我正在Yii2中使用Kartik\DetailViwew,无法在buttons1选项中设置一个自定义按钮。 我正在处理的代码: 在的 根据http://demos.krajee.com/detail-view例子,有一种方法可以定制。但是没有例子。留档没有解释如何做到这一点。 有人能帮忙吗?

  • 我做了,有一个按钮,我想在通知和按钮点击上执行两个不同的

  • 问题内容: 我有一个基于Swing的应用程序,其中包含一个。现在,我想使用唯一的行ID来更新或删除每一行。因此,我想向每行添加一个更新和删除按钮,它们具有支持ActionListener的功能。但是,我不知道如何使用NetBeans执行此操作。 问题答案: 要在列中显示按钮,您需要创建: 一个自定义渲染器以显示JButton 定制编辑器以响应鼠标单击 阅读Swing教程中有关如何使用表的部分。关于

  • 如果我创建一个继承JComponent的新类,我重写了JComponent的绘图Component(Graphics g)方法,通过使用g绘制一个圆圈,我应该修改什么才能使MouseListener仅在我单击组件的边界内时触发? 因为我在组件的构造函数中添加了setBounds(…)然后添加了一个MouseListener,但它会在我每次单击自定义组件所在容器中的任何位置时触发,而不仅仅是在我单击

  • 问题内容: 我只是试图在我的注释点添加一个细节按钮而被卡住,不幸的是,我不知道该怎么做。有人可以帮我吗? 下图显示了我想要实现的目标。谢谢! MapKitViewController: 问题答案: 您做对了,您只需要实现这些方法即可添加按钮以及标题和副标题 iOS 8和Xcode 6 查看我的输出。