7、可伸缩窗口

该自定义窗口可以通过鼠标随意更改窗口大小

package com.hikvision.encapsulate.view.control.shell;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; import com.hikvision.encapsulate.view.swt.SWTResourceManager; /**
* <p>自定义shell,该shell仅适用于无标题,即 style == SWT.NO_TRIM使用,提供放大缩小功能</p>
* @author wangfang5 2018年6月11日 下午2:32:07
* @version V1.0
*/
public class DefinedShell extends Shell {
private Point lastPos;
private boolean drag = false;
/**
* <p>锚点对象</p>
* @author wangfang5 2018年6月11日 下午1:39:43
* @version V1.0
*/
private class Anchor {
/**
* 锚点的光标对象
*/
final Cursor cusor;
/**
* 锚点位置计算的掩码
*/
final Rectangle mask;
Anchor(Cursor cusor, Rectangle mask) {
this.cusor = cusor;
this.mask=mask;
}
}
private int anchorIndex; // 光标定义
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+-------+-------+rb
enum 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))};; public DefinedShell(int style){
super(style);
final Cursor defCursor=getCursor();
this.setBackground(SWTResourceManager.getWhiteColor());
if((style & SWT.NO_TRIM) != 0){
getDisplay().addFilter(SWT.MouseDown,event->{
try{
moveAbove(null);
Control control = (Control)event.widget;
if(control.getData("close") == null){
if(event.button == 1 && anchorIndex>=0){
drag = true;
lastPos = ((Control)(event.widget)).toDisplay(event.x, event.y);
}
}
}catch(Throwable e){
}
});
getDisplay().addFilter(SWT.MouseUp, event->{
drag = false;
});
addShellListener(new ShellListener() { @Override
public void shellIconified(ShellEvent e) {
// TODO Auto-generated method stub } @Override
public void shellDeiconified(ShellEvent e) {
// TODO Auto-generated method stub } @Override
public void shellDeactivated(ShellEvent e) {
drag = false;
} @Override
public void shellClosed(ShellEvent e) {
// TODO Auto-generated method stub } @Override
public void shellActivated(ShellEvent e) {
// TODO Auto-generated method stub }
});
getDisplay().addFilter(SWT.MouseMove, event->{
try{
if(drag){ //允许拖拽
Point pos=((Control)(event.widget)).toDisplay(event.x, event.y);
modify(pos.x-lastPos.x,pos.y-lastPos.y,anchors[anchorIndex].mask);
lastPos = pos;
}else{
//查找相对于shell的坐标
Point point = getRelativeShellPoint((Control)event.widget,event.x ,event.y);
anchorIndex = getAnchorIndex(point.x ,point.y);
if(anchorIndex == -1){ //未选中可以拖拽的边
setCursor(defCursor);
}else{
setCursor(anchors[anchorIndex].cusor);
}
}
}catch(Throwable e){
}
});
}
} /**
* 获取相对于shell的坐标
* @author wangfang5 2018年6月11日 下午5:14:34
* @param control
* @return
*/
private Point getRelativeShellPoint(Control control,int eventX,int eventY){
int x = eventX;
int y = eventY;
Control now = control;
while(!(now instanceof Shell)){
x += now.getBounds().x;
y += now.getBounds().y;
now = now.getParent();
}
return new Point(x,y);
} @Override
protected void checkSubclass(){
}
/**
* 改变窗口位置和尺寸
* @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;
// 设置新的窗口位置
setBounds(bound);
redraw();
} /**
* 获取锚点
* @author wangfang5 2018年6月11日 下午2:00:57
* @param mousex
* @param mousey
* @return
*/
private int getAnchorIndex(int mousex,int mousey){
try{
Rectangle bound = getBounds();
if(Math.abs(mousex - bound.width) < 10 && mousey < 10){ //右上角、
return AnchorType.RT.ordinal();
}else if(Math.abs(mousey - bound.height) <= 10 && mousex < 10){ //左下角
return AnchorType.LB.ordinal();
}if(0 <= mousey && mousey < 10 && 0 <= mousex && mousex < 10){ //左上角
return AnchorType.LT.ordinal();
}else if(Math.abs(mousey - bound.height) <= 10 && Math.abs(mousex - bound.width) < 10){ //右下角
return AnchorType.RB.ordinal();
}else if (0 <= mousey && mousey < 5) { //上、
return AnchorType.T.ordinal();
} else if(Math.abs(mousey - bound.height) <= 5){ //下
return AnchorType.B.ordinal();
}else if (0 <= mousex && mousex< 5) { //左
return AnchorType.L.ordinal();
}else if(Math.abs(mousex - bound.width) <= 5){ //右
return AnchorType.R.ordinal();
}else
return -1;
}catch(Throwable e){
return -1;
}
} @Override
public void open() {
// TODO Auto-generated method stub
super.open();
drag = false;
}
}
使用范例:

public MainUI() {
Display display = Display.getDefault();
shell = new DefinedShell(SWT.NO_TRIM | SWT.NONE);
shell.setMinimumSize(shellMinWidth, shellMinHeight);
shell.setBackground(SWTResourceManager.getColor(51, 51, 51));
int shellWidth = 1280;
int shellHeight = 800;
shell.setMaximized(true);
shell.setMinimized(true);
int x = Display.getCurrent().getClientArea().width/2 - shellWidth / 2;
int y = Display.getCurrent().getClientArea().height / 2 - shellHeight / 2;
if(x <= 0){
x = 0;
shellWidth = Display.getCurrent().getClientArea().width/2;
if(shellWidth < (shellMinWidth + 100)){
shellWidth = shellMinWidth + 100;
}
}
if(y<=0){
y = 0;
shellHeight = Display.getCurrent().getClientArea().height/2;
if(shellHeight < (shellMinHeight+100)){
shellHeight = shellMinHeight+100;
}
if((shellHeight + 400)<shellWidth){
shellWidth = shellHeight + 400;
}
}
shell.setLocation( Display.getCurrent().getClientArea().width/ 2 - shellWidth / 2,
Display.getCurrent().getClientArea().height / 2 - shellHeight / 2);
shell.setSize(shellWidth, shellHeight);
} //若是需要最大化按钮和最小化按钮(自己提供的图标),需要给他们绑上事件,代码如下:
Label min_label = new Label(tool_bar_composite, SWT.NONE);
  min_label.setBackground(SWTResourceManager.getColor(51, 51, 51));
  min_label.setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
  GridData gd_min_label = new GridData(SWT.RIGHT,SWT.CENTER,true,false,1,1);
  gd_min_label.heightHint = 24;
  gd_min_label.widthHint = 24;
  min_label.setLayoutData(gd_min_label);
  min_label.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.MININIZE)));
  min_label.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
  min_label.setToolTipText("最小化");
  min_label.addListener(SWT.MouseDown, event ->{
   shell.setMinimized(true);
  });
  
  Label max_label = new Label(tool_bar_composite, SWT.NONE);
  max_label.setBackground(SWTResourceManager.getColor(51, 51, 51));
  max_label.setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
  GridData gd_max_label = new GridData(SWT.RIGHT,SWT.CENTER,true,false,1,1);
  gd_max_label.heightHint = 24;
  gd_max_label.widthHint = 24;
  max_label.setLayoutData(gd_max_label);
  max_label.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.MAXIMIZE)));
  max_label.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
  max_label.setToolTipText("最大化");
  max_label.addListener(SWT.MouseDown, event ->{
   if(shell.getFullScreen()){
    shell.setFullScreen(false);
    max_label.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.MAXIMIZE)));
    max_label.setToolTipText("最大化");
   }else{
    shell.setFullScreen(true);
    max_label.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.RESTORE)));
    max_label.setToolTipText("恢复");
   }
  });

以上DefinedShell提供了通过鼠标改变窗口大小功能,范例中提供了放大窗口和缩小窗口功能。

自定义SWT控件七之自定义Shell(可伸缩窗口)的更多相关文章

  1. 自定义SWT控件六之自定义Tab

    6.自定义tab 本章节提供的自定义tab 分为两类 tab上带删除按钮和添加按钮,可删除tab和添加tab tab不可删除和添加 6.1 不可删除tab package com.view.contr ...

  2. 自定义SWT控件二之自定义多选下拉框

    2.自定义下拉多选框 package com.view.control.select; import java.util.ArrayList; import java.util.HashMap; im ...

  3. 自定义SWT控件一之自定义单选下拉框

    一.自定义下拉控件 自定义的下拉框,是自定义样式的,其中的下拉框使用的是独立的window,非复选框的下拉框双击单机其它区域或选择完之后,独立window构成的下拉框会自动消失. package co ...

  4. 自定义SWT控件五之自定义穿梭框

    5.自定义穿梭框 package com.view.control.shuttlebox; import java.util.ArrayList; import java.util.HashMap; ...

  5. 自定义SWT控件四之其它下拉框

    4.其它下拉框 4.1 添加联动二级多选择框(有添加按钮和删除按钮) package com.view.control.select; import java.util.ArrayList; impo ...

  6. IOS开发--自定义segment控件,方便自定义样式

    系统的segment控件太封闭,想换个颜色加个背景太难了,忍不住自己写一个,以备不时之需 这个控件给出了很多自定义属性的设置,用起来还是比较方便的,需要注意的 itemWidth如果不设置,则会按照控 ...

  7. 自定义SWT控件三之搜索功能下拉框

    3.搜索功能下拉弹出框 package com.view.control.select; import java.util.ArrayList; import java.util.LinkedList ...

  8. javascript实例学习之六—自定义日历控件

    基于之前上篇博客轻量级jquery,tool.js和base.js.自定义开发的base_datePicker插件,效果类似于jquery_ui的datePicker插件 //基于Base.js以及t ...

  9. 【转】带checkbox的ListView实现(二)——自定义Checkable控件的实现方法

    原文网址:http://blog.csdn.net/harvic880925/article/details/40475367 前言:前一篇文章给大家展示了传统的Listview的写法,但有的时候我们 ...

随机推荐

  1. asp.net core 自定义异常处理中间件

    asp.net core 自定义异常处理中间件 Intro 在 asp.net core 中全局异常处理,有时候可能不能满足我们的需要,可能就需要自己自定义一个中间件处理了,最近遇到一个问题,有一些异 ...

  2. 使用release自动打包发布正式版详细教程

    昨天写了个release插件的版本管理,今天就在自动发布过程中遇到了许多坑,只能再写一篇自动发布详细教程,纪念我那昨日逝去的青春 (╥ _ ╥`) release正常打包发布流程按照如下几个阶段: C ...

  3. 你确定你会写 Dockerfile 吗?

    如今 GitHub 仓库中已经包含了成千上万的 Dockerfile,但并不是所有的 Dockerfile 都是高效的.本文将从五个方面来介绍 Dockerfile 的最佳实践,以此来帮助大家编写更优 ...

  4. Don’t Repeat Yourself

    The Don’t Repeat Yourself (DRY) principle states that duplication in logic should be eliminated via ...

  5. zeroMQ 4 java

    自己最开始是在cloud foundry中接触过消息服务器(nats),或者说是消息中间件,也算是初步知道了一个消息服务器对于分布式的网络系统的重要性,后来自己也曾想过在一些项目中使用它,尤其是在一些 ...

  6. c++字符数组

    题目描述 题目描述 输入一个英文句子(长度不会超过100),和他的长度,统计每个字母出现的个数. 输入 第一行包括一个整数,表示句子的长度,长度不会超过100.数字后可能会有多余的无效字符 请gets ...

  7. 音频编辑器 OcenAudio v3.1.9.0 绿色便携版

    下载地址:点我 基本介绍 ocenaudio是一款跨平台的,易于使用的,快速的,功能强大的,好用的音频编辑软件.该软件支持Virtual Studio Technology插件,美观.统一的跨平台界面 ...

  8. 【深入浅出-JVM】(4):编译 jdk

    环境 mac,xcode,jdk8,openjdk,autoconf 步骤 安装autoconf brew install autoconf 下载openjdk源码 git clone https:/ ...

  9. React躬行记(8)——样式

    由于React推崇组件模式,因此会要求HTML.CSS和JavaScript混合在一起,虽然这与过去的关注点分离正好相反,但是更有利于组件之间的隔离.React已将HTML用JSX封装,而对CSS只进 ...

  10. Jenkins Ci系列目录

    Jenkins入门篇 1.Jenkins入门之界面概览 2.Jenkins入门之新建任务 3.Jenkins入门之导航操作 4.Jenkins入门之任务基本操作 5.Jenkins入门之执行Power ...