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 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll