我在jpanel上绘制线条作为使用图形2D的缓冲图像,我想将点存储为成对,即起点的x和y坐标作为一对,终点的x和y坐标作为另一个对。由于会有几行,我想将所有这些对存储为一个列表(或者可能是2 - 一个用于起点,一个用于终点)并且如果移动线并且点改变并且检查是否能够更新它们给定的点在列表中。我怎么能这样做,这可能吗?
我看过有一个Pair类,但我不知道它是如何工作的,如果我可以有一个Pa列表。此外,我已经看过使用地图和arraylists,但他们似乎都没有我正在寻找的功能(或者我可能只是不知道)。
目前,我只是画线,但没有存储点。这是完成所有绘图的类:
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.FLEXIBLEWALL;
private MouseState state = MouseState.IDLE;
private Framework frameworkType = INITIAL_FRAMEWORK;
private Color colour = INITIAL_COLOUR;
private Point start = null; // START POINT
private Point end = null; // END 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)
{
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)
{
g2.setColor(colour);
switch (frameworkType)
{
case FLEXIBLEWALL:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
case VERTICALWALL:
g2.setStroke(new BasicStroke(5));
end.x = start.x;
g2.drawLine(start.x,start.y,end.x,end.y);
break;
case HORIZONTALWALL:
g2.setStroke(new BasicStroke(5));
end.y = start.y;
g2.drawLine(start.x,start.y,end.x,end.y);
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;
}
}
public void clear()
{
bufImage.flush();
bufImage = null;
repaint();
}
@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();
}
}
public void updateLocation(MouseEvent e)
{
}
@Override
public void mouseClicked(MouseEvent e)
{
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
@Override
public void mouseMoved(MouseEvent e)
{
}
}
使用java.awt.geom.Line2D
。您可以将其放入列表或任何其他集合中。它有equals()
和hashCode()
。
您可以使用需要较少空间的Line2D.Float
作为Line2D.Double
,这在计算中更方便。
如果你有成千上万的这样的线,那么事情会发生变化。然后它变得不那么舒服了。为此,int[]
的内存效率最高,但这是另一个问题。
package util;
public final class Pair<S,T> {
public S first;
public T second;
public Pair(S first, T second) {
super();
this.first = first;
this.second = second;
}
public S getFirst() {
return first;
}
public T getSecond() {
return second;
}
public void setFirst(S first) {
this.first = first;
}
public void setSecond(T second) {
this.second = second;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((first == null) ? 0 : first.hashCode());
result = prime * result + ((second == null) ? 0 : second.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pair<?,?> other = (Pair<?,?>) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (second == null) {
if (other.second != null)
return false;
} else if (!second.equals(other.second))
return false;
return true;
}
@Override
public String toString() {
return "<"+first+","+second+">";
}
}
首先,您可以将所有点存储在一个列表中,因此偶数位置的点将是线段的起点,奇数位置的点将是结束点:
List <Point> points = Arrays.asList (
new Point (100, 100), new Point (200, 100), // First line segment
new Point (200, 100), new Point (200, 200), // Second line segment
new Point (200, 200), new Point (100, 100)); // Third line segment
此外,您可以在列表中存储点阵列,因此每个阵列将表示一条曲线,其中原因曲线可能只包含一个段:
List <Point []> points = Arrays.asList (
new Point [] {new Point (100, 100), new Point (200, 100)}, // First line segment
new Point [] {new Point (200, 100), new Point (200, 200)}, // Second line segment
new Point [] {new Point (200, 200), new Point (200, 100), new Point (100, 100)); // Curve of third and fourth segments
因为你可以声明自己的类来存储两个点,如下所示:
public class TwoPoints
{
public final Point begin;
public final Point end;
public TwoPoints (int x1, int y1, int x2, int y2)
{
this (new Point (x1, y1), new Point (x2, y2));
}
public TwoPoints (Point begin, Point end)
{
this.begin = begin;
this.end = end;
}
}
这个类的对象你肯定可以存储在列表中:
List <TwoPoints> lines = Arrays.asList (
new TwoPoints (100, 100, 100, 200), // First line segment
new TwoPoints (100, 200, 200, 200), // Second line segment
new TwoPoints (200, 200, 100, 100)); // Third line segment