java SWT入门:自定义背景透明且可鼠标拖动改变尺寸和位置的Composite

本文主要是介绍java SWT入门:自定义背景透明且可鼠标拖动改变尺寸和位置的Composite,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下面的代码实现了一个透明可移动可改变尺寸的Composite窗体,如下图
这里写图片描述
鼠标点击窗口获取焦点,在获取焦点时会显示9个锚点用于改变窗口的位置和尺寸。
可以通过鼠标拖动锚点来改变窗口的位置或尺寸,也可以通过上下左右键来移动窗口

ActiveRectangle.java

package net.gdface.ui;import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;/*** 自定义透明窗口,* 窗口位置和尺寸可以通过鼠标和上下左右键修改* @author gudong*/
public class ActiveRectangle extends Composite {/*** 锚点对象* @author guyadong*/private class Anchor {/*** 描述锚点位置尺寸的矩形对象*/final Rectangle rect=new Rectangle(0, 0, anchorSize, anchorSize);/*** 锚点的光标对象*/final Cursor cusor;/*** 锚点位置计算的掩码*/final Rectangle mask;Anchor(Cursor cusor, Rectangle mask) {this.cusor = cusor;this.mask=mask;}}/*** 焦点矩形边框颜色*/private static Color focusRectColor=SWTResourceManager.getColor(SWT.COLOR_GREEN);/*** 非焦点矩形边框颜色*/private static Color nofocusRectColor=SWTResourceManager.getColor(SWT.COLOR_RED);/*** 矩形边框线宽*/private static int lineWidth=1; /*** 锚点矩形尺寸*/private static int anchorSize=8;/*** 上下左右键移动窗口的步长*/private static int arrowStep=1;/*** 是否焦点*/boolean focus=true;/*** 当前鼠标位置所在的锚点索引 {@link #anchors} */private int anchorIndex=-1;// 光标定义private final Cursor CURSOR_SIZENESW=new Cursor(Display.getDefault(),SWT.CURSOR_SIZENESW);private final Cursor CURSOR_SIZENS=new Cursor(Display.getDefault(),SWT.CURSOR_SIZENS);private final Cursor CURSOR_SIZENWSE=new Cursor(Display.getDefault(),SWT.CURSOR_SIZENWSE);private final Cursor CURSOR_SIZEWE=new Cursor(Display.getDefault(),SWT.CURSOR_SIZEWE);private final Cursor CURSOR_SIZEALL=new Cursor(Display.getDefault(),SWT.CURSOR_SIZEALL);    //lt+-------+-------+rt//  |       t       |//  |               |//  |       c       |//l +       +       +r//  |               |//  |               |//  |       b       |//lb+-------+-------+rbenum AnchorType{LT,T,RT,L,C,R,LB,B,RB}/*** 9个锚点位置({@link Anchor})对象数组(按从左到右从上到下顺序排序)*/private final Anchor[] anchors=new Anchor[]{new Anchor(CURSOR_SIZENWSE,new Rectangle(1,1,-1,-1)),new Anchor(CURSOR_SIZENS,new Rectangle(0,1,0,-1)),new Anchor(CURSOR_SIZENESW,new Rectangle(0,1,1,-1)),new Anchor(CURSOR_SIZEWE,new Rectangle(1,0,-1,0)),new Anchor(CURSOR_SIZEALL,new Rectangle(1,1,0,0)),new Anchor(CURSOR_SIZEWE,new Rectangle(0,0,1,0)),new Anchor(CURSOR_SIZENESW,new Rectangle(1,0,-1,1)),new Anchor(CURSOR_SIZENS,new Rectangle(0,0,0,1)),new Anchor(CURSOR_SIZENWSE,new Rectangle(0,0,1,1))};;   /*** 矩形修改标记,为true时,处于鼠标拖动修改窗口位置和尺寸的状态,* 鼠标位于9个锚点区域({@link Anchor})之一,且鼠标键按下(mouseDown)*/private boolean onMouseModfied;/*** 矩形修改状态下({@link #onMouseModfied}为true),记录上次鼠标位置*/private Point lastPos;/*** 真实的窗口位置和尺寸*/protected Rectangle originalBounds;private boolean originalBoundsNeedupdate=false;/*** 父窗口x轴缩放比例*/private float zoomY;/*** 父窗口y轴缩放比例*/private float zoomX;/*** Create the composite.* @param parent* @param isFocus 是否为焦点对象* @param originalBounds 对象原始位置尺寸*/public ActiveRectangle(Composite parent, boolean isFocus, Rectangle originalBounds) {// 透明背景样式super(parent, SWT.TRANSPARENT);this.originalBounds = originalBounds;this.focus=isFocus;     addPaintListener(new PaintListener() {public void paintControl(PaintEvent e) {// 绘制透明矩形窗口e.gc.setLineStyle(SWT.LINE_SOLID);e.gc.setLineWidth(lineWidth);e.gc.setForeground(focus?focusRectColor:nofocusRectColor);Point size = getSize();             e.gc.drawRectangle(new Rectangle(0,0,--size.x,--size.y));if(focus){Color bc = e.gc.getBackground();                    e.gc.setBackground(focusRectColor);e.gc.fillRectangle(anchors[AnchorType.LT.ordinal()].rect.x, anchors[AnchorType.LT.ordinal()].rect.y, anchorSize, anchorSize);e.gc.fillRectangle(anchors[AnchorType.T.ordinal()].rect.x, anchors[AnchorType.T.ordinal()].rect.y, anchorSize, anchorSize);e.gc.fillRectangle(anchors[AnchorType.RT.ordinal()].rect.x, anchors[AnchorType.RT.ordinal()].rect.y, anchorSize, anchorSize);                   e.gc.fillRectangle(anchors[AnchorType.L.ordinal()].rect.x, anchors[AnchorType.L.ordinal()].rect.y, anchorSize, anchorSize);// 画中心十字e.gc.drawLine(anchors[AnchorType.C.ordinal()].rect.x+(anchorSize>>1), anchors[AnchorType.C.ordinal()].rect.y, anchors[AnchorType.C.ordinal()].rect.x+(anchorSize>>1), anchors[AnchorType.C.ordinal()].rect.y+anchorSize);e.gc.drawLine(anchors[AnchorType.C.ordinal()].rect.x, anchors[AnchorType.C.ordinal()].rect.y+(anchorSize>>1), anchors[AnchorType.C.ordinal()].rect.x+anchorSize, anchors[AnchorType.C.ordinal()].rect.y+(anchorSize>>1));e.gc.fillRectangle(anchors[AnchorType.R.ordinal()].rect.x, anchors[AnchorType.R.ordinal()].rect.y, anchorSize, anchorSize);e.gc.fillRectangle(anchors[AnchorType.LB.ordinal()].rect.x, anchors[AnchorType.LB.ordinal()].rect.y, anchorSize, anchorSize);e.gc.fillRectangle(anchors[AnchorType.B.ordinal()].rect.x, anchors[AnchorType.B.ordinal()].rect.y, anchorSize, anchorSize);e.gc.fillRectangle(anchors[AnchorType.RB.ordinal()].rect.x, anchors[AnchorType.RB.ordinal()].rect.y, anchorSize, anchorSize);                   // 恢复背景色e.gc.setBackground(bc);                 }}});// 当获取/失去焦点时重绘窗口addFocusListener(new FocusAdapter() {@Overridepublic void focusGained(FocusEvent e) {focus=true;// 将对象设置到顶层,否则无法响应所有的mouseMove事件moveAbove(null);((Control)(e.widget)).redraw();}@Overridepublic void focusLost(FocusEvent e) {focus=false;((Control)(e.widget)).redraw();}});// 实现上下左右键移动窗口addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch(e.keyCode){case SWT.ARROW_LEFT:modify(-arrowStep,0,anchors[AnchorType.C.ordinal()].mask);break;case SWT.ARROW_RIGHT:modify(arrowStep,0,anchors[AnchorType.C.ordinal()].mask);break;case SWT.ARROW_UP:modify(0,-arrowStep,anchors[AnchorType.C.ordinal()].mask);break;case SWT.ARROW_DOWN:modify(0,arrowStep,anchors[AnchorType.C.ordinal()].mask);break;default:}}});// 加入mouseMove事件处理,实现鼠标拖动锚点改变窗口位置和尺寸addMouseMoveListener(new MouseMoveListener() {private final Cursor defCursor=getCursor();         public void mouseMove(MouseEvent e) {if(focus){if(onMouseModfied){// 计算鼠标移动的距离Point pos=((Control)(e.widget)).toDisplay(e.x, e.y);modify(pos.x-lastPos.x,pos.y-lastPos.y,anchors[anchorIndex].mask);// 记录当前鼠标位置,以供下次mouseMove消息时计算鼠标移动距离lastPos=pos;}else   if((anchorIndex=anchored(e.x, e.y))>=0&&anchors[anchorIndex].cusor!=getCursor()){// 当鼠标位置某个锚点时,更新鼠标形状setCursor(anchors[anchorIndex].cusor);}else   if(defCursor!=getCursor())// 鼠标不在锚点时,恢复默认鼠标形状setCursor(defCursor);}else anchorIndex=-1;}});// 配合MouseMoveListener实现鼠标改变窗口位置和尺寸addMouseListener(new MouseAdapter() {           @Overridepublic void mouseDown(MouseEvent e) {if(anchorIndex>=0){// 记录当前鼠标位置,以供mouseMove消息时计算鼠标移动距离lastPos=((Control)(e.widget)).toDisplay(e.x, e.y);onMouseModfied=true;}else if(!isFocusControl()){// 当前对象非焦点对象时,设置当前对象为焦点对象setFocus();}}@Overridepublic void mouseUp(MouseEvent e) {onMouseModfied=false;}});}@Overrideprotected void checkSubclass() {// Disable the check that prevents subclassing of SWT components}/*** 改变窗口位置和尺寸* @param x x轴移动距离* @param y y轴移动距离* @param mask 锚点位置计算的掩码*/private void modify(int x,int y,Rectangle mask){// 计算出新的窗口位置和尺寸Rectangle bound = getBounds();bound.x+=x*mask.x;bound.y+=y*mask.y;bound.width+=x*mask.width;bound.height+=y*mask.height;// 设置新的窗口位置this.originalBoundsNeedupdate=true;setBounds(bound);this.originalBoundsNeedupdate=false;}@Overridepublic void dispose() {// 释放光标资源CURSOR_SIZENESW.dispose();CURSOR_SIZENS.dispose();CURSOR_SIZENWSE.dispose();CURSOR_SIZEWE.dispose();CURSOR_SIZEALL.dispose();super.dispose();}/*** 根据窗口尺寸计算各个{@link Anchor}的位置*/private void setAnchors(){Point size = getSize();setAnchorPos(anchors[AnchorType.LT.ordinal()].rect,0, 0);setAnchorPos(anchors[AnchorType.T.ordinal()].rect,(size.x-anchorSize)>>1, 0);setAnchorPos(anchors[AnchorType.RT.ordinal()].rect,size.x-anchorSize, 0);setAnchorPos(anchors[AnchorType.L.ordinal()].rect,0, (size.y-anchorSize)>>1);setAnchorPos(anchors[AnchorType.C.ordinal()].rect,(size.x-anchorSize)>>1, (size.y-anchorSize)>>1);setAnchorPos(anchors[AnchorType.R.ordinal()].rect,size.x-anchorSize, (size.y-anchorSize)>>1);setAnchorPos(anchors[AnchorType.LB.ordinal()].rect,0, size.y-anchorSize);setAnchorPos(anchors[AnchorType.B.ordinal()].rect,(size.x-anchorSize)>>1, size.y-anchorSize);setAnchorPos(anchors[AnchorType.RB.ordinal()].rect,size.x-anchorSize, size.y-anchorSize);}private void setAnchorPos(Rectangle anchorRect,int x,int y){anchorRect.x=x;anchorRect.y=y;}/*** 计算指定的坐标(x,y)是否位于某个{@link Anchor}区域* @param x* @param y* @return 返回 {@link #anchors}的索引值,不在任何一个{@link Anchor}则返回-1*/private int anchored(int x,int y){for(int i=0;i<anchors.length;++i){if(anchors[i].rect.contains(x, y))return i;}return -1;}private void setOriginalBounds(Rectangle rect){// 如果originalBounds没有初始化,则用第一次调用setBounds的参数来初始化if(null==originalBounds)originalBounds=rect;else if(originalBoundsNeedupdate)// 非zoom状态下更新将当前窗口的尺寸换算后更新originalBoundsoriginalBounds=unZoom(zoomX,zoomY);}@Overridepublic void setBounds(int x, int y, int width, int height) {super.setBounds(x, y, width, height);// 重写setBounds方法,修改窗口位置和尺寸时同步重新计算所有锚点位置setAnchors();setOriginalBounds(new Rectangle(x, y, width, height));}@Overridepublic void setBounds(Rectangle rect) {super.setBounds(rect);// 重写setBounds方法,修改窗口位置和尺寸时同步重新计算所有锚点位置setAnchors();setOriginalBounds(rect);}/*** 根据zoom缩放比例缩放矩形显示* @param zoomX x轴缩放比例* @param zoomY y轴缩放比例*/protected void zoom(float zoomX, float zoomY) {if(null!=originalBounds){this.zoomX=zoomX;this.zoomY=zoomY;setBounds(new Rectangle((int)(originalBounds.x*zoomX),(int)(originalBounds.y*zoomY),(int)(originalBounds.width*zoomX),(int)(originalBounds.height*zoomY)));}}/*** x,y轴等比例缩放* @param rect* @param zoom x,y轴缩放比例* @see #zoom(float, float)*/void zoom(Rectangle rect, float zoom) {     zoom(zoom,zoom);}/*** 根据zoom缩放比例返回缩放前的矩形对象({@link Rectangle})* @param zoomX x轴缩放比例* @param zoomY y轴缩放比例* @return*/protected Rectangle unZoom(float zoomX, float zoomY) {  Rectangle bounds = getBounds();return new Rectangle((int)(bounds.x/zoomX),(int)(bounds.y/zoomY),(int)(bounds.width/zoomX),(int)(bounds.height/zoomY));     }/*** x,y轴等比例缩放* @param zoom x,y轴缩放比例* @return* @see #unZoom(float, float)*/protected Rectangle unZoom(float zoom) {    return unZoom(zoom,zoom);       }}

测试代码
TestActiveRectangle.java

package testwb;import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;import net.gdface.ui.ActiveRectangle;import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Control;public class TestActiveRectangle extends Dialog {protected Object result;protected Shell shell;/*** Create the dialog.* @param parent* @param style*/public TestActiveRectangle(Shell parent, int style) {super(parent, style);setText("SWT Dialog");}/*** Open the dialog.* @return the result*/public Object open() {createContents();shell.open();shell.layout();Display display = getParent().getDisplay();while (!shell.isDisposed()) {if (!display.readAndDispatch()) {display.sleep();}}return result;}/*** Create contents of the dialog.*/private void createContents() {shell = new Shell(getParent(), getStyle());shell.setSize(463, 366);shell.setText(getText());Group group = new Group(shell, SWT.NONE);group.setBounds(10, 10, 423, 302);Composite composite2 = new ActiveRectangle(group, false, null);composite2.setBounds(81, 102, 51, 90);Composite composite1 = new ActiveRectangle(group, true, null);composite1.setBounds(24, 141, 147, 90);group.setTabList(new Control[]{composite2, composite1});shell.setTabList(new Control[]{group});}
}

这篇关于java SWT入门:自定义背景透明且可鼠标拖动改变尺寸和位置的Composite的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/837560

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav