我正在编写一个程序,允许用户创建房间的平面图 - 这意味着他们可以绘制线条来代表墙壁等。我正在使用带有Graphics 2D的JPanel来完成所有绘图工作,目前我有一个网格设置作为JPanel的背景,我可以根据鼠标移动绘制线条(我有一个枚举鼠标状态有两种状态 - DRAGGING和IDLE)。但是我想在线上添加控制点,这样一旦它们被绘制就可以在JPanel周围移动它们,我无法弄清楚如何做到这一点。我知道我需要矩形来表示点,但我不知道如何将它们链接到线上,这样如果移动点,线也会移动。我很感激任何帮助。
以下是JPanel类的代码:
package floorplan;
/**
*
* @author xodkx
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.event.MouseListener;
public class Floor extends JPanel implements MouseListener, MouseMotionListener
{
private static final int WIDTH = Integer.parseInt(JOptionPane.showInputDialog("Please
enter the width of your room"));
private static final int LENGTH = Integer.parseInt(JOptionPane.showInputDialog("Please
enter the width of your room"));
private static final Color BACKGROUND = Color.WHITE;
private static final Color INITIAL_COLOUR = Color.BLACK;
private static final Framework INITIAL_FRAMEWORK = Framework.WALL;
private MouseState state = MouseState.IDLE;
private Framework frameworkType = INITIAL_FRAMEWORK;
private Color colour = INITIAL_COLOUR;
private Point start = null;
private Point end = null;
private Rectangle startpt = new Rectangle(0, 0, 8, 8);// Start control point
private Rectangle endpt = new Rectangle(0, 0, 8, 8);// End control point
private BufferedImage bufImage = null;
public Floor()
{
setPreferredSize(new Dimension(LENGTH,WIDTH));
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder (Color.black, 5));
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void setColor(Color color)
{
colour = color;
}
public void setFramework(Framework framework)
{
frameworkType = framework;
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if(bufImage == null)
{
int h = this.getHeight();
int w = this.getWidth();
bufImage = (BufferedImage)this.createImage(h,w);
Graphics2D gc = bufImage.createGraphics();
gc.setColor(BACKGROUND);
gc.fillRect(0, 0, w, h);
}
g2.drawImage(bufImage,null,0,0);
drawGrid(g2);
if(state == MouseState.DRAGGING)
{
createComponent(g2);
}
}
public void drawGrid(Graphics g2)// sets a grid as the background of the JPanel
{
int gridDivisions = 20;
int divisionSize = WIDTH/gridDivisions;
int grid = WIDTH*LENGTH;
g2.setColor(Color.lightGray);
for(int i=1; i<grid; i++)
{
int x = i * divisionSize;
g2.drawLine(x,0,x,getSize().height);
}
for(int i=1; i<grid; i++)
{
int y = i*divisionSize;
g2.drawLine(0,y,getSize().width,y);
}
}
public void createComponent(Graphics2D g2)// method that draws the lines for various
components of the room
{
g2.setColor(colour);
switch (frameworkType)
{
case WALL:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
case DOOR:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
case WINDOW:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
default:
g2.drawString("test", 10, 20);
break;
}
}
@Override
public void mousePressed(MouseEvent e)
{
state = MouseState.DRAGGING;
start = e.getPoint();
end = start;
}
@Override
public void mouseDragged(MouseEvent e)
{
state = MouseState.DRAGGING;
end = e.getPoint();
this.repaint();
}
@Override
public void mouseReleased(MouseEvent e)
{
end = e.getPoint();
if(state == MouseState.DRAGGING)
{
state = MouseState.IDLE;
createComponent(bufImage.createGraphics());
this.repaint();
}
}
@Override
public void mouseClicked(MouseEvent e)
{
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
@Override
public void mouseMoved(MouseEvent e)
{
}
}
答案 0 :(得分:11)
为什么不创建控制点的ArrayList,或者更好的是,Ellipse2D对象以控制点为中心?然后,您可以测试是否在椭圆中按下鼠标以确定其行为应该是什么,并且您可以使用List of Ellipse2D对象在使用paintComponent(...)
方法绘制时获取行结束点。
请注意,您的代码不会为我们编译或运行,因此我们很难对其进行全面分析,测试和修改。要获得更具体的帮助,请考虑将代码压缩到仍然编译,运行并能够重现问题的最小代码sscce。
例如:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class Floor2 extends JPanel {
private static final Color BACKGROUND = new Color(0, 0, 0, 0);
private static final Color INITIAL_COLOUR = Color.BLACK;
private static final int BORDER_WIDTH = 5;
private static final Color LINE_DRAWING_COLOR = new Color(200, 200, 255);
private static final Color LINE_COLOR = Color.blue;
private static final Stroke DRAWING_LINE_STROKE = new BasicStroke((float)BORDER_WIDTH);
public static final int ELLIPSE_DIAMETER = 10;
private MouseState mouseState = MouseState.IDLE;
private BufferedImage bufImage = null;
private int width;
private int height;
private int gridDivisions;
private List<List<Ellipse2D>> ellipseList = new ArrayList<List<Ellipse2D>>();
private Line2D drawingLine = null;
public enum MouseState {
IDLE, DRAGGING
}
public Floor2(int width, int height, int gridDivisions) {
this.width = width;
this.height = height;
this.gridDivisions = gridDivisions;
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder(Color.black, BORDER_WIDTH));
MyMouseAdapter mouseAdapter = new MyMouseAdapter();
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
private static void createAndShowGui() {
int w = 600;
int h = w;
int gridDiv = 20;
Floor2 mainPanel = new Floor2(w, h, gridDiv);
JFrame frame = new JFrame("Floor2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bufImage == null) {
bufImage = createGridImage();
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Stroke initStroke = g2.getStroke();
g2.setStroke(DRAWING_LINE_STROKE);
if (mouseState == MouseState.DRAGGING && drawingLine != null) {
g2.setColor(LINE_DRAWING_COLOR);
g2.draw(drawingLine);
}
g2.setColor(LINE_COLOR);
for (List<Ellipse2D> ellipses : ellipseList) {
Point2D p2d1 = new Point2D.Double(ellipses.get(0).getCenterX(), ellipses.get(0).getCenterY());
Point2D p2d2 = new Point2D.Double(ellipses.get(1).getCenterX(), ellipses.get(1).getCenterY());
Line2D line = new Line2D.Double(p2d1, p2d2);
g2.draw(line);
}
g.drawImage(bufImage, 0, 0, this);
g2.setStroke(initStroke);
}
private BufferedImage createGridImage() {
BufferedImage gridImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = gridImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setBackground(BACKGROUND);
g2.clearRect(0, 0, width, height);
int divisionSize = width / gridDivisions;
int grid = width * height;
g2.setColor(Color.lightGray);
for (int i = 1; i < grid; i++) {
int x = i * divisionSize;
g2.drawLine(x, 0, x, getSize().height);
}
for (int i = 1; i < grid; i++) {
int y = i * divisionSize;
g2.drawLine(0, y, getSize().width, y);
}
g2.dispose();
return gridImage;
}
private class MyMouseAdapter extends MouseAdapter {
private Point p1;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (List<Ellipse2D> endPts : ellipseList) {
// check if one of the ellipses has been selected
// if so, remove it from elipseList
// set drawingLine == to end points
// setdragging = true
// repaint
// return
}
mouseState = MouseState.DRAGGING;
p1 = e.getPoint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (mouseState != MouseState.DRAGGING) {
return;
}
drawingLine = new Line2D.Double(p1, e.getPoint());
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
if (drawingLine != null) {
List<Ellipse2D> newEndPoints = new ArrayList<Ellipse2D>();
double x1 = drawingLine.getX1() - ELLIPSE_DIAMETER / 2;
double y1 = drawingLine.getY1() - ELLIPSE_DIAMETER / 2;
Ellipse2D ellipse1 = new Ellipse2D.Double(x1, y1, ELLIPSE_DIAMETER, ELLIPSE_DIAMETER);
x1 = drawingLine.getX2() - ELLIPSE_DIAMETER / 2;
y1 = drawingLine.getY2() - ELLIPSE_DIAMETER / 2;
Ellipse2D ellipse2 = new Ellipse2D.Double(x1, y1, ELLIPSE_DIAMETER, ELLIPSE_DIAMETER);
newEndPoints.add(ellipse1);
newEndPoints.add(ellipse2);
ellipseList.add(newEndPoints);
repaint();
}
mouseState = MouseState.IDLE;
drawingLine = null;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
编辑:mousePressed方法更改:
private class MyMouseAdapter extends MouseAdapter {
private Point2D p1;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (List<Ellipse2D> endPts : ellipseList) {
for (int i = 0; i < endPts.size(); i++) {
Ellipse2D endPt = endPts.get(i);
if (endPt.contains(e.getPoint())) {
Ellipse2D endPt2 = endPts.get(Math.abs(i - 1));
ellipseList.remove(endPts);
Point2D p2 = new Point2D.Double(endPt.getCenterX(), endPt.getCenterY());
p1 = new Point2D.Double(endPt2.getCenterX(), endPt2.getCenterY());
drawingLine = new Line2D.Double(p1, p2);
mouseState = MouseState.DRAGGING;
repaint();
return;
}
}
}
mouseState = MouseState.DRAGGING;
p1 = e.getPoint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (mouseState != MouseState.DRAGGING) {
return;
}
drawingLine = new Line2D.Double(p1, e.getPoint());
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
if (drawingLine != null) {
List<Ellipse2D> newEndPoints = new ArrayList<Ellipse2D>();
double x1 = drawingLine.getX1() - ELLIPSE_DIAMETER / 2;
double y1 = drawingLine.getY1() - ELLIPSE_DIAMETER / 2;
Ellipse2D ellipse1 = new Ellipse2D.Double(x1, y1, ELLIPSE_DIAMETER, ELLIPSE_DIAMETER);
x1 = drawingLine.getX2() - ELLIPSE_DIAMETER / 2;
y1 = drawingLine.getY2() - ELLIPSE_DIAMETER / 2;
Ellipse2D ellipse2 = new Ellipse2D.Double(x1, y1, ELLIPSE_DIAMETER, ELLIPSE_DIAMETER);
newEndPoints.add(ellipse1);
newEndPoints.add(ellipse2);
ellipseList.add(newEndPoints);
repaint();
}
mouseState = MouseState.IDLE;
drawingLine = null;
}
}