JAVA2D学习:绘制可拖拽选择框

来源:互联网 发布:java 迭代器的实现 编辑:程序博客网 时间:2024/05/22 09:35

       弄了一天,基本实现了一般绘图软件的绘制矩形选择框的功能。

  • 拖动鼠标用虚线调整矩形选择区域的大小
  • 松开鼠标完成选择,更改矩形选择区域边线样式,绘制8个用来调整大小的手柄
  • 用鼠标拖动手柄可重新调整矩形的大小

     一共两个类:

    PointRectangle


    扩展了AWT的Rectangle类,按左上角和右下角两个坐标点来定义矩形(AWT默认是按左上角坐标和长宽来定义矩形的)。

    SelectableCanvas

   扩展了AWT的Canvas,用来充当画板。

    考虑到可能有底图存在,这里没用到Double Buffering,每次画图前先按像素级精确擦除前一祯绘制的矩形的手柄,实际效果很理想,基本看不到闪烁。

package com.fancy.picture.test;import java.awt.Rectangle;public class PointRectangle extends Rectangle {private static final long serialVersionUID = -2465363144347743255L;int x1, x2, y1, y2;public PointRectangle(int x1, int y1, int x2, int y2) {this.x1 = x = x1;this.x2 = x2;this.y1 = y = y1;this.y2 = y2;width = x2 - x1;height = y2 - y1;if (x2 < x1) {x = x2;width = x1 - x2;}if (y2 < y1) {y = y2;height = y1 - y2;}}public PointRectangle(Rectangle rectangle) {super(rectangle.x, rectangle.y, rectangle.width, rectangle.height);this.x1 = rectangle.x;this.y1 = rectangle.y;this.x2 = rectangle.x + rectangle.width;this.y2 = rectangle.y + rectangle.height;}} package com.fancy.picture.test;import java.awt.AlphaComposite;import java.awt.BasicStroke;import java.awt.Canvas;import java.awt.Color;import java.awt.Cursor;import java.awt.Graphics2D;import java.awt.Rectangle;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseMotionAdapter;import java.awt.geom.Area;public class SelectableCanvas extends Canvas {private static final long serialVersionUID = -7159915510292362753L;boolean selecting;// 是否正在拖拽矩形int x, y;// 矩形原点坐标PointRectangle selection;// 当前绘制的矩形int activeHandle = -1;// 激活的Resize手柄Rectangle[] handles = new Rectangle[8];// 8个Resize手柄public SelectableCanvas() {addMouseListener(new MouseAdapter() {@Overridepublic void mouseReleased(MouseEvent e) {if (selecting || activeHandle >= 0) {wipeSelection();confirmSelection(selection);selecting = false;activeHandle = -1;setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));}}@Overridepublic void mousePressed(MouseEvent e) {x = e.getX();y = e.getY();}});addMouseMotionListener(new MouseMotionAdapter() {public void mouseMoved(MouseEvent e) {for (int i = 0; i < handles.length; i++) {if (handles[i] != null && handles[i].contains(e.getX(), e.getY())) {activeHandle = i;switch (i) {case 0:case 4:setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));break;case 1:case 5:setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));break;case 2:case 6:setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));break;case 3:case 7:setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));break;}return;}}activeHandle = -1;setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));}public void mouseDragged(MouseEvent e) {if (selection != null)wipeSelection();if (activeHandle >= 0) {switch (activeHandle) {case 0:selection = new PointRectangle(e.getX(), e.getY(), selection.x2, selection.y2);break;case 1:selection = new PointRectangle(selection.x1, e.getY(), selection.x2, selection.y2);break;case 2:selection = new PointRectangle(selection.x1, e.getY(), e.getX(), selection.y2);break;case 3:selection = new PointRectangle(selection.x1, selection.y1, e.getX(), selection.y2);break;case 4:selection = new PointRectangle(selection.x1, selection.y1, e.getX(), e.getY());break;case 5:selection = new PointRectangle(selection.x1, selection.y1, selection.x2, e.getY());break;case 6:selection = new PointRectangle(e.getX(), selection.y1, selection.x2, e.getY());break;case 7:selection = new PointRectangle(e.getX(), selection.y1, selection.x2, selection.y2);break;}drawSelection(selection);}else {selection = new PointRectangle(x, y, e.getX(), e.getY());drawSelection(selection);selecting = true;setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));}}});}// 清除选择的矩形public void clearSelection() {selection = null;selecting = false;activeHandle = -1;for (int i = 0; i < handles.length; i++)handles[i] = null;}// 清除上次的绘制的矩形private void wipeSelection() {Graphics2D graphics = (Graphics2D) getGraphics().create();// 初始化绘图上下文// 定义擦除区域Area area = new Area(new Rectangle(selection.x, selection.y, selection.width + 1, selection.height + 1));area.subtract(new Area(new Rectangle(selection.x + 1, selection.y + 1, selection.width - 1, selection.height - 1)));area.add(new Area(new Rectangle(selection.x - 2, selection.y - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x + selection.width / 2 - 2, selection.y - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x + selection.width - 2, selection.y - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x + selection.width - 2, selection.y + selection.height / 2 - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x + selection.width - 2, selection.y + selection.height - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x + selection.width / 2 - 2, selection.y + selection.height - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x - 2, selection.y + selection.height - 2, 5, 5)));area.add(new Area(new Rectangle(selection.x - 2, selection.y + selection.height / 2 - 2, 5, 5)));graphics.setClip(area);// 应用擦除区域update(graphics);// 用背景擦除}//画虚线矩形private void drawSelection(Rectangle selection) {Graphics2D graphics = (Graphics2D) getGraphics().create();// 初始化绘图上下文graphics.setPaint(Color.WHITE);// 设置边框颜色graphics.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1f, new float[] { 5 }, 0));// 设置边框笔触graphics.draw(selection);// 绘制选择边框}//画带手柄的矩形private void confirmSelection(Rectangle selection) {this.selection = new PointRectangle(selection);Graphics2D graphics = (Graphics2D) getGraphics();// 绘图上下文if (selection.isEmpty()) {clearSelection();return;}graphics.setStroke(new BasicStroke(1));// 设置选择框底色笔触graphics.setPaint(Color.BLUE);// 设置边框底色颜色graphics.draw(selection);// 绘制选择边框底色graphics.setPaint(Color.WHITE);// 设置边框颜色graphics.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1f, new float[] { 5 }, 0));// 设置边框笔触graphics.draw(selection);// 绘制选择边框// 定义手柄handles[0] = new Rectangle(selection.x - 2, selection.y - 2, 4, 4);handles[1] = new Rectangle(selection.x + selection.width / 2 - 2, selection.y - 2, 4, 4);handles[2] = new Rectangle(selection.x + selection.width - 2, selection.y - 2, 4, 4);handles[3] = new Rectangle(selection.x + selection.width - 2, selection.y + selection.height / 2 - 2, 4, 4);handles[4] = new Rectangle(selection.x + selection.width - 2, selection.y + selection.height - 2, 4, 4);handles[5] = new Rectangle(selection.x + selection.width / 2 - 2, selection.y + selection.height - 2, 4, 4);handles[6] = new Rectangle(selection.x - 2, selection.y + selection.height - 2, 4, 4);handles[7] = new Rectangle(selection.x - 2, selection.y + selection.height / 2 - 2, 4, 4);graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));// 设置填充不透明graphics.setPaint(Color.WHITE);// 设置手柄填充颜色// 填充手柄for (Rectangle handle : handles)graphics.fill(handle);graphics.setPaint(Color.BLACK);// 设置手柄边框颜色graphics.setStroke(new BasicStroke(1f));// 设置实线笔触// 绘制手柄边框for (Rectangle handle : handles)graphics.draw(handle);}//返回当前有效的矩形public Rectangle getSelection() {return selection;}}

   原文: http://www.coolfancy.com/log/32.html


   更多精彩原创文章请关注笔者的原创博客:http://www.coolfancy.com


原创粉丝点击