`
nciky1984
  • 浏览: 19613 次
  • 来自: 0
文章分类
社区版块
存档分类
最新评论

如何编写自定义Swing组件(下)

阅读更多

UI Delegate
如果说模型接口是最编写自定义组件最重要的部分,那么UI delegate则是最复杂的部分。主要问题在于:如何编写绘制逻辑使得他在所有的look and feels上都一致?有时,除非你编写每个look and feels所对应的UI delegate(像 SwingX project 就是通过这种方式),否则是无法实现的。但是,在某些情况下你会发现你可以通过组装现有的swing组件来达到这种仿真的效果,在后面的部分,UI delegates代码将要注意那些平台相关的设置比如说颜色,字体和抗锯齿。


在"  Enhancing Swing Applications"一文中,作者描述了通过的继承定义好的look and feels的简单UI delegate实现的样板代码。以install*和unstall*方法开始,如果你不打算使用他们,第三方的look and feel 可能会在基本的功能基础上增加一些额外的功能(举个例子来说,在slider上增加鼠标滚轮滚动功能)


在我们这个例子中,我们可以看到这个自定义组件包含一个slider和一组labels(包括图标和文本),由于所有的JComponent都是容器类,我们可以轻松地通过在我们的installComponents方法中增加JSlider和JLabel(每个label是一个选项control point)组件来达到这种仿真的虚拟界面效果(别忘了在uninstallComponents方法中移除他们)。通过重用Swing核心组件的方式,我们的自定义组件能够使其在swing核心LAF和第三方LAF下都保持一致。


当我们增加附属组件时,为了在创建和缩放时定位这些附属组件,我们需要实现自定义的LayoutManager。这是一个非常简单的工作(甚至有点乏味):这些range在右侧纵向并排排列,相邻的range则根据其自身的weight值拥有相应空间的垂直区域,滑标则占有全部垂直空间,第一个和最后一个选项(control points)作为slider的起点和终点。


注意这个特殊的实现非常的困难并且几乎不可能使用单一的UI delegate来完成,举例来说,一些LAFs使用了native Api 来绘制各自的控制(像滑标的滑道与滑块)。一些第三方的LAF可能不遵循UIManager中的设置而是提供自己的颜色和自定义的Api


现在回到我们的实现(使用JSlider),我们现在面临一个有趣的问题:滑标可以通过设置snapToTicks的值来决定是否自动对齐到最近的滑块刻度。这个行为控制通过在BasicSliderUI delegate中安装mouse montion监听器实现。我们要怎么做?其中一个选择是移除这个监听器并且安装上我们所提供的实现。另一个方法是提供自定义的BoundedRangeModel实现,当设置非关联的range时修改它的值(value)。第一种方法并非最优-你无法信赖其他LAF下特殊的SliderUI delegate实现逻辑,有的实现甚至不会去调用父类的方法。第二种方法稍微好一点,不过我们选择另一种方法实现,原因稍后说明。


我们的实现对这些附属组件使用类似树/表的单元格渲染模式(Cell renderer),slider只是用来渲染并且不获取任何事件(参考CellRendererPane)。这能使我们从LAF绘图和鼠标自定义事件中获益。在我们这个特殊的例子中,如果用户在slider滑块外点击鼠标。我们通过直接设置相应的range的值(value)来代替原本的向鼠标点击方向滚动一个”块”,这就是我们为什么不使用前面提到的第二种方法的原因:我们自定义的鼠标监听器转换鼠标点击转换相应的range(相邻的或非关联的)并且设置他们的值,一旦这个唯一的监听器被安装到组件上(指这个CellRendererPane,而这个slider 只是一个”橡皮图章”),我们可以保证没有其他的监听器阻碍我们的代码。
最终的输出结果如图2.蓝色边框表示选项(control point)标签的绑定框(bounds)。红色边框表示单元格渲染器面板


 
图2:组件布局


倘若我们使用单元格渲染面板,我们需要覆盖掉它的paint方法来绘制真正的滑块。我们并没有绘制那些选项标签因为他是这个组件“真正的”子组件,注意滑块的绘制在一个单独的方法中完成,这样可以允许第三方的LAF只覆盖的这个滑块的绘制逻辑而不是改变整个绘制逻辑。

    @Override 
    public void paint(Graphics g, JComponent c) { 
        super.paint(g, c); 
        this.paintSlider(g); 
    } 

    protected void paintSlider(Graphics g) { 
        Rectangle sliderBounds = sliderRendererPane.getBounds(); 
        this.sliderRendererPane.paintComponent(g, this.slider, 
                this.flexiSlider, sliderBounds.x, sliderBounds.y, 
                sliderBounds.width, sliderBounds.height, true); 
    } 

测试应用程序
现在我们拥有了一个完整的自定义滑标组件,是时候该测试它了。这个测试应用程序创建了一个滑标,它包含一些相邻的和非关联的range,并为其注册了改变监听器(change listener)。一旦发生改变事件,我们计算图标的尺寸比例并绘制它(该图标使用Tango Desktop Project的SVG-to-Java2D converte来转换,具体参考  Transcoding SVG to Pure Java2D code一文).图3显示了这个应用程序在不同的图标大小下的运行效果。



 
图3,选择不同值的运行效果


图4显示了在不同look and feels下的滑标,从左到右,这些 LAF为:Windows (core), Metal (core), Motif (core), Liquid (third party), 和 Napkin (third party).如你所见,这个新组件提供了和当前所设置的LAF一致的外观。


 
图4。在不同look and feel 下的自定义滑标
结尾

现在要何去何从?阅读Swing核心组件的代码。下载并学习开源组件的源代码(像SwingX 或Flamingo),然后开始构造你自己梦想中组件吧!

 

 资源

Kirill Grouchnikov has been writing software since he was in junior high school, and after finishing his BSc in computer science, he happily continues doing it for a living. His main fields of interest are desktop

 

  • 大小: 49.1 KB
  • 大小: 67.8 KB
  • 大小: 4.8 KB
分享到:
评论

相关推荐

    自定义Swing组件代码

    本主题主要关注如何自定义Swing组件,以便满足特定需求或实现独特功能。下面我们将深入探讨自定义Swing组件的基本概念、步骤以及相关知识点。 一、Swing组件基础 Swing组件是构建GUI的基础,包括按钮(JButton)、...

    swing自定义JTabbedPane组件外观

    总之,自定义`JTabbedPane`外观涉及的主要知识点包括:Swing组件模型、UI设计模式、可绘制组件、布局管理和API的使用。通过理解和实践这些概念,开发者可以创建出满足特定需求的、具有独特外观的`JTabbedPane`组件。

    swing组件介绍(一)

    6. **可定制性**:Swing组件高度可定制,可以通过设置外观(LookAndFeel)来改变组件的视觉样式,甚至实现自定义的外观。 7. **组件扩展**:Swing允许开发者通过继承现有的组件类并重写其方法来自定义组件,从而...

    java基于Swing组件的GUI设计

    在"java基于Swing组件的GUI设计"这个主题中,我们将深入探讨如何利用Swing进行GUI开发。 首先,Swing组件是轻量级的,它们大部分是用Java实现的,这使得Swing应用程序可以在不同的操作系统上保持一致的外观和行为。...

    swing组件的详细介绍

    【Swing组件详解】 Swing是Java编程语言中用于创建图形用户界面(GUI)的一个库,它是Java Foundation Classes (JFC)的一部分。在早期的Java版本(如JDK 1.0和1.1)中,Abstract Window Toolkit (AWT)是主要的GUI...

    Swing 扩展组件 Swing 扩展组件

    Swing扩展组件是Java Swing库中的一...同时,Swing组件的事件处理机制和模型-视图-控制器(MVC)设计模式也为程序的可维护性和可扩展性提供了保障。因此,深入理解和使用Swing扩展组件对于Java GUI开发者来说至关重要。

    swing 组件 demo

    此外,Swing组件还支持事件处理,通过实现EventListener接口或使用匿名内部类,可以编写代码来响应用户的操作,如按钮点击、文本输入等。 总结来说,"Swing组件demo"涵盖了Swing GUI开发中的基本元素和功能,通过...

    几个漂亮的SWING组件(源代码)

    标题提到的"几个漂亮的SWING组件(源代码)"很可能是包含了一些自定义或者美化过的Swing组件示例,供开发者参考学习。 在Swing组件库中,有许多基础和高级组件,包括但不限于: 1. **JFrame**: 这是大多数Swing...

    swing各个组件实例演示

    本教程将深入探讨Swing组件的实例应用,帮助开发者更好地理解和掌握Swing在实际编程中的运用。 一、Swing组件基础 Swing组件主要由JComponent类及其子类构成,包括按钮(JButton)、文本框(JTextField)、标签...

    Swing 组件大全

    综上所述,"Swing组件大全"不仅涵盖了Swing库中的所有核心组件,还涵盖了数据库操作、Excel文件处理和自定义布局管理,是学习和开发Swing应用的宝贵资源。通过深入理解和实践这些知识点,开发者可以构建出功能强大且...

    j2ee的应用-swing组件介绍

    在J2EE环境下,Swing组件通常用于构建客户端应用程序,这些应用程序可以与服务器进行交互,处理用户输入,显示数据,或者执行业务逻辑。例如,你可以使用Swing来创建一个简单的登录界面,用户输入用户名和密码后,...

    swing中自定义对话框的几种实际用法

    Swing是Java编程环境中用于构建图形用户界面(GUI)的一个重要工具包,它提供了丰富的组件和功能,使得开发者能够创建出美观且功能强大的桌面应用程序。在Swing中,对话框是一种特殊的窗口,用于向用户提供临时信息...

    Swing组件教案及示例程序

    这个“Swing组件教案及示例程序”压缩包文件显然包含了关于如何使用Swing来创建丰富的桌面应用程序的教学材料和实际示例。Swing提供了一套组件,如按钮、文本框、菜单等,使得开发者能够构建出美观且功能丰富的应用...

    Java Swing'组件集合

    本篇文章将深入探讨Java Swing组件集合,帮助初学者更好地理解和使用这些组件。 首先,Swing 提供了丰富的组件集,包括按钮(JButton)、文本框(JTextField)、标签(JLabel)、复选框(JCheckBox)、单选按钮...

    java Swing用户界面组件

    Swing组件库是基于Java AWT(Abstract Window Toolkit)的,但相比AWT,Swing组件是轻量级的,它们不依赖于操作系统提供的图形组件,这使得Swing应用具有更好的跨平台兼容性。Swing还提供了一些AWT不具备的特性,如...

    swing自制组件(一)

    总的来说,"swing自制组件(一)"这个主题是关于Java Swing编程中的组件扩展,通过分析"RichJLabel.java"我们可以深入理解Swing组件的自定义机制,并学习到如何利用Java Swing创建具有特殊功能的用户界面元素。...

    基于Java的开源的Swing组件 JIDE.zip

    **Java Swing组件与JIDE库** Java Swing是Java标准版(Java SE)的一部分,它提供了一组用于构建桌面应用程序的用户界面组件。Swing库基于Java AWT(Abstract Window Toolkit),但提供了更丰富的特性和更好的跨...

    Java Swing自定义观感(仅以自定义treeUI为例)

    Java Swing是Java GUI编程的重要工具,它提供了丰富的组件和接口,允许开发者构建用户界面。"Look and Feel"(观感)是Swing中一个关键的概念,它决定了应用程序的视觉样式和交互体验。Java Swing默认提供了多种观感...

    基于java的开源的Swing组件 JIDE.zip

    Java Swing组件库JIDE是一个强大的开发工具,专为Java开发者设计,用于构建功能丰富的桌面应用程序。JIDE提供了许多预构建的、高度可定制的Swing组件,极大地扩展了标准Java Swing的功能。这个开源项目旨在简化GUI...

Global site tag (gtag.js) - Google Analytics