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

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