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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每次监听器执行时如何更改面板的图形?相关的知识,希望对你有一定的参考价值。

我试图改变鼠标按下后点的颜色。理想情况下,在程序运行时,您将不断地绘制随机颜色的点。似乎无法解决这个问题,因为如果我尝试在听众中引用图形“页面”,则无法识别。如果我将随机颜色线放在图形构造函数中,那么程序将以一种随机颜色运行,并且每个点都不会更改。

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)和一个颜色,称为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());
    }
}

以上是关于每次监听器执行时如何更改面板的图形?的主要内容,如果未能解决你的问题,请参考以下文章

每当程序唤醒时,React Native如何执行一段代码?

每次更新数组时如何向侦听器发出消息?

Android - 多个视图或运行时片段替换​​?

如何防止在方向更改时重新创建片段寻呼机中的片段?

为 SWF 扩展面板添加关闭和更改 FLA 文档的事件侦听器。使用 ActionScript、JSFL

如何在屏幕方向更改时附加片段?