简体   繁体   English

Java:在按住鼠标时填充基于2D数组的图形

[英]Java: Filling in Graphics based on 2D array as mouse held down

So I have a JPanel that is populated by the contents of a 2D array. 所以我有一个由二维数组内容填充的JPanel。 I have a mouse listener which changes the colour of a cell when pressed. 我有一个鼠标监听器,可以在按下时更改单元格的颜色。 My question is, is it possible to have the user drag the mouse over a line of cells and colour them all in succession? 我的问题是,是否有可能让用户将鼠标拖过一行单元格并连续着色它们? I have looked into mouse motion listener but this doesn't seem to help. 我已经研究过鼠标运动监听器,但这似乎没有帮助。

Any ideas? 有任何想法吗?

You can use the mouseDragged() method of the MouseMotionListener in conjunction with the mousePressed() method of the MouseListener . 可以使用mouseDragged()的方法MouseMotionListener与结合mousePressed()的方法MouseListener

The mousePressed() method will handle a simple click without movement, and mouseDragged() will handle any dragging done. mousePressed()方法将处理一个没有移动的简单单击, mouseDragged()将处理任何完成的拖动。 I combined the code I wrote for my answer to your original question here to better clarify what everything does, and a response on your other question would be very much appreciated. 我结合我写我的回答你原来的问题的代码在这里 ,以更好地澄清一切呢,和你的其他问题的回答将是非常赞赏。

package stackoverflow.answers;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class JPanelPaint {
    JPanel panel;
    JFrame frame;
    BufferedImage image;

    public JPanelPaint() {
        image = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
        for (int i = 0; i < image.getWidth(); i++) {
            for (int j=0; j < image.getHeight(); j++) {
                /* I'm just initializing the image with an arbitrary color (white in this case), you can easily change this. */
                image.setRGB(i, j, new Color((int)(255 ), (int)(255 ), (int)(255 )).getRGB());
            }
        }

        frame = new JFrame("JPanel Paint");
        panel = new JPanel() {
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                Rectangle rect = g.getClipBounds();
                g.setColor(Color.white);
                g.fillRect(rect.x, rect.y, rect.width, rect.height);
                for (int i = 0; i < image.getWidth(); i++) {
                    for (int j=0; j < image.getHeight(); j++) {
                        /* Set the color of the "quadpixel" to that of the original cell on the image. */
                        g.setColor(new Color(image.getRGB(i, j)));
                        g.fillRect(j*4, i*4, 4, 4);
                    }
                }


            }
        };

        panel.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent arg0) { }

            @Override
            public void mouseEntered(MouseEvent arg0) { }

            @Override
            public void mouseExited(MouseEvent arg0) { }

            @Override
            public void mousePressed(MouseEvent arg0) {
                /* Y and X are swapped, just a quirk in the JRE */
                /* I'm just setting the pixel with an arbitrary color (black in this case), you can easily change this. */
                image.setRGB(arg0.getY() / 4, arg0.getX() / 4, new Color(0, 0, 0).getRGB());
                panel.repaint();
            }

            @Override
            public void mouseReleased(MouseEvent arg0) { }

        });

        panel.addMouseMotionListener(new MouseMotionListener() {

            @Override
            public void mouseDragged(MouseEvent arg0) {
                /* Y and X are swapped, just a quirk in the JRE */
                /* I'm just setting the pixel with an arbitrary color (black in this case), you can easily change this. */
                image.setRGB(arg0.getY() / 4, arg0.getX() / 4, new Color(0, 0, 0).getRGB());
                panel.repaint();
            }

            @Override
            public void mouseMoved(MouseEvent arg0) { }

        });

        panel.setPreferredSize(new Dimension(200, 200));

        frame.add(panel);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        panel.repaint();
    }

    public static void main(String[] args) {
        new JPanelPaint();
    }
}

You don't need the mouse listeners if you extend JPanel. 如果扩展JPanel,则不需要鼠标侦听器。 Just enable mouse events then override the component's mouse event handlers. 只需启用鼠标事件,然后覆盖组件的鼠标事件处理程序。 The general logic is: 一般逻辑是:

if mouse pressed {
    dragging = true 
    begin drag
}

if mouse dragged and dragging == true {
    process drag
}

if mouse released and dragging == true {
    dragging = false
    finalize drag
}

Here is an example: 这是一个例子:

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class DragTest {

    // example JPanel. click and drag on it to create lines.
    static class DragPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        static class Line {
            int x1, y1, x2, y2;
        }

        private final List<Line> lines = new ArrayList<Line>();
        private Line draggedLine; // null if not dragging

        public DragPanel() {

            // enable mouse event processing even if no listeners are registered
            enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);

        }

        @Override
        public void paintComponent(Graphics g) {

            super.paintComponent(g);
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, getWidth(), getHeight());
            // draw saved lines
            g.setColor(Color.WHITE);
            for (Line line : lines)
                g.drawLine(line.x1, line.y1, line.x2, line.y2);
            // draw currently active line if there is one
            if (draggedLine != null) {
                g.setColor(Color.RED);
                g.drawLine(draggedLine.x1, draggedLine.y1, draggedLine.x2, draggedLine.y2);
            }

        }

        // does the work; since motion and press/release are all MouseEvent,
        // we can just direct MouseEvents here from the event handler overrides
        // and handle based on event ID.
        private void handleMouseEvent(MouseEvent e) {

            if (e.getID() == MouseEvent.MOUSE_PRESSED && e.getButton() == MouseEvent.BUTTON1) {
                // begin drag by initializing a new Line at mouse position
                if (draggedLine == null) {
                    draggedLine = new Line();
                    draggedLine.x1 = draggedLine.x2 = e.getX();
                    draggedLine.y1 = draggedLine.y2 = e.getY();
                    e.consume();
                }
            } else if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
                // if drag in progress, update line endpoint
                if (draggedLine != null) {
                    draggedLine.x2 = e.getX();
                    draggedLine.y2 = e.getY();
                    e.consume();
                }
            } else if (e.getID() == MouseEvent.MOUSE_RELEASED && e.getButton() == MouseEvent.BUTTON1) {
                // if drag in progress, accept new line and end drag
                if (draggedLine != null) {
                    draggedLine.x2 = e.getX();
                    draggedLine.y2 = e.getY();
                    lines.add(draggedLine);
                    draggedLine = null;
                    e.consume();
                }
            }

            if (e.isConsumed())
                repaint();

        }

        @Override
        public void processMouseMotionEvent(MouseEvent e) {
            handleMouseEvent(e); // pass to our handler, may consume event
            super.processMouseMotionEvent(e); // in case there are registered listeners
        }

        @Override
        public void processMouseEvent(MouseEvent e) {
            handleMouseEvent(e); // pass to our handler, may consume event
            super.processMouseEvent(e); // in case there are registered listeners
        }

    }

    public static final void main(String[] args) {

        JFrame frame = new JFrame("Panel Drag Example");
        frame.getContentPane().add(new DragPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(640, 480);
        frame.setVisible(true);

    }

}

Extending JPanel is usually a better idea than adding listeners with inline classes because it gives you a fully self-contained reusable component. 扩展JPanel通常比添加内联类的侦听器更好,因为它为您提供了一个完全独立的可重用组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM