我的开发环境是Eclipse 3.3.1,JDK 1.4.2_19
最近都在做Swing相关的开发,对于swing组件底层的运转机制不甚理解,一直心有余悸。这两天在开发一个弹出框,类似JComboBox的下拉框,想要鼠标点击弹出框之外的区域时,弹出框会自动消失。
上图是偶做的一个弹出框,这其实是个JDialog,去掉修饰[详见方法setUndecorated(...)],在用户点击“新增人员”的时候,弹出一个JDialog在与JButton相对合适的坐标处,代码如下:
dlg.setCompanyList(companyList);
Point p = btnNewMember.getLocation();
SwingUtilities.convertPointToScreen(p, FilterListFrame.this.paneMain);
dlg.setLocation((int) p.getX(), (int) p.getY() + btnNewMember.getHeight());
dlg.show();
变量说明:
dlg JDialog的子类创建的窗口对象,也就是图片中的“选择人员所在机构”弹出框
btnNewMember JButton对象,图中的“新增人员”按钮
关键逻辑:
因为按钮btnNewMember是被添加到面板paneMain上,所以btnNewMember.getLocation()得到的是btnNewMember在面板paneMain中的坐标,使用SwingUtilities转换这个坐标为btnNewMember在屏幕中的绝对坐标,而后把可爱的弹出框锁定在按钮的正下方。
而后鼠标点击弹出框之外的区域,如何隐藏弹出框呢?这个时候瞅见了JComboBox,如果能够懂得ComboBox的运转机制应该就能解决这个问题。
就这样从愚人节的早上一直翻到愚人节晚上的12点左右,白天坐在办公桌前,晚上躺在窗口,怎么都看不明白。
白天的时候查到Sun官方论坛有个帖子“Swing - About popup hide”,链接是 http://forums.sun.com/thread.jspa?threadID=5342058
帖子里有个帅哥叫做“camickr ”,一言点醒梦中人,意思是——JComboBox的逻辑都被写入到UI类,你可以从源码中寻找线索,不过会被复杂的逻辑弄得很困扰……
晚上的时候,我就纳闷了,不知道第几次翻开这些代码——
1.JComboBox 浏览代码的关于鼠标监听器的部分,没有找到任何线索,想想camickr大哥(也说不定是个大叔~~⊙﹏⊙b汗)说的,逻辑都写进UI类了
2.ComboBoxUI 抽象类,没什么可看的,进入实现类
3.BasicComboBoxUI 在这里,找到属性popup,发现它的类型是ComboPopup,一直只知道有JPopupMenu,没想到还有个ComboPopup,难道是给ComboBox专用的?看来有玄机
4.ComboPopup 晕,是个接口,实现类中我比较感兴趣的是 BasicComboPopup 和 MetalComboPopup
5.BasicComboPopup, MetalComboPopup 在这两个类之间徘徊了很久,没有看出什么神秘的地方(就因为没发现,才让我晚上又转点了~~)
反反复复地看着几个类,几个钟头下来终于没耐心了,因为我的开发工具是Eclipse,打开Debug模式,我在类JComboBox的方法 showPopup(), hidePopup(), setPopupVisible() 上设置断点,并且还在我怀疑的几个UI类上的处理鼠标点击事件的方法上加上断点,发现意料之外情理之中的事情了,鼠标点击JComboBox的时候,这些方法有的有反应,但是鼠标点击ComboBox之外的区域时,没有一个方法被断点停住脚步的。
这说明什么呢?ComboBox以及相关的辅助类中的鼠标监听器是不会处理ComboBox外的鼠标事件的。
其实用swing这么久,这个道理也是懂的,事件监听器不加到Component或JComponent上是不可能在这些组件上捕获到鼠标事件的。也就是说,ComboBox的上级面板paneMain(上文中提到的JPanel对象 )必然被加上了鼠标监听器。(^_^ 忘记一个很重要的事情,图片中右边那个弱不禁风的ComboBox就是我本文中分析ComboBox运转机制的对象)
确定了这个正确的思考方向,回到BasicComboBoxUI和BasicComboPopup之中(这就是宿命~~因为运气好,转点之后,脑袋发晕就只盯着这两个类了,要不然通宵可能都搞不定),在所有的鼠标操作方法上设置断点,因为我觉得既然要给面板加上鼠标事件监听器,必然得通过ComboBox本身的事件来辅助完成这个操作(其实这是现在总结的,当时完全是没方向的乱试),5分钟不到就推翻了我的想法,没有经过这里。
目光游走落到了类 BasicComboPopup 中叫 MouseGrabber 的静态内部类上,既然和鼠标点击有关,那么字样里有Mouse的自然特别吸引眼球,怪哉怪哉,代码里只调用了一次MouseGrabber的构造器,但是没有调用它的任何方法(奸笑一下,感觉 BasicComboPopup 的作者也跟我一样是熬通宵脑袋晕了吧~~),反正代码基本都过了一遍,抱着再看一次也损失不了的心态,打开 MouseGrabber 的代码,发现里面别有洞天。
BasicComboPopup 中的静态内部类 MouseGrabber 就是鼠标点击 ComboBox 之外区域隐藏弹出框的关键,它通过辅助类 MenuSelectionManager 的帮助,获取弹出菜单之外的父级面板组件,而后在这些组件上加上鼠标、键盘等相关的各种监听器(⊙﹏⊙b汗,加这么多……竟然也不会慢,太神奇了……),这些监听器会监控用户操作,一旦发现鼠标点击了 ComboBox 之外的区域,或者鼠标滚轮发生滚动等事件,就会调用可爱的方法 cancelPopupMenu() 让弹出框人间蒸发……
好家伙,这个 MouseGrabber 让我找的苦死了~~作者也藏得太深了~~
不过了解了 ComboBox 的这个玄机,其他的问题就不难解决了,我的弹出框借鉴这个思路,也可以继续完善了~~ :)
2010年3月19日21:55:21
此文后记:
后来一位热心的网友与我交流了许多,他寻到一篇网文让我参考,推荐的技巧是使用JPopupMenu来实现自定义下拉框的特性,在JPopupMenu中的面板里增加我们需要的各种组件,而后模拟JComboBox弹出框的操作方式。
希望对后来者能有些借鉴。
分享到:
相关推荐
Java 实现下拉列表 JComboBox 中值和显示不同 在 Java 中,实现下拉列表 JComboBox 中值和显示不同是一种常见的需求。下拉列表 JComboBox 是 Java 中的一种 GUI 组件,用于提供用户选择多个选项。通常情况下,我们...
Java Swing JComboBox 下拉列表框的示例代码 Java Swing JComboBox 下拉列表框是一种常用的 GUI 组件,它允许用户从多个选项中选择一个值。下面将详细介绍 JComboBox 的基本概念、常用构造方法、常用方法和示例代码...
Java的JComboBox是一个非常有用的组件,它允许用户在下拉列表中选择一个或多个选项。在GUI编程中,处理JComboBox的事件是提高用户交互性和应用程序功能的关键部分。本篇文章将深入探讨Java中JComboBox的事件处理机制...
在Java Swing库中,`JComboBox`是一种常用的组件,它提供了下拉列表的功能,用户可以选择列表中的一个选项或者自定义输入新的值。本教程将详细讲解如何在Java中创建一个可自行输入的`JComboBox`。 首先,我们需要...
Java `JComboBox` 是 Swing 组件库中的一个控件,用于在下拉列表中显示一组可选择的选项。它提供了一个简单的用户界面,允许用户从预定义的选项中进行单选。`JComboBox` 在 Java 图形用户界面(GUI)编程中非常常见...
在Java编程中,下拉列表通常被称为`JComboBox`,它是Swing库中的一个组件,用于提供一组可选的选项供用户选择。本篇将详细阐述如何在Java中使用`JComboBox`,并提供相关代码示例进行说明。 1. **JComboBox简介** `...
在Java Swing库中,`JComboBox`通常用于创建下拉列表,它允许用户从一组预定义的选项中选择一个。然而,默认情况下,`JComboBox`只支持单选操作。但根据你的需求,我们可以通过自定义组件来实现多选功能。在标题...
在IT行业中,自动显示下拉列表框是一种常见的交互设计,特别是在网页和桌面应用程序中,它极大地提升了用户体验。这里我们将深入探讨如何使用`ComboBox`控件实现这种功能,以实现类似百度搜索框的效果。 首先,`...
支持自动过滤可选项的JComboBox 支持键盘选择、鼠标选择
在Java编程语言中,下拉列表(Dropdown List)通常指的是`JComboBox`组件,它是Swing库中的一个关键部分,用于创建用户界面时提供选择项的控件。本实例13下拉列表主要探讨如何使用Java实现一个交互式的下拉菜单,让...
总结,这个实例展示了如何利用Java Swing的`JComboBox`结合`JDBC`技术,动态地从`SQL2000`数据库获取数据并显示在下拉列表中。通过监听用户的选择变化,可以实现灵活的数据交互。这种动态绑定数据的方法在各种需要与...
在Java编程中,创建具有图标的下拉列表可以极大地提升用户界面的美观度和用户体验。这一功能主要通过Swing库中的JComboBox组件实现,Swing是Java提供的一个用于构建图形用户界面(GUI)的工具包。下面将详细介绍如何...
当你需要在`JTable`的某一列中嵌入可选择的下拉列表时,`JComboBox`就派上了用场。在你的项目中,你可能遇到了一个问题:当`JComboBox`未被选中时,其下拉箭头没有正确显示。这个问题通常是由于`JTable`的默认渲染器...
在Java Swing库中,`JComboBox`和`JCheckBox`是两种常见的组件,它们分别用于创建下拉选择框和复选框。`JComboBox`提供了一个可扩展的列表,用户可以从中选择一个或多个选项,而`JCheckBox`则允许用户在一组选项中...
在Windows Forms应用开发中,`ComboBox`控件是常见的组件之一,用于实现下拉列表框的功能。本案例主要探讨如何使用C#语言来美化这个基本的控件,使其在用户界面设计上更具吸引力和用户体验。以下是一些关于`ComboBox...
在Java Swing框架中,`JComboBox`是一个非常重要的组件,它主要用于实现下拉列表的功能,常被用作用户输入的一种形式。本文将围绕如何在Swing组件`JComboBox`中获取下拉列表中的元素进行详细讲解。 #### 一、...
在Java Swing或JavaFX中,也有相似的JComboBox类用于创建下拉列表组件。 在实际应用中,多个COMBOBOX之间可能存在数据传递的需求。例如,一个ComboBox的选择可能会影响另一个ComboBox的显示内容。这通常通过事件...
1. **ComboBox控件**:ComboBox是Windows Forms中的一种常用控件,它结合了下拉列表和文本输入框的功能。用户可以在下拉列表中选择一个选项,或者在输入框中手动输入文本。 2. **颜色表示与处理**:在C#中,颜色...
在Java编程中,`JComboBox` 是Swing库中用于创建下拉选择框的组件,它允许用户从一组预定义的选项中进行选择。当需要为`JComboBox`添加图像时,可以创建自定义的组合框模型,将每个选项与对应的图片关联起来,以提供...
通过理解`ComboBoxModel`的工作原理以及如何与`JComboBox`进行交互,你可以创建出满足各种需求的下拉菜单。在实际项目中,根据具体需求,你可能还需要处理如数据加载、异步更新、用户输入验证等复杂情况。