Swing 自定义控件学习笔记

原创 2015年07月08日 00:07:09

做一个用Swing开发的小工具,需要用到一个可拉伸的矩形控件,学习了下极客学院的自定义控件的视频教程记录一下~^_^

自定义控件主要实现Jcomponent中的4个方法来绘制控件:

  • paintComponent(Graphics)  绘制组件自身
  • paintBorder(Graphics)  绘制组件border边框
  • paintChildren(Graphics) 绘制该控件内部的子控件
  • paint(Graphics) 依次调用上面的函数来进行绘制
调用的次序依次是paintComponent、paintBorder、paintChildren方法,其中Graphics对象进行具体的绘制,可以强转为Graphics2D获得更多的绘图API,如消除锯齿等。

实现可拉伸的矩形框参考 http://blog.csdn.net/fancy888/article/details/7740958

主要实现:

  • 绘制矩形并绘制8个用来调整大小的手柄
  • 拖动手柄可以调整矩形框的大小
  • 在矩形框内部可以拖动整个矩形框的位置

一共两个类

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

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;
	}

}

RectBound :自定义的矩形边框控件

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;

public class RectBoundS extends JPanel implements MouseInputListener {

	private static final long serialVersionUID = -8362626432551491341L;
	boolean selecting;
	int x, y; // 鼠标点击坐标
	int rbx, rby; // jpanel原点坐标

	PointRectangle rectBound = null;// 当前绘制的矩形框
	Rectangle[] handles = new Rectangle[8];// 8个Resize手柄

	int activeHandle = -1; // 激活的Resize手柄

	public RectBoundS() {
		// 添加鼠标事件监听
		addMouseListener(this);
		addMouseMotionListener(this);
	}

	public RectBoundS(Rectangle rec) {
		rectBound = new PointRectangle(rec);
		// 添加鼠标事件监听
		addMouseListener(this);
		addMouseMotionListener(this);
	}

	// 返回当前有效的矩形
	public Rectangle getSelection() {
		return rectBound;
	}

	// 清除选择的矩形
	public void clearSelection() {
		rectBound = null;
		selecting = false;
		activeHandle = -1;
		for (int i = 0; i < handles.length; i++) {
			handles[i] = null;
		}
	}

	@Override
	protected void paintComponent(Graphics g) {
<p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Monaco;"><span style="color: #931a68"><span style="white-space:pre">		</span>  super</span>.paintComponent(<span style="color: #7e504f">g</span>); //必须先执行下父类的该方法</p>
		if (rectBound == null)
			rectBound = new PointRectangle(new Rectangle(getX(), getY(),
					getWidth() / 2, getHeight() / 2));
		Graphics2D graphics = (Graphics2D) g;

		if (rectBound.isEmpty()) {
			clearSelection();
			return;
		}

		graphics.setStroke(new BasicStroke(1));// 设置选择框底色笔触
		graphics.setPaint(Color.BLUE);// 设置边框底色颜色
		graphics.draw(rectBound);// 绘制选择边框底色
		graphics.setPaint(Color.WHITE);// 设置边框颜色
		graphics.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
				BasicStroke.JOIN_ROUND, 1f, new float[] { 5 }, 0));// 设置边框笔触
		graphics.draw(rectBound);// 绘制选择边框
		// 定义手柄
		handles[0] = new Rectangle(rectBound.x - 2, rectBound.y - 2, 4, 4);
		handles[1] = new Rectangle(rectBound.x + rectBound.width / 2 - 2,
				rectBound.y - 2, 4, 4);
		handles[2] = new Rectangle(rectBound.x + rectBound.width - 2,
				rectBound.y - 2, 4, 4);
		handles[3] = new Rectangle(rectBound.x + rectBound.width - 2,
				rectBound.y + rectBound.height / 2 - 2, 4, 4);
		handles[4] = new Rectangle(rectBound.x + rectBound.width - 2,
				rectBound.y + rectBound.height - 2, 4, 4);
		handles[5] = new Rectangle(rectBound.x + rectBound.width / 2 - 2,
				rectBound.y + rectBound.height - 2, 4, 4);
		handles[6] = new Rectangle(rectBound.x - 2, rectBound.y
				+ rectBound.height - 2, 4, 4);
		handles[7] = new Rectangle(rectBound.x - 2, rectBound.y
				+ rectBound.height / 2 - 2, 4, 4);
		graphics.setComposite(AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 1f));// 设置填充不透明
		graphics.setPaint(Color.YELLOW);// 设置手柄填充颜色
		// 填充手柄
		for (Rectangle handle : handles)
			graphics.fill(handle);
		graphics.setPaint(Color.BLACK);// 设置手柄边框颜色
		graphics.setStroke(new BasicStroke(1f));// 设置实线笔触
		// 绘制手柄边框
		for (Rectangle handle : handles)
			graphics.draw(handle);

	}

	@Override
	public void mousePressed(MouseEvent e) {
		x = e.getX();
		y = e.getY();
		rbx = (int) rectBound.getX();
		rby = (int) rectBound.getY();
	}

	@Override
	public void mouseReleased(MouseEvent e) {

		if (selecting || activeHandle >= 0) {

			repaint();
			selecting = false;
			activeHandle = -1;
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			System.out.println("左上角坐标(" + rectBound.x1 + "," + rectBound.y1
					+ "), 右下角坐标(" + rectBound.x2 + "," + rectBound.y2 + ")");
		}

	}

	@Override
	public void mouseEntered(MouseEvent e) {

	}

	@Override
	public void mouseExited(MouseEvent e) {

	}

	@Override
	public void mouseDragged(MouseEvent e) {

		if (activeHandle >= 0) {
			switch (activeHandle) {
			case 0:
				rectBound = new PointRectangle(e.getX(), e.getY(),
						rectBound.x2, rectBound.y2);
				break;
			case 1:
				rectBound = new PointRectangle(rectBound.x1, e.getY(),
						rectBound.x2, rectBound.y2);
				break;
			case 2:
				rectBound = new PointRectangle(rectBound.x1, e.getY(),
						e.getX(), rectBound.y2);
				break;
			case 3:
				rectBound = new PointRectangle(rectBound.x1, rectBound.y1,
						e.getX(), rectBound.y2);
				break;
			case 4:
				rectBound = new PointRectangle(rectBound.x1, rectBound.y1,
						e.getX(), e.getY());
				break;
			case 5:
				rectBound = new PointRectangle(rectBound.x1, rectBound.y1,
						rectBound.x2, e.getY());
				break;
			case 6:
				rectBound = new PointRectangle(e.getX(), rectBound.y1,
						rectBound.x2, e.getY());
				break;
			case 7:
				rectBound = new PointRectangle(e.getX(), rectBound.y1,
						rectBound.x2, rectBound.y2);
				break;
			}
			repaint();
		} else if (null != rectBound && rectBound.contains(e.getX(), e.getY())) {
			rectBound.setLocation(rbx + e.getX() - x, rby + e.getY() - y);
			rectBound.x1 = (int) rectBound.getX();
			rectBound.y1 = (int) rectBound.getY();
			rectBound.x2 = (int) (rectBound.getX() + rectBound.getWidth());
			rectBound.y2 = (int) (rectBound.getY() + rectBound.getHeight());
			System.out.println("左上角坐标(" + rectBound.getX() + ","
					+ rectBound.getY() + "), 右下角坐标("
					+ (rectBound.getX() + rectBound.getWidth()) + ","
					+ (rectBound.getY() + rectBound.getHeight()) + ")");
			repaint();
			setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));

		} else {
			//
		}

	}

	@Override
	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;
			}
		}

		if (rectBound.contains(e.getX(), e.getY())) {
			activeHandle = -1;
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		} else {
			activeHandle = -1;
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		}
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub

	}

}



版权声明:本文为博主原创文章,未经博主允许不得转载。

Swing 实现简单的自定义不规则按钮组件2

使用之前介绍的方式再次尝试定制一个简单的组件,使用Java2d 中的RadialGradientPaint类,自己实现了一个简单的椭圆形状的自定义按钮,按钮颜色实现放射状渐变的效果。 特点:椭圆形状按...
  • sunsnowad
  • sunsnowad
  • 2009年07月30日 12:30
  • 2560

Swing各个组件学习

学习swing组件,主要有三个内容  一是组件的显示,二是对组件支持的事件进行侦听,三是是自定义组件  1.JFrame  JFrame是主窗口,它和JDialog,JApplet的地位并列.但...
  • bj_scholar
  • bj_scholar
  • 2013年01月10日 16:58
  • 957

如何给Swing里组件自定义边框

 其实很简单,只要从一个Border类中继承,然后重写其paintBorder方法就好了。像下面的代码所产生的就是一个三面有线一面没线的边框。class MyBorder extends LineBo...
  • zcsunt
  • zcsunt
  • 2007年07月25日 12:19
  • 962

java swing 自定义UI的实现方式的几个资源

java中MVC与LookAndFeel类及自创界面 http://wenku.baidu.com/view/7f5d920ef12d2af90242e6a6.htmlJButton大改造http:/...
  • zhuxiufenghust
  • zhuxiufenghust
  • 2011年03月18日 09:21
  • 2971

用Java Swing实现的自定义日历组件

主要是用JTextField、JComboBox、JDialog等组件组合而成的日历组件,先贴下效果图。 程序并不复杂,主要是点击了文本框旁边的按钮后会弹出一个没有标题栏的对话框,用以装载日...
  • Greentea107
  • Greentea107
  • 2013年06月08日 15:01
  • 3318

自定义控件其实很简单一

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 自定义View,很多初学Andro...
  • sun20209527
  • sun20209527
  • 2015年11月05日 15:31
  • 1420

Swing自定义按钮

  • 2009年07月22日 19:52
  • 39KB
  • 下载

使用Javaswing自定义图片作为按钮(原创)

主要实现Javaswing中自定义图片作为按钮,仅可以实现此功能。暂未知晓如何修改按钮大小,如果有什么疑问或者建议麻烦提出,谢谢!...
  • u013238347
  • u013238347
  • 2015年05月28日 17:37
  • 2786

关于JTable单元格自定义控件的简单示例

不想多说什么相关的知识,我说不清也不想抄书,如果想明明白白的知道的话可以去翻书,只是现在Swing的相关的教程实在不多,我也是只是略懂些皮毛,为了便于以后自己翻阅便动手写了一个简单的程序,先看截图 J...
  • Greentea107
  • Greentea107
  • 2010年11月17日 21:27
  • 3154

java swing最简单实例(2) 往JFrame里面放一个容器或组件

可以往JFrame里面放的东西有两种,Containers和Components.介绍了如果添加一个容器或组件...
  • shirenfeigui
  • shirenfeigui
  • 2014年08月26日 15:28
  • 11767
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Swing 自定义控件学习笔记
举报原因:
原因补充:

(最多只允许输入30个字)