java - 每次监听器执行时如何更改面板的图形?

标签 java swing graphics listener panel

我正在尝试更改按下鼠标后制作的点的颜色。因此,理想情况下,您将在程序运行时连续绘制随机颜色的点。似乎无法弄清楚这一点,因为如果我尝试引用监听器中的图形“页面”,它不会被识别。如果我将随机颜色线放入图形构造函数中,则程序会以一种随机颜色运行,并且每个点都不会改变。

import java.util.ArrayList;
import java.util.Random;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;

public class DotsPanel extends JPanel {
    private final int SIZE = 6; // radius of each dot
    Random rand = new Random();
    private ArrayList<Point> pointList;
    Color randomColor = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));

    public DotsPanel() {
        pointList = new ArrayList<Point>();

        addMouseListener(new DotsListener());
        addMouseMotionListener(new DotsListener());

        setBackground(Color.black);
        setPreferredSize(new Dimension(300, 200));
    }

    public void paintComponent(Graphics page) {
        super.paintComponent(page);
        for (Point spot : pointList) {
            page.setColor(randomColor);
            page.fillOval(spot.x - SIZE, spot.y - SIZE, SIZE * 2, SIZE * 2);
        }
        page.drawString("Count: " + pointList.size(), 5, 15);
    }

    private class DotsListener implements MouseListener, MouseMotionListener {
        public void mousePressed(MouseEvent event) {
            pointList.add(event.getPoint());
            repaint();
        }

        public void mouseDragged(MouseEvent event) {
            pointList.add(event.getPoint());
            repaint();
        }

        public void mouseClicked(MouseEvent event) {
        }

        public void mouseReleased(MouseEvent event) {
        }

        public void mouseEntered(MouseEvent event) {
        }

        public void mouseExited(MouseEvent event) {
        }

        public void mouseMoved(MouseEvent e) {
        }
    }
}

最佳答案

首先,您需要将点与颜色相关联,可以通过以下两种方式之一完成:

  1. 通过在 BufferedImage 上绘制点,并在组件的绘制方法(JPanel 的 PaintComponent)中绘制该图像,或者
  2. 通过某种方式直接将颜色与点关联起来,例如与 Map 或将两者结合在一起的自定义对象,从而在 PaintComponent 方法中绘制所有点及其关联颜色。

在您的监听器中,创建您的点及其颜色,并使用您想要的任何技术将它们关联起来。

例如,使用HashMap<Shape, Color>关联一个 Shape(这里是一个包含圆的 Ellipse2D)和一个 Color,名为 shapeColorMap

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.*;

@SuppressWarnings("serial")
public class RandomDot extends JPanel {
    // size of JPanel
    private static final int PREF_W = 800;
    private static final int PREF_H = 650;
    // width of dot
    public static final int DOT_WIDTH = 40;
    private Map<Shape, Color> shapeColorMap = new HashMap<>();

    public RandomDot() {
        setPreferredSize(new Dimension(PREF_W, PREF_H));
        addMouseListener(new MyMouse());
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // smooth out jaggies in graphics
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // iterate through the Map getting color and circle
        for (Entry<Shape, Color> entry : shapeColorMap.entrySet()) {
            Color color = entry.getValue();
            Shape shape = entry.getKey();
            g2.setColor(color);
            g2.fill(shape);
        }
    }

    private class MyMouse extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
            // get a random color using HSB
            float multiplier = 0.3f;
            float hue = (float)Math.random();
            float saturation = (float) (multiplier * Math.random() + (1 - multiplier));
            float brightness = (float) (multiplier * Math.random() + (1 - multiplier));
            Color color = Color.getHSBColor(hue, saturation, brightness);

            // create a circle at mouse click
            double x = e.getX() - DOT_WIDTH / 2;
            double y = e.getY() - DOT_WIDTH / 2;
            double w = DOT_WIDTH;
            Ellipse2D circle = new Ellipse2D.Double(x, y, w, w);

            // put both into the map
            shapeColorMap.put(circle, color);

            // repaint
            repaint();
        }
    }

    private static void createAndShowGui() {
        RandomDot mainPanel = new RandomDot();

        JFrame frame = new JFrame("RandomDot");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

关于java - 每次监听器执行时如何更改面板的图形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52139486/

相关文章:

java - 在 bean 变量中传递 <br/> 以在 <h :outputLabel/> 中打印

java - JUnit 应用程序套件测试

java - JTable渲染后调用方法: is there a onRenderFinished event?

java - 如何为H2数据库用户定义函数和存储过程指定java类版本?

java - Spring 模块和 Spring 启动器模块之间的区别

java - UIManager setLookAndFeel 不起作用

java - 如何找到 Java Desktop API 在 Linux 上需要哪些库?

algorithm - 与 XOR 类似的简单纹理生成算法有哪些?

java 什么更重 : Canvas or paintComponent()?

java - 我应该为 Java 图形使用什么 IDE?