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实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2