《Java 2 图形设计卷Ⅱ- SWING》第3章 Swing组件的体系结构
第3章 Swing组件的体系结构
new Intger(oldMin),new Integer(minimum));
}
JSlider.setMinimum()在设置最小值后激发一个属性变化事件。组件模型的所有属性(一个滑杆的最小值和最大值)都应该激发属性变化事件。
2.传送模型事件
Swing组件还把模型事件传送给一个已向组件登记过的监听器。例如,一个滑杆作为一个变化监听器向其模型登记。当这个滑杆的模型激发了一个变化事件时,这个滑杆接着把一个变化事件发送给自己的变化监听器。JSlider类实现一个变化监听器,它只把一个状态变化事件发送给滑杆的变化监听器。与组件UI一样,JSlider等组件类常常在内部类中封装事件处理。
下面列出了大大简化了的JSlider类进行监听的代码,其中说明了滑杆把状态变化发送给它们的监听器以响应模型状态的变化的方法(与其他Swing组件类的处理方法类似)。
panel.add(slider);
panel.add(readOut);
contentPane.add(panel,BorderLayout.NORTH);
contentPane.add(imageView,BorderLayout.CENTER);
model.addChangeListener(new ReadOutSynchronizer());
}
...
这个小应用程序的变化监听器对模型变化作出反应,它更新显示图像比例的readOut标签。此后还调用了这个标签的revalidate方法,以便这个标签重新布局和重画。有关revalidate方法的更多信息,请参见4.3.5节“Validate、Invalidate和Revalidate方法”。
...
class ReadoutSynchronizer implements ChangeListener{
public void stateChanged(ChangeEvent e){
String s= Integer.toString(model.getValue());
readOut.setText(s + "%");
readOut.revalidate();
}
}}
例3-1 一个带多个视图的模型
</applet>
<hr>
例3-2一个滑杆的轻量通知
SomeType newValue = (SomeType)e.getNewValue();
//act upon new value...
}
}
图3-10所示的应用程序用一个树和一个用于设置该树的rootVisible属性的复选框举例说明了处理模型属性变化事件。如果rootVisible属性是true,则树的根节点是可视的,否则,根节点是隐藏的。
----
图3-10 模型属性变化通知(当下载对话框出现时,可直接点击打开按钮试试)
----
这个应用程序实现一个属性变化监听器,该监听器在树的rootVisible属性修改时,显示一个消息对话框。
e.getNewValue().toString();
例3-3 处理模型属性变化通知
e.getNewValue().toString();
static private ResourceBundle resources;
new Class[]{acClass})
put(uiClass,m);
}
uiObject = m.invoke(null,new object[]{target});
}
catch (NoSuchMethodException e){
getUIError(" static createUI() method not"+
" found in"+ uiClass);
}
catch(Exception e){
getUIError(" createUI() failed for"+ target +
" "+e);
}
}
return(ComponentUI) uiObject;
}
UIDefaults.getUI()必须能够实例化任何类型的UI代表。例如,如果当前的界面样式是Java的界面样式,则必须为滑杆实例化MetalSliderUI实例;如果当前的界面样式是Windows的界面样式,则必须为滑杆实例化WindowsSliderUI实例,等等。另外,UIDefaults.getUI()还必须能够实例化那些将开发出来的UI代表实例。显然,用new语句来实例化UI代表不是一个可行的选择。
为了实例化任何类型的UI代表,UIDefaults.getUI()使用了Java的反射功能。UIDefaults.getUI()以一个对组件的引用(UI代表就是为这个组件的而创建的)作为参数。再用这个组件来获得对这个UI代表类的引用。
有了UI代表类,再把反射功能用于获得对UI代表的static createUI方法的一个引用,然后再用Method.invoke()来调用这个方法(用这个组件作为参数)。所有UI代表实现一个 static createUI方法,该方法返回一个对UI代表的引用。下面介绍有关createUI方法的更多信息。
例3-4 一个定制的UI代表
例3-5 一个定制监听器的实现
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
final JSlider slider = new JSlider();
final JCheckBox checkBox = new JCheckBox("Annotate");
slider.setUI(new AnnotatedSliderUI(slider));
contentPane.setLayout(new FlowLayout());
contentPane.add(checkBox);
contentPane.add(slider);
checkBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean selected = checkBox.isSelected();
slider.putClientProperty(
AnnotatedSliderUI.ANNOTATE_PROPERTY,
selected ? Boolean.TRUE : Boolean.FALSE);
slider.repaint();
}
});
}
}
class AnnotatedSliderUI extends BasicSliderUI {
public static String ANNOTATE_PROPERTY =
"AnnotatedSliderUI.annotate";
boolean annotate = false;
public AnnotatedSliderUI(JSlider slider) {
super(slider);
}
public Dimension getPreferredSize(JComponent c) {
Dimension d = super.getPreferredSize(c);
return new Dimension(d.width,d.height+20);
}
public void paint(Graphics g, JComponent c) {
if(annotate) {
JSlider slider = (JSlider)c;
int v = slider.getValue();
g.setColor(UIManager.getColor("Label.foreground"));
g.setFont(new Font("Dialog", Font.PLAIN, 28));
g.drawString((new Integer(v)).toString(),10,33);
}
super.paint(g,c);
}
protected PropertyChangeListener
createPropertyChangeListener(JSlider slider) {
return new AnnotatePropertyListener();
}
protected class AnnotatePropertyListener
extends BasicSliderUI.PropertyChangeHandler {
public void propertyChange(PropertyChangeEvent e) {
System.out.println("property changed");
super.propertyChange(e);
String name = e.getPropertyName();
if(name.equals(ANNOTATE_PROPERTY)) {
System.out.println("property changed");
if(e.getNewValue() != null) {
annotate =
((Boolean)e.getNewValue()).booleanValue();
}
}
}
}
}
3.3 本章回顾
?略