[英]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.