`
fancy888
  • 浏览: 39770 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

JAVA2D学习 绘制可拖拽选择框

awt 
阅读更多

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

  • 拖动鼠标用虚线调整矩形选择区域的大小
  • 松开鼠标完成选择,更改矩形选择区域边线样式,绘制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() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (selecting || activeHandle >= 0) {
					wipeSelection();
					confirmSelection(selection);
					selecting = false;
					activeHandle = -1;
					setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
				}
			}

			@Override
			public 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

 

分享到:
评论
5 楼 fancy888 2010-03-25  
ionlywantto 写道
不能直接运行,不能看效果
能不能发个直接运行的Jar包(含源码)

随便建个窗口,直接在JPanel上放个SelectableCanvas就可以看效果了。
4 楼 ionlywantto 2010-03-23  
ionlywantto@126.com
我的邮箱
希望多向你学习
3 楼 ionlywantto 2010-03-23  
不能直接运行,不能看效果
能不能发个直接运行的Jar包(含源码)
2 楼 lcywjvb 2010-03-22  
mark!
1 楼 wocsok 2010-03-19  
呵呵不错  从你这个上面 学到很多东西 。。。谢谢。

相关推荐

    qt 绘图工具 实例 C++ 2D 图形绘制 编辑

    本实例是关于使用QT进行C++ 2D图形绘制的工程实践,特别强调了图形的可编辑性,这对于创建绘图软件或需要动态修改图形的应用来说至关重要。 在QT中,QGraphicsView和QGraphicsScene是进行2D图形绘制的核心组件。...

    QT 矩形框绘制 源代码

    本示例专注于使用QT库创建一个功能,允许用户通过鼠标绘制矩形框,并且能够拖动这些矩形,同时还可以通过键盘进行交互控制。这涉及到QT的信号与槽机制、事件处理以及图形视图框架。 首先,QT提供了一个强大的图形...

    java实现拓扑图插件 - 1(已亲测)

    2. **图形绘制**:使用Java的Graphics2D API来绘制节点和边。需要考虑布局算法,以确保节点在屏幕上合理分布,可以使用诸如Spring Layout或Force-Directed Layout等算法。 3. **交互性**:添加鼠标事件监听器,使...

    用draw2d画uml图源码实例

    在UML图的绘制中,Draw2D主要负责绘制类的矩形框、接口的虚线框、关联线等基本元素。 2. **GEF(Graphical Editing Framework)**:GEF为开发者提供了一个框架,用于构建图形编辑器,特别适合用于创建基于模型的...

    java源码:Java 绘图框架 JGraphEd.rar

    在Java中,Graphics2D类是用于进行二维图形绘制的核心接口,它扩展了Graphics类,提供了更多的高级特性,如抗锯齿、颜色空间转换和几何形状的精确绘制。通过Graphics2D,开发者可以绘制直线、曲线、圆形、矩形等基本...

    Java绘图板源码 画图源代码 Swing

    在绘图操作上,开发者可能会使用Graphics2D类,它是Java 2D API的一部分,提供了强大的图形绘制能力。例如,通过Graphics2D对象的drawLine(), drawCircle(), drawOval(), drawRect(), drawPolygon()等方法,可以轻松...

    vtk画矩形,可以随意拖动和缩放。

    vtk中的例子TestvtkAffineWidget 可以画矩形和圆,但是矩形和圆都不能移动和缩放,本内容改造了vtkAffineRepresentation2D , 使矩形和圆都可以放大和缩小。也可以移动,满足了测量的需求,可以用它来对选择的感兴趣...

    利用ISISDraw绘制2D化学结构.ppt

    你可以围绕目标分子点击鼠标,形成一个选择框,然后通过“编辑”菜单中的“复制”和“粘贴”选项来复制结构。移动复制的分子至空白区域,即可完成复制品的放置。 调整结构大小时,需先选中分子,然后拖动其角点来...

    java绘图程序(CAD)3

    同时,可能会利用选区(选框)的概念,通过拖动一个矩形框来选择多个图形对象。 文件名“proCAD”可能代表程序的主文件或者项目文件,这通常包含程序的主要逻辑和用户数据。在Java中,可以使用面向对象的设计模式来...

    Java画图源代码

    此外,颜色选择、字体设置、图形透明度等也是图形绘制中常见的需求,都可以通过Java的API来实现。 总结起来,"Java画图源代码"这个主题涵盖了一系列的图形绘制技术,包括基础的图形组件使用、自定义图形绘制、数据...

    c# 绘制3D可旋转旋转矩形

    在C#编程中,利用GDI+库进行3D图形绘制是一种常见的技术。GDI+是.NET Framework的一部分,提供了一套强大的2D图形处理能力,虽然它不是专门用于3D图形,但通过一些技巧和算法,可以实现简单的3D效果。本教程将深入...

    Java写的绘图工具源代码

    通过分析这个Java写的绘图工具源代码,我们可以学习如何在Java环境中构建图形用户界面,掌握图形绘制的基本技巧,以及如何实现用户交互。这不仅有助于提升编程技能,也能为开发更复杂的图形应用打下坚实的基础。

    java编写绘图软件的过程(带程序和代码)

    Java的File和FileInputStream/FileOutputStream类可用于读写文件,而序列化(Serializable)接口则可以帮助我们将图形对象保存到磁盘,之后再重新加载。 总结来说,开发一个Java绘图软件涵盖了以下几个关键点: 1....

    Java语言实现鼠标拖动旋转立方体

    2. **Java 3D**: 要绘制三维对象,如立方体,Java 3D API是一个不错的选择。它是Java的一个扩展,提供了丰富的3D图形功能,包括对象建模、渲染、动画和交互。 3. **鼠标监听器**: 鼠标事件监听是实现拖动旋转的基础...

    Java实现图片的拖拉变形放大缩小.rar

    在Java编程语言中,图像处理是一项常见的任务,特别是在开发图形用户界面(GUI)应用程序时。本项目关注的是如何实现图片的拖动、变形以及...理解这些基本概念和方法对于深入学习Java图形处理和GUI编程是非常有益的。

    cocoa2D学习

    通过学习cocoa2D及其相关技术,开发者不仅能够提高自身的技术水平,还能创造出更多富有创意和趣味性的游戏作品。希望本文档能够帮助大家更好地理解和掌握cocoa2D的相关知识,为未来的游戏开发之路打下坚实的基础。

    基于Java的实例源码-绘图框架 JGraphEd.zip

    2. **图形表示与交互**:学习如何使用Java图形API(如Graphics2D)来绘制自定义图形,并实现图形的选中、拖放和缩放等功能。 3. **图模型**:理解图的概念,包括节点、边和它们之间的关系,以及如何用数据结构(如...

    Java实现画图工具

    在Java编程语言中实现一个画图工具是一项有趣的挑战,它涉及到图形用户界面(GUI)的构建、事件处理以及图形绘制。下面将详细讲解这个过程涉及的关键知识点。 首先,我们需要使用Java的Swing或JavaFX库来创建GUI。...

    2D drawing software using VC

    如果用户选择绘制圆形或椭圆形,我们可以捕捉鼠标拖动的起点和终点来计算半径或边界。 7. **撤销/重做功能**:为了提高用户体验,我们可以实现撤销和重做功能。这需要记录每一步的绘图操作,并在需要时回滚或重播...

    java写的截屏程序

    然而,实际的截屏程序可能还需要添加更多功能,比如选择特定区域截屏、定时截屏、拖动截取等。这些可以通过监听鼠标事件、绘制矩形框等技术实现。 在Java Swing中,可以使用`JOptionPane`来显示一个对话框,让用户...

Global site tag (gtag.js) - Google Analytics