显示标签为“Java”的博文。显示所有博文
显示标签为“Java”的博文。显示所有博文

Log4j+Spring配置

0 评论  

    现在的公司项目原有的log4j是采用的最传统的方式,即在classpath下面新建一个log4j.properties文件,待Tomcat启动的时候log4j.jar会自动扫描这个路径,如果发现这个文件,则加载它,如果没有,打印警告信息并采用默认配置。 这样的配置应该是最简单的,但却很难实现一些比较实在的需求,比如日志输出文件路径采用相对路径,对日志配置文件的监听和动态加载。


    Spring看到了这些需求,发挥其无所不包的特性,对log4做了封装,实现了上述的功能。具体配置如下:
    在web.xml 添加

    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>webName.root</param-value>
    </context-param>
    <context-param>
  <param-name>log4jExposeWebAppRoot</param-name>
  <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>WEB-INF/log4j.properties</param-value>
    </context-param>

    <context-param>
        <param-name>log4jRefreshInterval</param-name>
        <param-value>60000</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

  1. 这里的webAppRootKey是保存整个web应用的相对路径的Key,在你的log4j.properties文件中引用这个路径的时候只需要类似 ${webName.root}就可以了,
  2. log4jExposeWebAppRoot则是表示是否需要把Web应用的根路径导出到webAppRootKey中
  3. log4jConfigLocation,没的说,你的配置文件,这里之所以要你指明,还是有一点玄机的
  4. log4jRefreshInterval,对日志配置文件的监听线程刷新间隔,毫秒为单位
  5. org.springframework.web.util.Log4jConfigListener,上述的context-param最终都是被这个Listener读取并借此初始化以及动态修改log4j配置的

配置算是相当简单了,但 有两个需要值得注意的地方

  1. webAppRootKey不是必须的,如果不填,会自动默认会webapp.root,但如果你有多个web应用运行在同一个JVM中,则必须要指定,不然大家都是webapp.root,所有的webapp.root会指向JVM加载的最后一个web应用的根路径。
  2. log4jConfigLocation这个路径很重要,如果直接沿用传统的方式的路径,WEB-INF/classes/log4j.properties或者classpath:log4j.properties,虽然一样能加载,但是由于log4j自身会自动扫描这个路径,所以应用启动的时候会先抛出多个找不到路径的异常(java.io.FileNotFoundException:),因为你所指定的,根据${webapp.root}来的相对路径log4j本身是不认识的。

JavaFX, 之“立体”球

0 评论  

这是一个展示JavaFX 2D图形,特效,渐变的简单教程。

首先我们创建一个Frame,在坐标(120,140)处绘制一个长60像素,宽20像素,黑色填充的椭圆。然后再坐标(100,100)处绘制一个半径为50,红色填充的圆。组合起来以后,圆看起来就像一个立体的球,而椭圆则是他的阴影。

  1. import javafx.application.*;
  2. import javafx.scene.paint.*;
  3. import javafx.scene.geometry.*;
  4. Frame {
  5. title: "JavaFX Sphere", width: 300, height: 300, visible: true
  6. stage: Stage {
  7. content: [
  8. Ellipse {
  9. centerX: 120, centerY: 140, radiusX: 60, radiusY: 20
  10. fill: Color.BLACK
  11. },
  12. Circle { centerX: 100, centerY: 100, radius: 50, fill: Color.RED }
  13. ]
  14. }
  15. }

现在添加点特效让他更加逼真。

First we’ll just add javafx.scene.effect.* to our import list and just call the gaussian blur effect in our ellipse with

首先我们得把引用加到Import中,import javafx.scene.effect.*,然后调用gaussian blur effect(高斯渐变?)效果到椭圆上,代码如下:

  1. effect: GaussianBlur{ radius: 20 }

就这样简单的一句话,特效就出来了,下面是原来的椭圆: 这个是添加了渐变的椭圆:

现在我们给圆添加一个RadialGradient(光线渐变?)让他看起来更像一个球。代码如下:

  1. RadialGradient {
  2. centerX: 75, centerY: 75, radius: 50, proportional: false
  3. stops: [
  4. Stop {offset: 0.0 color: Color.WHITE},
  5. Stop {offset: 0.3 color: Color.RED},
  6. Stop {offset: 1.0 color: Color.DARKRED},
  7. ]
  8. }

首先让我们来看颜色是如何变化的,从白色开始,在30%的位置变化为红色,剩下的部分渐变到深红色。这样制造出来的渐变如下: 对应于我们的光线渐变,指定坐标在(75,75),半径为50.则其效果如下图:

在应用光学渐变之前,我们的圆如下: 应用渐变之后变得立体起来:

完整的代码如下,简单明了

  1. import javafx.application.*;
  2. import javafx.scene.paint.*;
  3. import javafx.scene.effect.*;
  4. import javafx.scene.geometry.*;
  5. Frame {
  6. title: "JavaFX Sphere", width: 300, height: 300, visible: true
  7. stage: Stage {
  8. content: [
  9. Ellipse {
  10. centerX: 120, centerY: 140, radiusX: 60, radiusY: 20
  11. fill: Color.BLACK
  12. effect: GaussianBlur{ radius: 20 }
  13. },
  14. Circle {
  15. centerX: 100, centerY: 100, radius: 50
  16. fill: RadialGradient {
  17. centerX: 75, centerY: 75, radius: 50, proportional: false
  18. stops: [
  19. Stop {offset: 0.0 color: Color.WHITE},
  20. Stop {offset: 0.3 color: Color.RED},
  21. Stop {offset: 1.0 color: Color.DARKRED},
  22. ]
  23. }
  24. }
  25. ]
  26. }
  27. }

最终效果截图

JavaFX之 Digital Number

0 评论  

JavaFX对2D的支持比Swing要好多了,Swing只是给你了一张白白的画布和一只笔,看似自由度很高,不过复杂性也同样比较高,因为所有的都是一笔一画出来的。

JavaFX里面就不一样了,类似Swing里面的Component,JavaFX geometry包下面的对象就是一些经过包装过的常用2D对象,它们都继承与javafx.scene.Node且实现了javafx.animation.Interpolatable接口,所以都具有事件处理,缩放,坐标转换,角度转换的功能,有了这些就可以轻松的绘制你想要的图形,并且是具备事件处理,很方便就能交互的图形。

我的老主板有一个监控软件,可以显示CPU,主板温度,风扇转速,其中转速这里是用 的类似电子表里面的数字显示,感觉还是比较漂亮的,以前学Swing的时候也想照着做一个,不过全无头绪,现在看见JavaFX了,自然眼前一亮,用Geometry包绝对很简单。

先来个截图: 点击Button按钮,下面的数字加1再Mod 10, 代码不多,也就花了半天时间,主要的思路就是把数字分成八个部分,然后先绘制好第一个部分,剩下的部分通过转换位置,角度来实现,至于透明效果,javaFX里面只需要指定窗口样式为透明,Fill为Null就可以,简单!! 源代码

Java SE 6 Update 10 RC

0 评论  

前段时间去下JDK的时候还是Beta,现在已经是RC了,估计离正式发布也不远了,呵呵,最近看的JavaFX里面用到了桌面透明和不规则窗口,都需要Update 10才行啊,早点出吧。 New Feature Download

JavaFX之我见

2 评论  

RIA从去年到现在一直是一个很热门的话题,从微软的SliverLight,到Adobe的Flex,Java的JavaFX,谁会是未来的主流,谁会成为最终的胜者,现在都还难以定论。就开发状态而言,SliverLight现在是Beta2,Flex也已经到Version3了,JavaFX从去年开始我就看到过了,不过一年的时间过去了,前段时间才出Preview,哎,说实话,Java的东西最大的优势还是在于有一大堆开源免费的解决方案,不然也真的看不出什么好的了,最近我同事一直在关注SliverLight,SliverLight我始终还是提不起兴趣,微软的东西,看上去很美,谁用谁知道吧。Flex也不想去尝试,Flex跟SliverLight也是一路货啊,很强大,不过都是价格不菲,按说盗版真没发达,搞个盗版来玩玩还是很容易的,不过盗版用起来总是让人感觉挺悬乎的。所以最终我还是选择JavaFX学学吧,就算到时候JavaFX很垃圾了,似乎也还可以转到Flex去,就像JavaFX的Hans Muller 一样转战Flex。

这几天都在看JavaFX的相关资料,总体感觉JavaFX还是很强的,不过关于JavaFX的资料太少了,或许你会不相信,Google上搜索一下JavaFX,1,750,000个相关结果,关键的关键是JavaFX的改动太大了,从去年到现在,以前的JavaFX只有3个常用的包,javafx.ui,javafx.ui.canvas,这两个Package在现在的Preview里面已经完全空空如也,这么大的改动Sun也不说一声,害得我下了一本JavaFX的书,准备看图索骥,边看边练,结果HelloWorld都跑不通,还好NetBeans里面有Code Snippet,用了这个才完成了Hello World,汗。。。

而且Java官方网站的例子实在太少了,教程也少得可怜,像API doc,我一开始在网站上找了很久都没找到,后来偶然间打开Preview SDK的安装目录,才知道API Doc藏得这么深,,这个API Doc从界面上来说比以前传统的JavaAPI Doc好看多了,不过里面的内容很多都很“简洁”。 还有一些杂七杂八的让人感觉很不爽的东东,比如说www.javafx.com这个网站,应该也算JavaFX的一个门面了,在FireFox里面看起来还是比较酷的,不过在IE里面就不行了,页面都乱了,哎,粗制滥造啊。还有JavaFX Preview本身的问题,JavaFX里面有些特性是需要JDK Update 10Beta版的,比如窗口透明特性,这点Sun应该在官方网站上说明,我第一天用Preview的时候,Netbeans无故死了好几次,后来想想可能是代码的预览功能,每改动一次代码,预览界面就会刷新一下,这个刷新的过程比较卡,我编HelloWorld的时候都需要好几秒,而且预览界面似乎就是简单的Run了一下,这样每一个预览都开一个新的Frame,可能到后面就内存泄漏了,到后来我就不怎么用Preview,这么慢,还不如直接点击Run。

说了这么多JavaFX的缺点,还是打算好好学一下,毕竟java里面开源的,免费的多,而且其他的不熟啊,还是Java的熟悉,最近听说Sun的日子不好过啊,还有谣言说要被富士通收购,晕,这样的话java不就完了,,,

Java 嵌入浏览器-DJ NativeSwing

1 评论  

Java里面的嵌入浏览器一直比较麻烦,不像C#,VB想调用IE的时候只需要一句话就搞定了,不过现在许多应用都需要在UI里面嵌入一个浏览器,就像Qq,MSN之类,而且如果DesktopUi跟嵌入浏览器能进行数据传递,相互调用的话那就更好了。 以前在Swing里面一直知道的就是JDIC了,JDIC是通过JNI包装调用IE或者FireFox,虽然调用方式比较丑陋,不过基本的还是实现了,起码在Swing里面也能调 了,不过Swing里面只能简单的进行到浏览器的前进,后退,加载,刷新,停止操作,对某些特殊的想法就无能为力了。 今天无意中看到了DJ Native的项目,其实这个项目好像很久之前也看到过,看过Demo,当时没细看,只觉得跟JDIC也差不多,今天才发现,原来DJ native要强大很多。 DJ Native解决了一些JDIC的问题,比如说 轻量级的Swing组件跟它的重量级的组件的绘制问题,Z-order问题。还有Swing的model窗口无法block重量级组件的问题,已经重量级组件跟Swing线程交互的问题。 其实DJ Native底层是用基于SWT实现,众所周知,SWT是IBM搞的对本机API的包装,而且SWT经历过比JDIC更多的检验,比如说Eclipse之类,所以就这一点DJ Native也应该比JDIC有优势。 DJNative里面包含了五个组件和一个文件关联工具,组件包括JWebBrowser,JFlashPlayer,JVLCPlayer,JHTMLEditor,JWMediaPlayer(win32). 分别介绍:

  • JWebBrowser:
细心的人应该能看出这个是对SWT里面的浏览器做了一个封装,使之适应到Swing的环境下面,而SWT又是对本机浏览器的封装,通过JNI,不过这里面有两个个很大的亮点就是1.JWebBrowser支持从Swing调用JavaScript代码段动态的改变页面的内容。 2.JWebBrowser支持从页面上发送参数到Swing端。 这两个特性太酷了,这样就可以实现HTML页面跟Swing的相互调用交互。 JWebBrowser
  • JFlashPlayer:
JFlashPlayer跟JWebBrowser一样,是对FlashPlayer的一个封装,之所以独立的对FlashPlayer进行封装,这里有一个主要的目的就是能够对Flash进行交互,跟JWebBrowser一样,能够从Swing调用FlashPlayer里面的函数也能从FlashPlayer发送参数到Swing端。这个也很酷,不过我不会Flash,所以也就算了。 JFlashPlayer
  • JVLCPlayer:
JVLCPlayer这个是封装了一个VLC的播放器,之所以封装一个VLC的播放器我想应该是出于跨平台的考虑吧,IE里面其实本身也有Embed的播放器的。 JVLCPlayer
  • JHTMLEditor:
JHTMLEditor是封装的一个FCKEditor,其实我之前也一直在想既然Swing没有很好的HTML所见即所得的编辑器,为什么不用JDIC嵌入一个浏览器,然后再调用FCKEditor之类,不过这样做有个很大的问题就是如何跟浏览器交互的问题,你可以通过JDIC得到当前浏览器的整个内容,但是这样做还得遍历整个浏览器的文档去找到用户在FCKEditor里面输入了什么。
  • JWMediaPlayer(w32):
这个是针对WindowsMediaPlayer的一个封装。 更多的去作者的文章里面看吧:http://java.dzone.com/news/dj-nativeswing-reloaded-jwebbr

Swing屏幕截图工具 Swing Screen Capture 之二,实现QQ屏幕截图

2 评论  

前几天的截图工具其实跟QQ的原理不一样,QQ的截图给人感觉是在按下截图按钮之后界面会冻结,界面怎么可能冻结呢?这里一样用了一个全屏的程序,并把按下按钮之前的屏幕截图,作为全屏程序的背景,这样就给人感觉屏幕以冻结。可能你会问,那这个时候如果我按ALT+TAB切换呢,呵呵,QQ把这个程序作为AlwaysOnTop的了,这样就算你切换完了,还是全屏显示这个冻结的画面。 上次做的感觉原理跟QQ的各有千秋吧,QQ这个就像相机,按下快门就已经截图了,只是后面再在截的图上面做裁剪,而上次的那个是动态的,你先取好景,支好三脚架,然后静待美景的出现,再按下快门。 这里我也修改了一下上次的代码,做了个Java版的QQ截图工具,开始截图之前会先通过Robot截取整个屏幕,然后再通过CropImageFilter对图片做裁剪,裁剪代码如下:

     Image captureImage = null;
     ImageFilter cropFilter;
     cropFilter = new CropImageFilter(pn.x,pn.y,pn.width,pn.height);//四个参数分别为图像起点坐标和宽高,即CropImageFilter(int x,int y,int width,int height),详细情况请参考API

     captureImage = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
网上搜索了一下java 图片裁剪,结果少的可怜,看来这个类被人并不常用啊。不过换成从BufferedImage裁剪到Image以后确出了问题,Image不能直接调用ImageIO输出图片了,后面又折腾了半天,把Image又转换会BufferedImage,再保存,晕了,似乎也没什么好的办法了,认了吧。 BufferedImage转Image代码:
      BufferedImage bufferedImage = new BufferedImage(captureImage.getWidth(null), captureImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
     Graphics2D g = bufferedImage.createGraphics();
     g.drawImage(captureImage, null, null);

  • 主屏幕截图:
  • 截图结果:

A Thumbnail Preview Tabbed Pane

0 评论  

【转】 From:http://weblogs.java.net/blog/aberrant/archive/2008/06/a_thumbnail_pre_1.html

Posted by aberrant on June 17, 2008 at 04:07 AM

Lately I've been spending my spare time contributing code samples to the The Java Tutorial Community Portal. My hope is that one or more of these examples will be interesting enough to be included in the official tutorial. My latest addition is an example on how to override tool tip generation for a particular component. This example is a tabbed pane that shows a preview of a tab as a tooltip.

In this picture the mouse was hovering over the "images" tab.

There are techniques for installing custom universal tool tip providers. In this case I only wanted to change the behaviour for one particular component. To accomplish this I overrode the createToolTip() method of JTabbedPane with the following:

/**
* overide createToolTip() to return a JThumbnailToolTip
*/
@Override
public JToolTip createToolTip() {
Point loc = getMousePosition();
int index = indexAtLocation(loc.x, loc.y);

if (index != -1) {
Component comp = getComponentAt(index);

BufferedImage image = ImageFactory.toImage(comp);

JToolTip tip = new JImageToolTip(image, 0.5);

return tip;
} else {
return super.createToolTip();
}
}

This method returns an instance of JImageToolTip which displays an image of the hidden component instead of the tooltip text. The image of the component was generated by the toImage() method of my ImageFactory class.

/**
* Generates a buffered Image of the specified component.
*
* @param componet
* @return image 'snapshot' of the component and it's state at the time this
*         method was called.
*/
public static BufferedImage toImage(Component componet) {
BufferedImage image = new BufferedImage(componet.getWidth(), componet
.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
graphics.setColor(componet.getBackground());
graphics.fillRect(0, 0, componet.getWidth(), componet.getHeight());
componet.paint(graphics);
graphics.dispose();

return image;
}

The JImageToolTipThis also class was used to create a label that displays a thumbnail of an image and provides the full size image as a tooltip.

I've made the full source code available. Comments on this or any other code sample are welcomed and encouraged.

Source Code: ThumbnailTooltipDemo-src.zip

记得以前在Let's Swing Java 的博客上也看到过一篇类似的文章,不过当时感觉他的实现方式似乎比较复杂也就没细看,aberrant的实现方式还是比较简洁的,通过短短的组件的paint方法把组件绘制到一个BufferImage中,不错。

Swing屏幕截图工具 Swing Screen Capture

0 评论  

前两天装Spark的时候发现里面有一个截图工具很炫,Spark是用Swing写的,那这个截图的Function应该也是用Swing来写的,就在想实现的原理,网上搜索了一下,不过多半是讲怎么样截取整个屏幕,但如果要对屏幕上某个区域截图的话似乎是没人提到的。最大的难点应该在于如何在整个屏幕上显示一个可以拖拽的透明矩形框,这个问题我以前也想过,不过一直没想到好的解决方案,其实现在想想关键在于思维局限性,只是想到在屏幕上面绘制一个单纯的透明矩形框,其实完全可以绘制一个大的透明的Cover将整个屏幕遮住,然后再在这个Cover上绘制矩形框就OK了。原理就这么简单了,呵呵,上我的截图:

  • 选取屏幕某块区域:
黑色铅笔区域就是截图工具的选择区域。
  • 截图完成
还有点不足的是,因为用到了窗体透明,所以本程序基于JDK 6 update 10Beta,JDK 6 update 10正式发布估计也还有好几个月吧,这个是局限。 不过通过屏幕截图绘制背景图的方式也可以实现透明,但比起的Sun官方实现,还是略显笨拙。 完整源代码下载。

Swing: Context Menu for TextComponents 文本控件右键菜单

0 评论  

Java编写的GUI程序里面,AWT,SWT,QT Jambi都是基于C++ Dll绘制界面,也就是所谓的重量级界面,而Swing是通过Java2D绘制出来的,完全基于java实现,是轻量级界面。Java的这个轻量级界面有对应于每个操作系统平台的Look and Feel,可以把程序装饰得跟本机程序一样。拿Windows里面的Look and Feel来说,几近以假乱真的程度,不过我还是可以通过一点来很容易的区分Java程序,那就是文本框对右键是没有任何反应的,普通的文本框,右键的时候都会有一个菜单,Cut,Copy,Paste,Select All,而Java的文本框?Nothing。这个缺陷其实不算大问题,Ctrl+C,Ctrl+v。。。就可以实现上面的这些功能,不过,想当初我学电脑的时候,也有很长很长一段时间不知道CTRL+C这些快捷键的,所以怎么说没有右键菜单都让人会觉得Swing在UI这块还是不够Professional,呵呵。 还记得去年实习,在公司做Swing的时候,就有这个想法,那个时候也花了大半天的时间去搜索现成的东东,不过没有找到,其实现在想想这个东西还是跟搜索的关键字有关,从技术的角度来讲,用中文搜跟用英文搜差别太大了,我今天又突然想起这个问题,用英文搜索了一下,结果第一页就找到答案了,呵呵,看来boldtech没白来,起码英文用得多一点了,对学习技术有帮助。 我首先搜索到的一篇文章,写文章的人也是因为对这个问题诟病很久了,它在文章里面提到要实现其实也不难,两种理所当然的方式,一是扩展这些文本组件,二是添加全局的MouseListener,实现Popup,不过这两种方式都被他否定了,因为这两种方式的代码量都比较多,前者需要扩展多种文本组件,TextField,TextArea之类,而且需要将之前的TextField,TextArea做一遍替换,后者则是针对每个Frame都要添加一遍Listener。然后作者提到了一种方案,通过自定义EventQueue来实现,主要的代码如下:

// @author Santhosh Kumar T - santhosh@in.fiorano.com 
public class MyEventQueue extends EventQueue{
protected void dispatchEvent(AWTEvent event){
super.dispatchEvent(event);

// interested only in mouseevents 
if(!(event instanceof MouseEvent))
return;

MouseEvent me = (MouseEvent)event;

// interested only in popuptriggers 
if(!me.isPopupTrigger())
return;

// me.getComponent(...) retunrs the heavy weight component on which event occured 
Component comp = SwingUtilities.getDeepestComponentAt(me.getComponent(), me.getX(), me.getY());

// interested only in textcomponents 
if(!(comp instanceof JTextComponent))
return;

// no popup shown by user code 
if(MenuSelectionManager.defaultManager().getSelectedPath().length>0)
return;

// create popup menu and show 
JTextComponent tc = (JTextComponent)comp;
JPopupMenu menu = new JPopupMenu();
menu.add(new CutAction(tc));
menu.add(new CopyAction(tc));
menu.add(new PasteAction(tc));
menu.add(new DeleteAction(tc));
menu.addSeparator();
menu.add(new SelectAllAction(tc));

Point pt = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), tc);
menu.show(tc, pt.x, pt.y);
}
}
很简单?的确,只是在MouseEvent里面对Event进行过滤,对右键菜单,并且是来自文本组件的右键菜单添加Popup菜单,
这种方案的确比较简单,最终只需要一行代码,
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new MyEventQueue()); 将这个EventQueue加到系统的EventQueue
中就Ok了,不过这个贴发出来以后就有很多反对的声音,主要是这种对全局右键事件的监听可能会打破原有的事件监听体系。
所以这个方案也只是 看上去很美,不过后面有人提到Swinglab的SwingX项目里面通过在look And Feel 里面添加 auxiliary LF
来实现,刚好我在IPSeeker里面 用到了SwingX项目,结果通过一行代码也实现了右键菜单,
UIManager.addAuxiliaryLookAndFeel(new ContextMenuAuxLF());
其中ContextMenuAuxLF位于SwingX中,org.jdesktop.swingx.plaf.ContextMenuAuxLF,不过这个文件的代码我没怎么看懂,大概就是
通过在重新TextUI,在其中加入每个textComponent对应的Action所生成的Popup。代码都不多,看似很简洁,很美,
IPSeeker中右键菜单截图:
  • 空白文本框中的右键菜单
  • 选中文字后右键菜单
  • TextArea中的右键菜单

SwingX 实现分析:
SwingX是开源的,这点很不错,直接看源代码就可以知道是怎么实现的了,我感觉编程不是一个技术活,经过一段时间的
培训,人人都可以编程,关键要是编出很好看的代码,那才叫牛逼,就像写文章,每个人都会写,但只有少数人能够成为
作家。扯远了,前面也提到SwingX的实现方式主要是通过
UIManager.addAuxiliaryLookAndFeel(new ContextMenuAuxLF());给当前的UIManager添加一个辅助的LookAndFeel,这个
特性很重要,很多时候重新一个LookAndFeel所需要的工作量是相当巨大而且可能是没必要的,这个时候通过调整部分UI,
作为一个辅助的LookAndFeel来添加就显得尤为重要,说白了这个辅助的LookAndFeel会覆盖当前LookAndFeel当中已有的
部分,而辅助的LookAndFeel没有实现的那些部分让又原有的LookAndFeel负责。
  • 下面介绍下ContextMenuAuxLF(注释部分用绿色标出,下同):
/*
* $Id: ContextMenuAuxLF.java,v 1.5 2006/03/30 10:19:12 kleopatra Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
package org.jdesktop.swingx.plaf;

import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;

/**
* Support for context dependent popup menus.
*
* It's meant to be used as a auxiliary LF on top of main LF:
*
*  
*  
*  UIManager.addAuxiliaryLookAndFeel(new ContextMenuAuxLF());
*  
*  
* * There are core-issues involved, which might or might not * impair its usefulness, for details please see a thread in * the SwingLabs forum:

* * * Experimental: default context menus for textcomponents/scrollbars * * * * @author Jeanette Winzenburg */ public class ContextMenuAuxLF extends LookAndFeel { private UIDefaults myDefaults; public String getName() { return "ContextMenuAuxLF"; } public String getID() { return getName(); } public String getDescription() { return "Auxiliary LF to Support Context Dependent Popups"; } public boolean isNativeLookAndFeel() { return false; } public boolean isSupportedLookAndFeel() { return true; } public UIDefaults getDefaults() { if (myDefaults == null) { initDefaults(); } return myDefaults; } private void initDefaults() { myDefaults = new MyUIDefaults(); Object[] mydefaults = { "TextFieldUI", "org.jdesktop.swingx.plaf.ContextMenuAuxTextUI", "EditorPaneUI", "org.jdesktop.swingx.plaf.ContextMenuAuxTextUI", "PasswordFieldUI", "org.jdesktop.swingx.plaf.ContextMenuAuxTextUI", "TextAreaUI", "org.jdesktop.swingx.plaf.ContextMenuAuxTextUI", "TextPaneUI", "org.jdesktop.swingx.plaf.ContextMenuAuxTextUI", "ScrollBarUI", "org.jdesktop.swingx.plaf.ContextMenuAuxScrollBarUI", }; myDefaults.putDefaults(mydefaults); /*关键在于这里,UIDefaults其实是一个HashTable,通过观察你也许就会发现,这里用来初始化UIDefaults的 是一些键值对,键是UI,Name是这个UI对应的实现。这里把TextField,EditorPane,PasswordField,TextAreaUI都初始化 "org.jdesktop.swingx.plaf.ContextMenuAuxTextUI"实现 */ } /** * UIDefaults without error msg. * */ private static class MyUIDefaults extends UIDefaults { /** * Overridden to do nothing. * There will be many errors because this is incomplete as * of component types by design * */ @Override protected void getUIError(String msg) { } } }

  • ContextMenuAuxLF引用到ContextMenuAuxTextUI
/*
* $Id: ContextMenuAuxTextUI.java,v 1.5 2005/10/24 13:20:45 kleopatra Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
package org.jdesktop.swingx.plaf;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseListener;

import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.TextUI;
import javax.swing.text.BadLocationException;
import javax.swing.text.EditorKit;
import javax.swing.text.JTextComponent;
import javax.swing.text.View;
import javax.swing.text.Position.Bias;

/**
* @author Jeanette Winzenburg
*/
public class ContextMenuAuxTextUI extends TextUI {

 private MouseListener mouseHandler;

 public static ComponentUI createUI(JComponent c) {
     return new ContextMenuAuxTextUI(); //单态模式
 }

 public void installUI(JComponent comp) {
     comp.addMouseListener(getMouseListener());//在InstallUI的时候给组件加上鼠标侦听
 }

 public void uninstallUI(JComponent comp) {
     comp.removeMouseListener(getMouseListener());//在卸载UI的时候移除监听
 }



 private MouseListener getMouseListener() {
     if (mouseHandler == null) {
         mouseHandler = createPopupHandler();//创建新的PopupHandler,处理右键弹出事件
     }
     return mouseHandler;
 }

 private MouseListener createPopupHandler() {
     return new ContextMenuHandler(createContextSource());
 }

 private ContextMenuSource createContextSource() {
     return new TextContextMenuSource();
 }

 public void update(Graphics g, JComponent c) {
 }

 public Rectangle modelToView(JTextComponent t, int pos)
         throws BadLocationException {
     // TODO Auto-generated method stub
     return null;
 }

 public Rectangle modelToView(JTextComponent t, int pos, Bias bias)
         throws BadLocationException {
     // TODO Auto-generated method stub
     return null;
 }

 public int viewToModel(JTextComponent t, Point pt) {
     // TODO Auto-generated method stub
     return 0;
 }

 public int viewToModel(JTextComponent t, Point pt, Bias[] biasReturn) {
     // TODO Auto-generated method stub
     return 0;
 }

 public int getNextVisualPositionFrom(JTextComponent t, int pos, Bias b,
         int direction, Bias[] biasRet) throws BadLocationException {
     // TODO Auto-generated method stub
     return 0;
 }

 public void damageRange(JTextComponent t, int p0, int p1) {
     // TODO Auto-generated method stub

 }

 public void damageRange(JTextComponent t, int p0, int p1, Bias firstBias,
         Bias secondBias) {
     // TODO Auto-generated method stub

 }

 public EditorKit getEditorKit(JTextComponent t) {
     // TODO Auto-generated method stub
     return null;
 }

 public View getRootView(JTextComponent t) {
     // TODO Auto-generated method stub
     return null;
 }

}

  • ContextMenuAuxTextUI中添加的ContextMenuHandler
/* * $Id: ContextMenuHandler.java,v 1.5 2005/10/24 13:20:46 kleopatra Exp $ * * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jdesktop.swingx.plaf; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.ActionMap; import javax.swing.JComponent; import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; /** * Responsible for showing the default PopupMenu. * * @author Jeanette Winzenburg */ public class ContextMenuHandler extends MouseAdapter { private ActionMap actionMap; private ContextMenuSource contextMenuSource; private JPopupMenu popup; /** * creates a context handler for TextContextMenuSource. * */ public ContextMenuHandler() { this(null); } /** * creates a context handler for the given ContextMenuSource. * Defaults to TextContextMenuSource if source == null. * * @param source */ public ContextMenuHandler(ContextMenuSource source) { contextMenuSource = source; } // --------------------- MouseListener public void mousePressed(MouseEvent e) { maybeShowContext(e);//在鼠标按下时检测是否是除非弹出事件 } public void mouseReleased(MouseEvent e) { maybeShowContext(e);//在鼠标释放时检测是否是除非弹出事件 } private void maybeShowContext(final MouseEvent e) { if (!e.isPopupTrigger() || !e.getComponent().isEnabled())//判断条件:该事件是弹出事件,触发该事件的组件没被禁用 return; if (e.getComponent().hasFocus()) { showContextPopup(e);//显示Popup } else { ((JComponent) e.getComponent()).grabFocus(); SwingUtilities.invokeLater(new Runnable() { public void run() { showContextPopup(e); } }); } } private void showContextPopup(MouseEvent e) { showContextPopup((JComponent) e.getComponent(), e.getX(), e .getY()); } private void showContextPopup(JComponent component, int x, int y) { JPopupMenu popup = getPopupMenu(component, true); popup.show(component, x, y); } /** * @param component * @return */ private JPopupMenu getPopupMenu(JComponent component, boolean synchEnabled) { if (popup == null) { popup = new JPopupMenu(); ActionMap map = getActionMap(component);//得到组件的ActionMap String[] keys = getContextMenuSource().getKeys(); for (int i = 0; i < style="color: rgb(102, 255, 153);">//添加对于的Action到Popup中 } else { popup.addSeparator(); } } } if (synchEnabled) { getContextMenuSource().updateActionEnabled(component, actionMap);//检查哪些Action可用 } return popup; } private ActionMap getActionMap(JComponent component) { if (actionMap == null) { actionMap = getContextMenuSource().createActionMap(component); } else { // todo: replace actions with components? } return actionMap; } private ContextMenuSource getContextMenuSource() { if (contextMenuSource == null) { contextMenuSource = new TextContextMenuSource(); } return contextMenuSource; } }
  • ContextMenuHandler用到的TextContextMenuSource
/* * $Id: TextContextMenuSource.java,v 1.5 2006/05/14 08:19:45 dmouse Exp $ * * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jdesktop.swingx.plaf; import java.util.Map; import javax.swing.ActionMap; import javax.swing.JComponent; import javax.swing.JPasswordField; import javax.swing.text.DefaultEditorKit; import javax.swing.text.JTextComponent; /** * @author Jeanette Winzenburg */ public class TextContextMenuSource extends ContextMenuSource{ String UNDO = "Undo"; String CUT = "Cut"; String COPY = "Copy"; String PASTE = "Paste"; String DELETE = "Delete"; String SELECT_ALL = "Select All"; String[] keys = { DefaultEditorKit.cutAction, DefaultEditorKit.copyAction, DefaultEditorKit.pasteAction, DefaultEditorKit.deleteNextCharAction, null, // separator DefaultEditorKit.selectAllAction };//文本组件的Action Name,ActionMap的Key,Null用来表示一个分隔符号 String[] defaultValues = { CUT, COPY, PASTE, DELETE, null, SELECT_ALL, }; public String[] getKeys() { return keys; } public void updateActionEnabled(JComponent component, ActionMap map) { if (!(component instanceof JTextComponent)) return; JTextComponent textComponent = (JTextComponent) component; boolean selectedText = textComponent.getSelectionEnd() - textComponent.getSelectionStart() > 0;//是否有文本被选中,条件1 boolean containsText = textComponent.getDocument().getLength() > 0;//是否有文本,条件2 boolean editable = textComponent.isEditable();//可否编辑,条件3 boolean copyProtected = (textComponent instanceof JPasswordField);//如果是PasswordField,则不能Copy,条件4 boolean dataOnClipboard = textComponent.getToolkit() .getSystemClipboard().getContents(null) != null;//系统剪切板上是否有数据,条件5 map.get(DefaultEditorKit.cutAction).setEnabled( !copyProtected && editable && selectedText);//Cut可用的条件是 4,3,1均成立 map.get(DefaultEditorKit.copyAction).setEnabled( !copyProtected && selectedText);//Copy可用的条件是 4,1成立 map.get(DefaultEditorKit.pasteAction).setEnabled( editable && dataOnClipboard);//Paste可用的条件是3,5成立 map.get(DefaultEditorKit.deleteNextCharAction).setEnabled( editable && selectedText);//Delete成立的条件是3,1成立 map.get(DefaultEditorKit.selectAllAction).setEnabled(containsText);//selectedAll需要条件2 }
引用来自:

Swing: Context Menu for TextComponents

SwingLabs

JDK 6 Update 7

2 评论  

今天无聊逛了一下java.sun.com,结果发现又有新的JDK更新了,Update7,记得前段时间下载Update6的时候还没多久呢,呵呵,最近Sun的更新比较频繁啊,看来传说中的Update 10也快正式发布了吧。 官方 的Release Note里面提到Update 7 照例干了一些Bug Fix 的活,不过这次附带一个Java Visual VM的工具软件,记得以前看到网上有篇文章,对Java VM的一个诟病之处就在于基于JMX API 无法很好的对VM进行监控,文中似乎还提到JRockit跟IBM的的那个VM比较好的一点就是对VM监控这方面的增强。 为了体验一下这个Visual VM,我装了一下Update 7,不过装完之后没有提示说有这么一个比较重要的特性。其实这里不得不提到一点,JDK安装好后,除了会在控制面板里面添加一个Java 的快捷方式,方便管理WebStart的东东以为就没有其它的快捷方式了,其实Java里面也有很多的好用的工具软件啊,大的比如说Java DB,小的有Native2Ascii,不知道在开始菜单里面新建一个Java 的文件夹,放上常用的快捷方式是不是会更加人性化一点,呵呵。 找这个Visual VM就是靠经验了,在JDK_HOME/bin目录下面,有一个jvisualvm.exe文件,看名字也就知道是它了,双击打开,从UI上来看,这个软件是基于NetBeans开发的了。

  • Splash界面
  • OverView界面
  • Monitor界面
  • Threads界面
  • Profiler界面
从界面上看还是比较简洁的,左边是树形结构,自动显示当前本机所运行的Java程序,还可以添加远程的Java VM,其中括号里面的PID指的是进程ID。OverView界面显示VM启动参数以及该VM对应的一些属性。Monitor界面则是监控Java堆大小,Permgen大小,Classes和线程数量。Profiler界面比较有趣,看样子似乎可以动态的对某个Java程序进行调优了。不过我没试用这个功能,感觉要调优还是在Netbeans里面比较自然一点,起码有代码,没代码调优了用处也不大。而且这里还有个问题,有些VM是没有Threads跟Profiler界面的,不知道是什么原因,像我截图里面的Weblogic的Server就没有这两个界面。

QT Jambi Clock

0 评论  

学程序也有好几年了吧,呵呵,从C程序开始,一直都想要写一个比较漂亮点的桌面程序,不过一直都有这样那样的问题,C++学得太烂了,学到最后还是只会写Console程序,什么是Console程序?就是在命令行(我叫它黑屏)里面运行的程序。还记得那个时候跟阳春一起去参加学校里面的C++程序大赛,呵呵,当然,我的水平很菜的,都靠阳春了,也混了个三等奖,不过一来多半是阳春出的力,再者我也觉得Console的程序实在太丑了。参考程序大赛之前还听过一节钱能的课,大学老师里面我还记得名字不多了,钱能算一个,主要这个名字还是比较牛逼的,有钱就能,哈哈。都说他的C++讲的很好,连那本红红的C++程序书也是他主编的,自然有点崇拜的意思了,不过现在都记得,为了运行在BolandC++6.0里面运行Console程序,钱老师让我们在每个程序的最后都会有一句话大概是cin>>。当时还有点莫名,不过其实这句话学过C++的应该知道,是等待命令行输入的,之所以有这句话,是因为每次运行完Console程序后BolandC++会自动退出这个程序,一般来讲,应该显示Press any key to Continue...这可能是BC6的Bug吧。 后来数据结构课的时候有一个作业,大概是模拟一个冰淇淋店,也是用Console的,因为当时还没写过不是Console的程序,也一直觉得用MFC挺难写的,大部分人应该都这样吧,所以那年的作业几乎都是用Console写的,我写这个程序花了很长时间,用VC6写的,当时就是一开始写很多代码,然后编译,在心里默默祈祷不报错,结果往往是报好几十个编译错误,让人眼花缭乱,无从下手,我C++写的少,就用过VC6,BC6,不过我总觉得VC6就是Shit,编译出来的错误信息千奇百怪,但就是不指向真正错误的地方,这点后来在接触Java以后深有感触。冰淇淋店的程序写到后来在要交作业之前终于能运行了,不过程序还有Bug,当时也基本不会调试,调了好久一直没通,眼看就要到最后期限了,就用了上面提到那招,老师当时坚持作业是让她的研究生来做的,他们都是看程序的运行有没有正常结束,恰好我的程序不能正常结束,我就自己Cout一行,“Press any key to Continue。。。”,也让我蒙过了,哎,惭愧啊。。。 再后来学Java了,应该是大二暑假吧,把电脑带回家,借了一本Java的书,主要也就是看中了书里面有很简单易学的GUI界面编程的东西,不像以前那些书,通篇看下来还不知所云,就这样进入了Java的怀抱。 后来才知道,Swing架构的确不错,MVC,轻量级的UI,不过这些都无法弥补Swing的致命弱点,运行速度慢,很多操作系统平台级别的API很难调用,比如你要写一个半透明的程序,要写一个不规则窗口,这些可以实现,一般人要实现这些那真太难了,要用到JNI,要封装C++程序来调本地API,再通过Java来调这个C++程序,太麻烦了,我曾经为了这两个问题搜索了好几天的百度,Google,也有些结果,不过不是因为效率太低,就是因为程序太难用而放弃了。而且其实Swing也不够灵活,说这句话是看了QT Jambi后才说,之前也觉得Swing是比较灵活,你可以通过Java2D绘制出很炫的程序,也有很多开源的框架,不过跟QT Jambi比起来,那还是有差距的。 QT是我偶然间发现的,当时就想找找C++里面有没有标准的GUI库,也是想试试看在NetBeans里面编个C++的GUI程序,搜索到很多第三方的C++库,也不知道哪个好,就一个一个的放到Google里面去,看返回的结果,谁最多就选谁了。说实话QT这个名字我不喜欢,不太专业,打开了他的官方首页一看,没想到QT还有For Java Developer的,就把这个ForJava 的版本Down了下来,里面有一个Exe的程序,打开,是QT的一些例子,一个个看下来,哇靠,效果刚刚的,看了一下这个Demo的源代码,似乎不是很难,就想要用它来写一个程序,Google一下,想找个简明教程来着,结果很让人失望,QT在C++领域是比较牛了,用得人很多,不过在Java领域几乎还是空白,没什么例子好参考,只剩下这个Demo了.上个星期天的时候把那个IP程序改得差不多了,不想改了,就试着去改QT JambiDemo里面的一个例子,这个例子在屏幕上画了一个圆形的时钟,窗口是圆形的,觉得挺有趣的,就基于这个程序,原程序是通过QT的2D绘制出来,比较丑,就想给它加个背景,搞了一下午,总算加好背景了。不过苦于没有好看的,合适的背景,星期一上班的时候去搜索了一下现有的Clock程序,找到一个也是绘制一个圆形的时钟,背景是BmP图片,呵呵,就用这个了,把这个程序里面的图片结合我已有的程序,效果还不错,后面就模仿它的功能做了一个背景样式选择. 完整源代码下载