在前面的章节中,我们了解了当在屏幕没有足够的空间显示完整的组件时,JScrollPane如何提供了一个可滚动的区域。Swing同时提供了其他的一些支持某种滚动类型或是边界范围值显示的组件。这些可用的组件有JScrollBar,JSlider,JProgressBar,以及更为有限角度的JTextField。这些组件共享BoundedRangeModel作为他们的数据模型。Swing类所提供的这种数据模型的默认实现是DefaultBoundedRangeModel类。
在本章中,我们将会了解这些Swing组件的类似与不同之处。我们的讨论由共享的数据模型BoundedRangeModel开始。
12.1 BoundedRangeModel接口
BondedRangeModel接口是本章中描述的组件所共享的MVC数据模型。这个接口包含了描述范围值minimum, maximum, value, extent所必须的四个交互关联的属性。
minimum与maximum属性定义了模型值的范围。value属性定义了我们所认为的模型的当前设置,而value属性的最大值并不一定是模型的maximum属性值。相反,value属性可以使用的最大设置是小于extent属性的maximum属性。为了有助于我们理解这些属性,图12-1显示了这些设置与JScollBar的关系。extent属性的其他目的依赖于作为模型视图的属性。
四个属性的设置必须满足下列关系:
minimum <= value <= value+extent <= maximum
当一个设置发生变化时,也许就会触发其他设置的变化,以满足上面的大小关系。例如,将minimum修改为当前value加上extent与maximum之间的一个设置会使得减少extent并且增加value来保持上面的大小关系。另外,原始属性的变化会导致修改为一个新设置而不是所请求的设置。例如,尝试将value设置为小于minimum或是maximum会将value设置为最接近范围极限的值。
BoundedRangeModel接口的定义如下:
public interface BoundedRangeModel {
// Properties
public int getExtent();
public void setExtent(int newValue);
public int getMaximum();
public void setMaximum(int newValue);
public int getMinimum();
public void setMinimum(int newValue);
public int getValue();
public void setValue(int newValue);
public boolean getValueIsAdjusting();
public void setValueIsAdjusting(boolean newValue);
// Listeners
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
// Other Methods
public void setRangeProperties(int value, int extent, int minimum,
int maximum, boolean adjusting);
}
尽管模型可用的不同属性设置是JavaBean属性,当属性设置发生变化时,接口使用Swing的ChangeListener方法而不是java.beans.PropertyChangeListener。
当用户正在执行一系列的模型快速变化时,也许是在屏幕上拖动滑块所造成的,模型的valueIsAdjusing属性就派上用场了。对于某些只对何时设置模型的最终值感兴趣的人,在getValueIsAdjusting()返回false之前监听器会忽略所有的改变。
12.2 DefaultBoundedRangeModel类
实际实现BoundedRangeModel接口的Swing类是DefaultBoundedRangeModel。这个类会小心处理为了保证不同属性值的相应顺序所必需的调整。他同时管理ChangeListener列表在模型发生变化时通知监听器。
DefaultBoundedRangeModel有两个构造函数:
public DefaultBoundedRangeModel()
public DefaultBoundedRangeModel(int value, int extent, int minimum, int maximum)
无参数版本会将模型的minimum, value与extent属性设置为0。余下的maximum属性设置为100。
第二个构造函数版本需要四个整形参数,显式设置四个属性。对于这两个构造函数,valuesAdjusting属性的初始值均为false,因为模型值在初始值之外并没有发生变化。
注意,除非我们在多个组件之间共享模型,通常并没有必要创建BoundedRangeMode。如果我们要在多个组件之间共享模型,我们可以创建第一个组件,然后获取其BoundedRangeModel模型进行共享。
类似于通常的管理其监听器列表的所有类,我们可以向DefaultBoundedRangeModel查询赋给他的监听器。这里我们可以使用getListeners(ChangeListener.class)方法获取模型的ChangeListener列表。这会返回一个EventListener对象数组。
12.3 JScrollBar类
最简单的边界范围组件是JScrollBar。JScrollBar组件用在我们在第11章所描述的JScrollPane容器中来控制滚动区域。我们也可以将这个组件用在我们自己的容器中,尽管由于JScrollPane的灵活性,通常并不必需这样做。然而关于JScrollBar我们需要记住的一点就是JScrollPane并用于值,而是用于屏幕的滚动区域。对于值,我们要使用在下节将要讨论的JSlider组件。
注意,JScrollPane中的JScrollBar实际是上是JScrollBar的一个特殊子类,他能够正确处理实现了Scrollable接口的可滚动组件。尽管我们可以修改JScrollPane的滚动条,但是通常并不需要这样做,而且所需要工作比我们认为要多得多。
如图12-2所示,水平的JScrollBar由几部分组成。由中间开始向前,我们可以看到滚动条的滑块。滑块的宽度是BoundedRangeModel的extent属性。滚动条的当前值是滑块的左边。滑块的左边与右边是块翻页区域。点击滑块的左边并减少滚动条的值,而点击右边会增加滚动条的值。滑块增加或减少的数量值是滚动条的blockIncrement属性。
在滚动条的左边与右边是箭头按钮。当点击左箭头时,滚动条会减少一个单元。滚动条的unitIncrement属性指定了这个单元。通常情况,这个值为1,尽管并不是必须这样。在左箭头的右边是滚动条的最小值与模型。除了用左箭头减少值以外,点击右箭头会使得滚动条增加一个单元。右箭头的左边是滚动条的最大范围。最大值实际上略远于左边,这里略远的距离是由模型的extent属性来指定的。当滑块紧邻右箭头时,这会将滚动条的滚动动条值放在滑块的左边,对于所有其他的位置也是如此。
垂直JScrollBar是由与水平JScrollBar相同的部分组成的,最小值与减少部分位顶部,而且值是由滚动条滑块的上边决定的。最小值与增加部分位于底部。
正如前面所提到的,JScrollBar模型是BoundedRangeModel。用户界面的委托是ScrollBarUI。
现在我们已经了解了JSrollBar的不同部分,现在我们来了解一下如何使用。
12.3.1 创建JScrollBar组件
JScrollBar有三个构造函数:
public JScrollBar()
JScrollBar aJScrollBar = new JScrollBar();
public JScrollBar(int orientation)
// Vertical
JScrollBar aJScrollBar = new JScrollBar(JScrollBar.VERTICAL);
// Horizontal
JScrollBar bJScrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
public JScrollBar(int orientation, int value, int extent, int minimum, int maximum)
// Horizontal, initial value 500, range 0-1000, and extent of 25
JScrollBar aJScrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 500, 25, 0, 1025);
使用无参数的构造函数会使用默认的数据模型创建一个垂直滚动条。模型的初始值为0,最小值为0,最大值为100,而扩展值为10。这个默认模型只提供了0到90的范围。我们可以显示的将方向设置为JScrollBar.HORIZONTAL或是JScrollBar.VERTICAL。如果我们不喜欢其他两个构造函数所提供的初始模型设置,我们需要自己进行显示的设置。如果数据元素没有正确的进行约束,正如前面关于BoundedRangeModel所描述的,则会抛出一个IllegalArgumentException,使得JScrollBar构造中断。
很奇怪没有出现在构造函数列表中的接受BoundedRangeModel参数的构造函数。如果我们有一个模型实例,我们可以在创建了滚动条之后调用setModel(BoundedRangeModel newModel)方法或是在创建构造函数时由模型获取单个属性,如下所示:
JScrollBar aJScrollBar =
new JScrollBar (JScrollBar.HORIZONTAL, aModel.getValue(), aModel.getExtent(),
aModel.getMinimum(), aModel.getMaximum())
由J2SE平台的1.3版本开始,滚动条不再参与焦点遍历。
12.3.2 处理滚动事件
一旦我们创建了JScrollBar,如果我们对滚动条的值何时发生变化感兴趣,则我们需要监听这些变化。有两种监听的方法:AWT 1.1事件模型方法以及Swing MVC方法。AWT方法涉及到将AdjustmentListener关联到JScrollBar。MVC方法涉及到将ChangeListener关联到数据模型。每一种方法都可以工作得很好,如果模型通过编程变化或是用户拖动滚动条滑块,两种方法都会得到通知。后一种方法提供了更多的灵活性,因而是一个不错的选择,除非我们是在多个组件之间共享数据模型并且需要知道哪一个组件修改了模型。
使用AdjustmentListsener监听滚动事件
将AdjustmentListener关联到JScrollBar使得我们可以监听用户修改滚动条设置。下面的代码片段,将会用在稍后的列表12-3中,显示了为了监听用户修改JScrollBar的值,我们如何将AdjustmentListsener关联到JScrollBar。
首先,定义简单输出滚动条当前值的AdjustmentListsener:
AdjustmentListener adjustmentListener = new AdjustmentListener() {
public void adjustmentValueChanged (AdjustmentEvent adjustmentEvent) {
System.out.println ("Adjusted: " + adjustmentEvent.getValue());
}
};
在我们创建了监听器之后,我们可以创建组件并且关联监听器:
JScrollBar oneJScrollBar = new JScrollBar (JScrollBar.HORIZONTAL);
oneJScrollBar.addAdjustmentListener(adjustmentListener);
这种监听修改事件的方法可以工作得很完美。然而,我们也许会更喜欢将ChangeListener关联到数据模型。
使用ChangeListener监听滚动事件
将ChangeListener关联到JScrollBar数据模型会在我们的程序设计中提供更多的灵活性。使用AWT AdjustmentListener,只有滚动条的值发生变化时监听器才会得到通知。另一方面,当最小值,最大值,当前值,以及扩展值发生变化时,所关联的ChangeListener会得到通知。另外,由于模型有一个valueIsAdjusting属性,我们可以选择忽略即时变化事件-一些我们可以使用AdjustmentListener,通过Adjustment中相同名的属性处理的事件。
为了进行演示,定义了一个当模型完成调整时输出滚动条当前值的ChangeListener,如列表12-1所示。我们可以通过本章来加强BoundedChangeListener类。
package swingstudy.ch11;
import javax.swing.BoundedRangeModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class BoundedChangeListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent event) {
// TODO Auto-generated method stub
Object source = event.getSource();
if(source instanceof BoundedRangeModel) {
BoundedRangeModel aModel = (BoundedRangeModel)source;
if(!aModel.getValueIsAdjusting()) {
System.out.println("Changed: "+aModel.getValue());
}
}
else {
System.out.println("Something changed: "+source);
}
}
}
一旦我们创建了监听器,我们也可以创建组件并且关联监听器。在这个特定的例子中,我们需要将监听器关联到组件的数据模型,而不是直接关联到组件。
ChangeListener changeListener = new BoundedChangeListener();
JScrollBar anotherJScrollBar = new JScrollBar (JScrollBar.HORIZONTAL);
BoundedRangeModel model = anotherJScrollBar.getModel();
model.addChangeListener(changeListener);
列表12-2显示了测试程序的源码。
package swingstudy.ch11;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import javax.swing.BoundedRangeModel;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.event.ChangeListener;
public class ScrollBarSample {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Runnable runner = new Runnable() {
public void run() {
AdjustmentListener adjustmentListener = new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent event) {
System.out.println("Adjusted: "+event.getValue());
}
};
JScrollBar oneJScrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
oneJScrollBar.addAdjustmentListener(adjustmentListener);
ChangeListener changeListener = new BoundedChangeListener();
JScrollBar anotherJScrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
BoundedRangeModel model = anotherJScrollBar.getModel();
model.addChangeListener(changeListener);
JFrame frame = new JFrame("ScrollBars R US");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(oneJScrollBar, BorderLayout.NORTH);
frame.add(anotherJScrollBar, BorderLayout.SOUTH);
frame.setSize(300, 200);
frame.setVisible(true);
}
};
EventQueue.invokeLater(runner);
}
}
当运行这个程序时,他会显示两个水平滚动条,如图12-3所示。移动滚动条的输出发送到终端容器。
12.3.3 JScrollBar属性
在我们创建了JScrollBar之后,修改其底层数据模型就变得必要了。我们可以使用public BoundedRangeModel getModel()方法获得模型,然后直接修改模型。更可能的,我们仅需要调用组件的相应方法:
• setValue(int newValue), setExtent(int newValue), setMinimum(int newValue)
• setMaximum(int newValue)
注意,尽管支持,但是并不推荐在显示组件之后修改JScrollBar方向。这会极大的影响用户的满意度并且使得用户去寻找其他的解决方案。
除了数据模型属性,表12-1显示了JScrollBar的16个属性。
12.3.4 自定义JScrollBar观感
每一个可安装的Swing观感都提供了不同的JScrollBar外观以及默认的UIResource值集合。图12-4显示了预安装的观感类型Motif,Windows,以及Ocean的JScrollBar组件的外观。
表12-2显示了JScrollBar的UIResource相关属性集合。有28个不同的属性。
分享到:
相关推荐
在计算机科学与材料科学的交叉领域,有一种用于模拟和分析多晶材料结构的方法,它涉及到“Polytope-bounded-Voronoi-diagram”(多面体边界Voronoi图)。这个标题中的“master_QC_wheelgy7_polygrain_gr”可能是指一...
在Android开发中,Bounded Service是一种特殊的服务类型,它允许客户端(通常是一个Activity或BroadcastReceiver)与服务建立连接,并通过接口直接交互。Bounded Service的生命周期与客户端紧密关联,当客户端不再...
### Java Swing:Bounded Range Components概述 在Java Swing框架中,`JScrollBar`、`JSlider` 和 `JProgressBar` 这三个组件被用来提供在有限区间内的可视化和选择功能。这些组件允许用户方便地从该区间内选择一个...
为了解决上述问题,本文提出了一种新的构建方法——快速KD树构建算法(Fast kd-tree Construction with an Adaptive Error-Bounded Heuristic),该算法能够在保持较高质量的同时,大幅度提升构建速度,使之适用于...
C Bounded Model Checker,简称CBMC,是一种针对C语言程序的静态分析工具,它采用了模型检查的技术来查找程序中的潜在错误。模型检查是形式验证的一种方法,它试图在程序执行的有限步数内找到错误,比如内存泄漏、...
标题中的"spdlog-master.rar_mpmc_bounded_q.h_spdlog"暗示了这是一个关于`spdlog`日志库的源代码压缩包,其中包含了`mpmc_bounded_q.h`这个特定的队列数据结构的实现。`spdlog`是一个在C++11环境下广泛使用的高性能...
Time-bounded Localization Algorithm based on Distributed Multidimensional Scaling for Wireless Sensor Networks
针对这一问题,ANSI-C Bounded Model Checker(简称CBMC)应运而生。 #### 二、Bounded Model Checking (BMC) 技术简介 **BMC**是一种形式化验证技术,它通过将状态机的转换关系和规范联合展开成一个布尔公式,并...
3. 有界性(Bounded Property):这是对插值函数值的一种限制,确保在插值区域内,函数值不会因为参数的变化而出现无限大的情况。 4. 点控制(Point Control):这是指在不改变整体插值数据的前提下,通过参数调整...
"bounded-mpmc-queue" 指的是一个有限大小的多生产者多消费者(Multi-Producer Multi-Consumer, MPMC)队列实现,它使用了 Rust 编程语言。队列是一种数据结构,允许在一个或多个生产者线程和一个或多个消费者线程...
生产者消费者问题(Bounded-Buffer Problem)是操作系统中一种典型的多线程同步问题,它模拟了一个场景,其中生产者线程生成数据并将数据放入一个有限大小的缓冲区,而消费者线程则从缓冲区中取出数据进行消费。...
### Delay-range-dependent Robust Stability Criteria for Uncertain Neutral-type Lur'e Systems with Sector-bounded Nonlinearities #### 引言 时滞系统稳定性分析是控制理论领域的重要研究课题之一,尤其在...
【标题】"Sarunas-Girdenas-Bounded_Memory-archive-refs-heads-master.zip" 提供的是一项关于有限内存管理的项目,很可能是一个研究或工程实践的代码库。这个压缩包可能包含了Sarunas Girdenas针对有限内存环境进行...
在本压缩包“yolov8系列--GUI for marking bounded boxes of objects in imag.zip”中,包含的是一个用于图像目标检测的图形用户界面(GUI)工具。这个工具主要用于在图像上标注物体的边界框,是训练对象检测模型如...
在数学分析领域,有界平均振荡(BMO)是研究函数局部行为的一个重要概念,尤其在调和分析、复分析以及偏微分方程等领域有着广泛的应用。本文将详细介绍BMO的基本定义、主要性质以及它与Hardy空间\(H^1\)之间的关系。 ...
为了解决这个问题,文档提出了一种基于误差界定线性模式的双向聚类方法(Error-bounded Bi-clustering,简称EB)。该方法在合成控制数据集和酵母细胞周期数据集上的广泛实验验证了其效果。实验结果表明,EB方法在...
有界的Voronoi演示该存储库包含Mapsense有界Voronoi演示的示例数据,以及将创建有界Voronoi图的python脚本(voronoi.py)和Jupyter笔记本(Voronoi.ipynb)。依存关系: numpy >= 1.9.2scipy >= 0.15.1shapely >= ...