Java桌面技术

Java Desktop Technology

常用链接

统计

友情连接

最新评论

打造专业外观-二

在上一篇《打造专业外观-九宫图》,介绍了九宫格的概念并留下了一个演示程序。那个程序只是一个渲染过的窗口,许多必要的功能尚未实现,比如拖拽移动、改变大小、标题栏双击等。好现在就来一一实现。
你首先从这里下载上一篇程序的代码,然后在eclipse中打开。
一、拖拽移动与双击标题栏。
为DemoShell类添加下列成员
private Point location;
注意:导入的时候仔细看import语句。import org.eclipse.swt.graphics.Point;而不是import java.awt.Point;
窗体的拖拽操作一般是拖拽窗体的标题栏,所以实现的思路就确定在northPanel了。方法就是为northPanel(充当标题栏)添加鼠标事件监听器。
northPanel.addMouseListener(this);
northPanel.addMouseMoveListener(this);
然后使DemoShell实现ControlListener、MouseListener、MouseMoveListener接口,并生成接口方法。
在mouseDoubleClick方法中添加如下代码:
if (e.getSource() == northPanel) {
   setMaximized(!getMaximized());
  }
首先判断如果双击是northPanel发起的,那么立即改变状态,只需一句话即可。
在mouseDown添加如下代码:
if (e.getSource() == northPanel) {
   if (!getMaximized()) {
    location = new Point(e.x, e.y);
   }
  }
同理,要判断是否是northPanel发出的双击事件。然后在窗口不是最大化时再为location赋值,注意,是在窗口不是最大化时,否则location就应该为null。之所以这么做是当窗体呈最大化状态时不应该移动,道理不难理解。
然后在mouseUp方法中添加如下代码:
if (e.getSource() == northPanel) {
   location = null;
  }
当鼠标抬起时,释放location。
接下来是最重要的mouseMove方法。该方法如下:
public void mouseMove(MouseEvent e) {
  if (e.getSource() == northPanel) {
   if (location != null) {
    Point p = getDisplay().map(this, null, e.x, e.y);
    setLocation(p.x - location.x, p.y - location.y);
   }
  }
 }
注意:有对location不空的判断。map(Control from, Control to, int x, int y)函数是坐标转换,把from组件上的(x,y)坐标转换成to组件的坐标。null表示to组件就是桌面。如果你仔细研读《SWT自定义组件之Slider》就会比较容易理解。
现在你可以运行程序,发现窗口可以拖拽了。

二、改变大小
添加如下变量声名
private Point size;
然后在mouseDown方法中追加如下语句
 else if (e.getSource() == southeastPanel) {
   size = new Point(e.x, e.y);
  }
在mouseUp中追加如下语句
else if (e.getSource() == southeastPanel) {
   if (size == null) {
    return;
   }
   setSize(new Point(getBounds().width + e.x - size.x,
     getBounds().height + e.y - size.y));
   size = null;
  }
其原理同上。
这个时候可以改变尺寸了,再添加如下功能画龙点睛。
private Cursor seCursor = new Cursor(getDisplay(), SWT.CURSOR_SIZESE);

 private Cursor titleCursor = new Cursor(getDisplay(), SWT.CURSOR_SIZEALL);
southeastPanel.setCursor(seCursor);
northPanel.setCursor(titleCursor);
好。现在运行程序观察下结果,但是美中不足的是,当拖拽右下角改变尺寸时,没有一个虚线来指示,能不能像前面《SWT自定义组件之Slider》虚拟划块那样实现呢,答案是不能,究其原因是Java支持的绘图操作还只能以组件为画布,不能实现在桌面上绘图,有待SWT、AWT(swing不行)在底层提供了这一功能。由于时间关系,只能先介绍移动、改变大小的实现。最小化、最大化、关闭等功能按钮,圆角,标题栏文字等的实现,以后再做介绍。不过您可以尝试标题栏文字着一功能,很简单,为northPanel添加addPaintListener即可。
改进后的代码这里下载

posted on 2007-11-04 20:12 sun_java_studio@yahoo.com.cn(电玩) 阅读(6831) 评论(9)  编辑  收藏 所属分类: NetBeansGUI Design

评论

# re: 打造专业外观-二 2007-11-05 03:06 欢乐猪

>>>究其原因是Java支持的绘图操作还只能以组件为画布,不能实现在桌面
>>>上绘图,有待SWT、AWT(swing不行)在底层提供了这一功能。

在Display上画图就相当于在桌面上画。
GC gc = new GC(display);
.....

另外GC.setAlpha(int alpha)可以控制透明度。

===================================================

>>>但是美中不足的是,当拖拽右下角改变尺寸时,没有一个虚线来指示,
>>>能不能像前面《SWT自定义组件之Slider》虚拟划块那样实现呢

这个功能要自己在桌面上画的话挺费劲的,
可以考虑用一个Tracker(SWT.RESIZE)。  回复  更多评论   

# re: 打造专业外观-二 2007-11-05 08:31 Matthew Chen

老是想到有个什么东西可以,原来是Tracker,swt sample里有。还有就是swing实现透明窗格,最近才知道还有个jna,看这里:http://www.blogjava.net/ruislan/archive/2007/10/24/154689.html
只是不知是否可以跨平台了,我以前一直觉得只要能有透明窗格,swing也能有Tracker这样的东西了,现在又不确定了,因为透明ms上面的一切都变透明了,不知画出来的线还看不看得到,不然就只有用toolkit里的取capture的方法模拟桌面来实现。
还有个问题,为什么我以前装ubuntu的时候java不提供win L&F,在win下也不提供GTK L&F,如果是许可证的问题那我们以后要怎么用它的皮肤啊。  回复  更多评论   

# re: 打造专业外观-二 2007-11-05 09:59 sun_java_studio@yahoo.com.cn(电玩)

@Matthew Chen
如果C水平足够强的话,完全可以弥补AWT SWT处理半透明等能力的不足,jna就是C。但是Java开发员当然期望这一切集成在Java中,Sun之所以计划在JDK1.7中实现这一功能,Vista的刺激是很重要的原因,AWT要实现不规则窗体、半透明窗体不是那么容易,原因不在AWT与技术难度,是因为接口得重新写,还要考虑跨平台和向前兼容,即使在JDK中有对应的功能,对于某些不支持透明的OS也无能为力。Sun公司AWT研发在俄罗斯,Swing研发在美国,彼此的协商也是一定问题,为苏联老大哥祈祷吧。  回复  更多评论   

# re: 打造专业外观-二 2007-11-05 10:02 sun_java_studio@yahoo.com.cn(电玩)

@欢乐猪
关于SWT的技术我主要来自http://www.eclipse.org/swt/snippets/和www.java2s.com。后来青睐swing后一直没怎么关注  回复  更多评论   

# re: 打造专业外观-二 2007-11-05 16:57 原来只潜水的人

精彩  回复  更多评论   

# re: 打造专业外观-二 2007-11-05 19:33 欢乐猪

>>> 透明窗格
----------------------------------------------------------------
不通过JNI,透明窗格根本没法实现,因为那是窗口子系统的一个特性。
窗口子系统不支持的话,谁也没则。 Windows 2000就不支持, 据说
Linux采用的X Window也不支持。 最早是macosx实现的,Microsoft直到
XP才有。SWT没有加入这个功能,可能是因为受到太多有关平台之间差异性
的批评,和不支持的平台太多也有关。其实完全可以提供,如果平台不支持就忽略。像SWT一贯的做法,我觉得挺好。

可以模拟,像Matthew Chen说的是一种方法,缺点是得启动一个Timer。

还有一个模拟的法子,
SWT的Snippets中有, 叫emulate transparent shell。就是用Non-Rectangle的Shell, 把Shell镂空,像一张网一样,只要网格够小,
看起来就是透明的。不用Timer,跨平台,只不过不好控制透明度。


不然就得JNI了, MS Windows下
void setWindowTransparency(int hwnd, int alpha) {
byte byteAlpha = (byte) alpha;
int style = OS.GetWindowLong(hwnd, OS.GWL_EXSTYLE);
OS.SetWindowLong(hwnd, OS.GWL_EXSTYLE, style |
OS.WS_EX_LAYERED);
OS.SetLayeredWindowAttributes(hwnd, 0, byteAlpha,
OS.LWA_ALPHA);
}

hwnd用Shell.handle。 就把一个不透明的Shell,改成透明度为alpha
的Shell了, alpha在0到256之间, 0是全透明。3个C函数SWT的
OS都已经做好对应,省了很多麻烦。

懒得写文章,就接LZ的帖子和大家分享些经验了。
  回复  更多评论   

# re: 打造专业外观-二 2007-11-06 00:57 sun_java_studio@yahoo.com.cn(电玩)

@欢乐猪
我不明白OS.SetLayeredWindowAttributes函数和OS.LWA_ALPHA还有OS.WS_EX_LAYERED是怎么出来的。是在3.3版运行的么。
JNI,Swing的Java2D也用JNI实现的,我说过如果C足够强的话,不在乎你用什么WT,Sun的同事就做过这些。  回复  更多评论   

# re: 打造专业外观-二 2007-11-06 03:29 欢乐猪

是啊, org.eclipse.swt.internal.win32.OS是SWT的一个非API类。当然你得用windows的SWT版本。我是在3.4M2下试的,好像不是新加上的,3.3应该早就有了  回复  更多评论   

# re: 打造专业外观-二 2008-06-25 11:22 yunjitang

太棒了。正是我所想要的。学习研究中  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
TWaver中文社区