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

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S