`
mylxiaoyi
  • 浏览: 327595 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

弹出窗口与选择器(四)

 
阅读更多

9.4 JColorChooser类

我们可以将JColorChooser认为是一个只可以输入的JOptionPane,其输入域要求我们选择一种颜色。与JOptionPane类似,JColorChooser也仅是位于窗口中的一堆组件,而并不是一准备好用来使用的弹出窗口。图9-18显示在了我们自己的程序窗口中JColorChooser的样子。在顶部是三个可选择的颜色选择面板;在底部是一个预览面板。其中“I Love Swing”并不是选择器的一部分,而包含选择器的程序所有的。

Swing_9_18

除了可以在我们的程序窗口显示以外,JColorChooser同时也为自动放置在JDialog的组件集合中提供了支持方法。图9-19显示了一个以这种方式自动创建的弹出窗口。

Swing_9_19

为了支持这种行为,JColorChooser需要位于javax.swing.colorchooser包中的一些支持类的帮助。JColorChooser的数据模型是ColorSelectionModel接口的一种实现。javax.swing.colorchooser包提供了DefaultColorSelectionModel类作为ColorSelectionModel接口的实现。对于用户界面,JColorChooser依赖ColorChooserComponentFactory来创建选择颜色的默认面板。这些面板是AbstractColorChooserPanel类的特殊子类,如果我们不喜欢默认的集合,我们也可以自己创建。

默认情况下,当在一个JColorChooser中有有多个选择器面板时,每一个面板显示在JTabbedPane的一个标签上。然而,ColorChooserUI可以以他要求的任何方式处理多个面板。

9.4.1 创建JColorChooser

如果我们希望创建一个JColorChooser,并且将其放在我们自己的窗口,我们可以使用下列JColorChooser类的三个构造函数中的一个:

public JColorChooser()
JColorChooser colorChooser = new JColorChooser();
 
public JColorChooser(Color initialColor)
JColorChooser colorChooser = 
  new JColorChooser(aComponent.getBackground());
 
public JColorChooser(ColorSelectionModel model)
JColorChooser colorChooser = new JColorChooser(aColorSelectionModel);

默认情况下,选择器的初始颜色为白色。如果我们不希望白色作为默认颜色,我们可以使用Color对象或是ColorSelectionModel来提供初始颜色。

9.4.2 使用JColorChooser

一旦我们应用构造函数创建了一个JColorChooser,我们可以将其放在任何容器中,类似于其他的组件。例如,列表9-7所示的源码创建了一个前面图9-18所示的GUI。

package swingstudy.ch09;
 
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
 
import javax.swing.BorderFactory;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
 
public class ColorSample {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		Runnable runner = new Runnable() {
			public void run() {
				JFrame frame = new JFrame("JColorChooser Popup");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
				final JLabel label = new JLabel("I Love Swing", JLabel.CENTER);
				label.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 48));
				frame.add(label, BorderLayout.SOUTH);
 
				final JColorChooser colorChooser = new JColorChooser(label.getBackground());
				colorChooser.setBorder(BorderFactory.createTitledBorder("Pick Foreground Color"));
 
				frame.add(colorChooser, BorderLayout.CENTER);
 
				frame.pack();
				frame.setVisible(true);
			}
		};
 
		EventQueue.invokeLater(runner);
	}
 
}

尽管上面的代码创建了GUI,但是在JColorChooser中选择不同的颜色并不会做任何事情。下面我们看一下使得颜色变化的代码。

监听颜色选择变化

JColorChooser使用ColorSelectionModel作为其数据模型。正如下面的接口定义所示,数据模型只包含一个属性,selectedColor,用来管理颜色选择器的状态。

public interface ColorSelectionModel {
  // Listeners
  public void addChangeListener(ChangeListener listener);
  public void removeChangeListener(ChangeListener listener);
  // Properties
  public Color getSelectedColor();
  public void setSelectedColor(Color newValue);
}

当用户改变了JColorChooser中的颜色,selectedColor属性发生变化,并且JColorChooser生成一个ChangeEvent来通知所注册的ChangeListener对象。

所以,要完成前一节中的ColorSample示例,并且当用户修改JColorChooser中的颜色选择时使得标签的前景色发生变化,我们需要向颜色选择器注册一个ChangeListener。这涉及到创建一个ChangeListener并将其添加到ColorSelectionModel中。将列表9-8中所示的代码添加到前面的9-7代码中的相应位置。

ColorSelectionModel model = colorChooser.getSelectionModel();
    ChangeListener changeListener = new ChangeListener() {
      public void stateChanged(ChangeEvent changeEvent) {
        Color newForegroundColor = colorChooser.getColor();
        label.setForeground(newForegroundColor);
      }
    };
    model.addChangeListener(changeListener);

一旦添加了这段代码,这个示例就完成了。运行这个程序会出现图9-18所示的颜色选择器,并且选择一个新的地修改标签的前景色。

创建并显示一个JColorChooser弹出窗口

尽管前面的例子对于如果我们仅是希望在我们程序中包含一个JColorChooser的情况来说已经足够了,但是更多的时候,我们希望JColorChooser在一个单独的弹出窗口中显示。这个窗口看起来像是我们在屏幕上选择一个按钮或者是选择一个菜单项目的结果。为了支持这种行为,JColorChooser包含下列的工厂方法:

public static Color showDialog(Component parentComponent,
  String title, Color initialColor)

当调用这个方法时,showDialog()会使用指定的父组件与标题创建一个模态对话框。在这个对话框中是一个给定了初始颜色值的JColorChooser。正如我们可以在图9-18中所看到的,在底部是三个按钮:OK,Cancel与Rest。当OK按钮被按下时,弹出窗口会消失,而showDialog()方法会返回当前选中的颜色值。当Cancel按钮被按下时,此方法会返回null,而不会返回所选择的颜色值或是初始颜色值。Reset按钮的选择会使得JColorChooser将其所选中的颜色修改为在启动时所提供的初始颜色。

showDialog()方法的通常作用过程是其初始颜色参数是一个对象的某个颜色属性。然后方法调用的返回值变为相同颜色属性的新值。这种模式用法显示在下面的代码行中,其中颜色属性的变化是一个按钮的背景颜色属性值。类似于JOptionPane,null父组件参数会使得弹出窗口位于屏幕的中间,而不是重叠在某个特定的组件之上。

Color initialBackground = button.getBackground();
Color background = JColorChooser.showDialog(
  null, "Change Button Background", initialBackground);
if (background != null) {
  button.setBackground(background);
}

可以将这段代码放在完整的示例程序中,列表9-9显示了这样的一个示例程序,其中提供了一个按钮,当选中时会显示一个JColorChooser。在OK按钮被选中之后颜色选择器中选中的颜色变为按钮的背景色。

package swingstudy.ch09;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
 
public class ColorSamplePopup {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		Runnable runner = new Runnable() {
			public void run() {
				JFrame frame = new JFrame("JColorChooser Sample Popup");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
				final JButton button = new JButton("Pick to Change Background");
 
				ActionListener actionListener = new ActionListener() {
					public void actionPerformed(ActionEvent event) {
						Color initialBackground = button.getBackground();
						Color background = JColorChooser.showDialog(null, "Change Button Background", initialBackground);
						if(background != null) {
							button.setBackground(background);
						}
					}
				};
 
				button.addActionListener(actionListener);
 
				frame.add(button, BorderLayout.CENTER);
 
				frame.setSize(300, 100);
				frame.setVisible(true);
			}
		};
 
		EventQueue.invokeLater(runner);
	}
 
}

提供我们自己的OK/Cancel事件监听器

如果showDialog()方法提供了太多了自动行为,我们也许会更喜欢另一种JColorChooser方法 ,这种方法允许我们在显示之前自定义JColorChooser并且定义当选择OK与Cancel按钮时的所发生的事件。

public static JDialog createDialog(Component parentComponent, String title,
  boolean modal, JColorChooser chooserPane, ActionListener okListener,
  ActionListener cancelListener)

在createDialog()方法,父组件与标题参数与showDialog()方法相同。modal参数使得弹出窗口可以是非模态的,这与showDialog()不同,后者弹出窗口总是模态的。当弹出窗口是非模态时,用户仍然可以与程序的其他部分交互。弹出窗口中的OK与Cancel按钮有一个相关联的ActionListener,从而在选择之后可以隐藏弹出窗口。如果我们需要选择之后的额外响应,则我们要负责添加我们自己的监听器。

为了演示createDialog()的正确使用,列表9-10中的程序重复了列表9-9中的程序的功能。然而,如果新的背景色与前景色相同,则颜色修改会被拒绝,而不会自动接受新的颜色值。另外,如果用户选择Cancel按钮,按钮的背景色会被设置为红色。

package swingstudy.ch09;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFrame;
 
public class CreateColorSamplePopup {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		Runnable runner = new Runnable() {
			public void run() {
				JFrame frame = new JFrame("JColorChooser Create Popup Sample");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
				final JButton button = new JButton("Pick to Change Background");
 
				ActionListener actionListener = new ActionListener() {
					public void actionPerformed(ActionEvent event) {
						Color initialBackground = button.getBackground();
 
						final JColorChooser colorChooser = new JColorChooser(initialBackground);
 
						// for okay selection, change button background to selected color
						ActionListener okActionListener = new ActionListener() {
							public void actionPerformed(ActionEvent event) {
								Color newColor = colorChooser.getColor();
								if(newColor.equals(button.getForeground())) {
									System.out.println("Color change rejected");
								}
								else {
									button.setBackground(newColor);
								}
							}
						};
 
						// for cancel selection, change button background to red
						ActionListener cancelActionListener = new ActionListener() {
							public void actionPerformed(ActionEvent event) {
								button.setBackground(Color.RED);
							}
						};
 
						final JDialog dialog = JColorChooser.createDialog(null, "Change Button Background", true, colorChooser, okActionListener, cancelActionListener);
 
						// wait for current event dispatching to complete before showing
						Runnable showDialog = new Runnable() {
							public void run() {
								dialog.setVisible(true);
							}
						};
 
						EventQueue.invokeLater(showDialog);
					}
				};
 
				button.addActionListener(actionListener);
				frame.add(button, BorderLayout.CENTER);
 
				frame.setSize(300, 100);
				frame.setVisible(true);
			}
		};
 
		EventQueue.invokeLater(runner);
	}
 
}

注意,actionPerformed()方法使用EventQueue.invokeLate()方法来显示选择器。当前的事件处理需在显示选择器之前完成。否则,在选择器显示之前,前一个动作的事件处理还没有完成。

9.4.3 JColorChooser属性

表9-8列出了JColorChooser的八个属性的信息,包括color属性的三个数据类型。

Swing_table_9_10

color属性比较特殊,因为他有三种设置的方法:

  • 直接由Color设置
  • 由一个使用0xAARRGGBB分配形式将红绿蓝值组合在一起的int变量来设置,其中A表示alpha值(被忽略,使用255替换)
  • 由分别表示红,绿,蓝颜色组件的单独三个int变量设置

如果我们没有使用showDialog(),我们可以在JColorChooser显示之前进行自定义。除了自定义color属性以外,color属性可以在JColorChooser构造函数中设置,我们还可以自定义在预览区域显示的组件以及选择器面板。

修改预览面板

ColorChooserComponentFactory类负责为JColorChooser的预览区域提供默认的组件。对于标准的观感类型,预览面板位于颜色选择器的底部。

如果我们不需要颜色选择器中的预览面板,我们必须将previewPanel属性设置为一个不为null的组件值。当这个属性设置为null时,则会显示观感的默认预览面板。将这个属性设置为一个空的JPanel可以实现不显示预览面板的目的。

colorChooser.setPreviewPanel(new JPanel());

图9-20显示了一个不带预览面板的颜色选择器的样子。因为当JPanel内没有任何内容时,JPanel没有尺寸,这就有效的移除的面板。

Swing_9_20

如果我们希望显示预览面板,但是并不喜欢默认的外观,我们可以向这个区域添加我们自己的JComponent。配置要求我们将我们的新预览面板放在一个带有标题边框的容器内,并且当用户选择一个新的颜色时预览面板的前景色发生变化。

注意,ColorChooserUI实现类(BasicColorChooserUI)中的bug要求额外的步骤来安装预览面板。除了调用setPreviewPanel(newPanel)之外,我们必须设置面板的尺寸与边框,从而使得用户界面正确的配置新的预览面板。

下面的代码演示了使用JLabel作为自定义预览面板。图9-21演示了使用了这种预览面板后JColorChooser的样子。

final JLabel previewLabel = new JLabel("I Love Swing", JLabel.CENTER);
previewLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 48));
previewLabel.setSize(previewLabel.getPreferredSize());
previewLabel.setBorder(BorderFactory.createEmptyBorder(0,0,1,0));
colorChooser.setPreviewPanel(previewLabel);

Swing_9_21

注意,因为预览面板的前景色的初始设置为其背景色,所以面板看起来是空的。这也就是默认预览面板使用限制的背景色显示文本的原因。

修改颜色选择器面板

JColorChooser上部的各种标签表示AbstractColorChooserPanel实现。每一个标签都允许用户以一种不同的方式选择颜色。默认情况下,ColorChooserComponentFactory提供具有三个面板的JColorChooser(如图9-22):

  • 样本面板允许用户由一个预定义的颜色样本集合中选择颜色,就如同在一个颜料店一样。
  • HSB面板允许用户使用色调饱和度明亮度的颜色模式选择颜色。
  • RGB面板允许用户使用红绿蓝颜色模式选择颜色。

Swing_9_22

如果我们不喜欢默认的选择器面板,或者是我们希望添加其他工作方式不同的颜色选择器面板,我们可以通过继承AbstractColorChooserPanel类来创建我们自己的面板。要将新面板添加到已存在集合中,我们可以调用下面的方法:

public void addChooserPanel(AbstractColorChooserPanel panel)

如果稍后我们决定不再使用新面板,我们可以使用下面的方法来移除:

public AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel panel)

要替换已存在的面板集合,可以调用下面的方法:

setChooserPanels(AbstractColorChooserPanel panels[ ])

创建一个新面板要求我们继承AbstractColorChooserPanel,并且为新面板填充颜色选择的细节。下面的代码行显示了这个类的定义,其中包括了五个抽象方法。这五个方法是我们必须重写的。

public abstract class AbstractColorChooserPanel extends JPanel {
  public AbstractColorChooserPanel();
  protected abstract void buildChooser();
  protected Color getColorFromModel();
  public ColorSelectionModel getColorSelectionModel();
  public int getDisplayMnemonicIndex();
  public abstract String getDisplayName();
  public abstract Icon getLargeDisplayIcon();
  public int getMnemonic();
  public abstract Icon getSmallDisplayIcon();
  public void installChooserPanel(JColorChooser);
  public void paint(Graphics);
  public void uninstallChooserPanel(JColorChooser);
  public abstract void updateChooser();
}

为了演示如何使用颜色选择器面板,下面我们来看一下如何来创建显示Color与SystemColor类中的颜色列表的颜色选择面板。由这个列表中,用户必须选择一个颜色。面板使用JComboBox来表示颜色列表。(JComboBox的使用会在第13章进行详细解释)图9-23显示了完成的面板。面板是使用下面的代码创建并添加的:

SystemColorChooserPanel newChooser = new SystemColorChooserPanel();
AbstractColorChooserPanel chooserPanels[] = {newChooser};
colorChooser.setChooserPanels(chooserPanels);

Swing_9_23

要定义的第一个方法是public String getDisplayName()。这个方法返回一个当存在多个选择器面板时在Tab上显示的文本标签。如果只有一个选择面板,这个名字不会显示。

public String getDisplayName() {
  return "SystemColor";
}

由两个Icon方法返回的值与系统的观感类型没有任何关系。我们可以由这两个方法中返回null,或者是返回与这两个方法无关的Icon来检测。自定义的ColorChooserUI需要使用这两个Icon方法,通常用于在选择器面板Tab页上的图标。

public Icon getSmallDisplayIcon() {
  return new DiamondIcon(Color.BLUE);
}
public Icon getLargeDisplayIcon() {
  return new DiamondIcon(Color.GREEN);
}

protected void buildChooser()方法是由AbstractColorChooserPanel的installChooserPanel()方法在面板被添加到选择器时调用的。我们使用这个方法来向容器添加必要的组件。在示例SystemColorChooserPanel选择器中,这个涉及到创建JComboBox并将其添加到面板。因为AbstractColorChooserPanel是一个JPanel子类,我们就可以使用add()方法添加组合框。组合框必须使用选项进行填充,并且必须安装一个事件处理器用于用户选择组件时的事件处理。事件处理的代码在下面的代码块之后描述。

protected void buildChooser() {
  comboBox = new JComboBox(labels);
  comboBox.addItemListener(this);
  add(comboBox);
}

注意,另外,如果我们选择重写uninstallChooserPanel(JColorChooser enclosingChooser),我们需要最后调用super.uninstallChooserPanel(JColorChooser enclosingChooser),而不是先调用。

当用户修改AbstractColorChooserPanel中的颜色时,面板必须通知颜色变化的ColorSelectionModel。在SystemColorChooserPanel面板中,这等同于用户在JComboxBox中选择一个新的选项。所以,当复选框的值发生变化时,确定与选项等同的Color,然后通知模型相应的变化。

public void itemStateChanged(ItemEvent itemEvent) {
  int state = itemEvent.getStateChange();
  if (state == ItemEvent.SELECTED) {
    int position = findColorLabel(itemEvent.getItem());
    // Last position is bad (not selectable)
    if ((position != NOT_FOUND) && (position != labels.length-1)) {
      ColorSelectionModel selectionModel = getColorSelectionModel();
      selectionModel.setSelectedColor(colors[position]);
    }
  }
}

最后要实现的AbstractColorChooserPanel方法是public void updateChooser()。这个方法也是在启动时由installChooserPanel()方法来调用的。另外,当JColorChooser的ColorSelectionModel发生变化时也会调用这个方法。当updateChooser()方法被调用时,选择器面板必须更新其显示来显示当前被选中的模型颜色。并不是所有的面板都显示当前被选中的是哪一个颜色,所以调用也许会不做任何事情。(系统提供的样品面板就是一个不显示当前颜色的面板。)另外,也有可能当前的颜色在面板上不能显示。例如,在SystemColorChooserPanel中,如果当前选择并不是一个SystemColor或是Color常量,我们可以选择不做任何事情或是显示一些内容来表示自定义的颜色。所以,在updateChooser()实现中,我们需要由ColorSelectionModel中获取当前的颜色,并且修改面板的颜色。实际的设置是通过一个为setColor(Color newValue)的助手方法来实现的。

public void updateChooser() {
  Color color = getColorFromModel();
  setColor(color);
}

setColor(Color newValue)方法简单使用由findColorPosition(Color newColor)返回的位置在一个查询表中查询颜色。

// Change combo box to match color, if possible
private void setColor(Color newColor) {
  int position = findColorPosition(newColor);
  comboBox.setSelectedIndex(position);
}

findColorLabel(Object label)与findColorPosition(Color newColor)的细节将会在稍后的列表9-11的完整源码中进行显示。

如果我们不使用显示选择器弹出容器的showDialog()方法,一旦选择器面板已经被定义,而且我们已经创建了一个选择器面板,他可以被通过addChooserPanel()方法放入JColorChooser中。

AbstractColorChooserPanel newChooser = new SystemColorChooserPanel();
colorChooser.addChooserPanel(newChooser);

在显示JColorChooser并且选择相应的Tab页之后,我们的新选择器就可以使用,如图9-24所示。

Swing_9_24

SystemColorChooserPanel的完整源码显示在列表9-11中。这个程序应该使用ComboBoxModel来将示例的labels与colors数组存储在一个数据模型中。然而,使用JComboBox的MVC功能的复杂性将会在第13章讨论。我们可以自由的修改示例从而为JComboBox或者是其他可用的集合API类使用合适的数据模型。

package swingstudy.ch09;
 
import java.awt.Color;
import java.awt.SystemColor;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
 
import javax.swing.Icon;
import javax.swing.JComboBox;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import javax.swing.colorchooser.ColorSelectionModel;
 
import swingstudy.ch04.DiamondIcon;
 
public class SystemColorChooserPanel extends AbstractColorChooserPanel implements ItemListener{
 
	private static int NOT_FOUND = -1;
 
	JComboBox comboBox;
	String labels[] = {
		"BLACK",
		"BLUE",
		"CYAN",
		"DARK_GRAY",
		"GRAY",
		"GREEN",
		"LIGHT_GRAY",
		"MAGENTA",
		"ORANGE",
		"PINK",
		"RED",
		"WHITE",
		"YELLOW",
		"activeCaption",
		"activeCaptionBorder",
		"activeCaptionText",
		"control",
		"controlDkShadow",
		"controlHighlight",
                "controlLtHighlight",
		"controlShadow",
		"controlText",
		"desktop",
		"inactiveCaption",
		"inactiveCaptionBorder",
		"inactiveCaptionText",
		"info",
		"infoText",
		"menu",
		"menuText",
		"scrollbar",
		"text",
		"textHighlight",
		"textHighlightText",
		"textInactiveText",
		"textText",
		"window",
		"windowBorder",
		"windowText",
		""
	};
 
	Color colors[] = {
		Color.BLACK,
		Color.BLUE,
		Color.CYAN,
		Color.DARK_GRAY,
		Color.GRAY,
		Color.GREEN,
		Color.LIGHT_GRAY,
		Color.MAGENTA,
		Color.ORANGE,
		Color.PINK,
		Color.RED,
		Color.WHITE,
		Color.YELLOW,
		SystemColor.activeCaption,
		SystemColor.activeCaptionBorder,
		SystemColor.activeCaptionText,
		SystemColor.control,
		SystemColor.controlDkShadow,
		SystemColor.controlHighlight,
		SystemColor.controlLtHighlight,
		SystemColor.controlShadow,
		SystemColor.controlText,
		SystemColor.desktop,
		SystemColor.inactiveCaption,
		SystemColor.inactiveCaptionBorder,
		SystemColor.inactiveCaptionText,
		SystemColor.info,
		SystemColor.infoText,
		SystemColor.menu,
		SystemColor.menuText,
		SystemColor.scrollbar,
		SystemColor.text,
		SystemColor.textHighlight,
		SystemColor.textHighlightText,
		SystemColor.textInactiveText,
		SystemColor.textText,
		SystemColor.window,
		SystemColor.windowBorder,
		SystemColor.windowText,
		null		
	};
 
	// change combo box to match color, if possible
	private void setColor(Color newColor) {
		int position = findColorPosition(newColor);
		comboBox.setSelectedIndex(position);
	}
 
	// given a label, find the position of the label in the list
	private int findColorLabel(Object label) {
		String stringLabel = label.toString();
		int position = NOT_FOUND;
		for(int i=0, n=labels.length; iif(stringLabel.equals(labels[i])) {
				position = i;
				break;
			}
		}
		return position;
	}
 
	// given a color, find the position whose color matches
	// this could result in a position different from original if two are equal
	// since actual color is same, this is considered to be okay
	private int findColorPosition(Color color) {
		int position =  colors.length-1;
		// cannot use equals() to compare Color and SystemColor
		int colorRGB = color.getRGB();
		for(int i=0, n=colors.length; iif((colors[i] != null) && (colorRGB == colors[i].getRGB())) {
				position = i;
				break;
			}
		}
		return position;
	}
 
	public void itemStateChanged(ItemEvent event) {
		int state = event.getStateChange();
		if(state == event.SELECTED) {
			int position = findColorLabel(event.getItem());
			// last position is bad(not selectable)
			if((position != NOT_FOUND) && (position != labels.length-1)) {
				ColorSelectionModel selectionModel = getColorSelectionModel();
				selectionModel.setSelectedColor(colors[position]);
			}
		}
	}
 
	public String getDisplayName() {
		return "SystemColor";
	}
 
	public Icon getSmallDisplayIcon() {
		return new DiamondIcon(Color.BLUE);
	}
 
	public Icon getLargeDisplayIcon() {
		return new DiamondIcon(Color.GREEN);
	}
 
	protected void buildChooser() {
		comboBox =  new JComboBox(labels);
		comboBox.addItemListener(this);
		add(comboBox);
	}
 
	public void updateChooser() {
		Color color = getColorFromModel();
		setColor(color);
	}
}

列表9-12演示了新的选择器面板的使用。这只是前面9-10中所显示的CreateColorSamplePopup程序的简单修改版本。我们可以取消setChooserPanels()语句的注释,并且注释掉addChooserPanel()调用就可以实现由添加一个面板(如图9-23所示)到替换所有面板(如图9-24所示)的转变。

package swingstudy.ch09;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFrame;
 
public class CustomPanelPopup {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		Runnable runner = new Runnable() {
			public void run() {
				JFrame frame = new JFrame("JColorChooser Custome Panel Sample");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
				final JButton button = new JButton("Pick to Change Background");
 
				ActionListener actionListener = new ActionListener() {
					public void actionPerformed(ActionEvent event) {
						Color initialBackground = button.getBackground();
 
						final JColorChooser colorChooser = new JColorChooser(initialBackground);
						SystemColorChooserPanel newChooser = new SystemColorChooserPanel();
 
						// AbstractColorchooserPanel chooserPanels[] = {newChooser};
						// colorChooser.setChooserPanels(chooserPanels);
						colorChooser.addChooserPanel(newChooser);
 
						// for okay button, change button background to selected color
						ActionListener okActionListener = new ActionListener() {
							public void actionPerformed(ActionEvent event) {
								Color newColor = colorChooser.getColor();
								if(newColor.equals(button.getForeground())) {
									System.out.println("Color change rejected");
								}
								else {
									button.setBackground(newColor);
								}
							}
						};
 
						// for cancel button, change button background to red
						ActionListener cancelActionlistener = new ActionListener() {
							public void actionPerformed(ActionEvent event) {
								button.setBackground(Color.RED);
							}
						};
 
						final JDialog dialog = JColorChooser.createDialog(null, "Change Button Background", true, colorChooser, okActionListener, cancelActionlistener);
 
						// wait for current event dispatching to complete before showing
						Runnable showDialog = new Runnable() {
							public void run() {
								dialog.setVisible(true);
							}
						};
						EventQueue.invokeLater(showDialog);
					}
				};
 
				button.addActionListener(actionListener);
				frame.add(button, BorderLayout.CENTER);
 
				frame.setSize(300, 100);
				frame.setVisible(true);
			}
		};
		EventQueue.invokeLater(runner);
	}
 
}

使用ColorChooserComponentFactory类

值得关注的一个类就是ColorChooserComponentFactory。通常这个类在幕后工作,而我们也不需要对其进行处理。

然而,如果我们希望移除一个默认的颜色选择器,我们不能使用JColorChooser的public AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel panel)。初始时,JColorChooser的chooserPanels属性为null。当这个属性为null时,默认的ColorChooserUI使用public static AbstractColorChooserPanel[] getDefaultChooserPanels()方法向ColorChooserComponentFactory查询默认面板。所以在我们修改这个属性之前,不会有面板显示。如果我们希望移除一个默认面板,我们必须获取默认数组,将我们希望保持的面板存入一个新数组,然后将选择器的chooserPanel属性修改为新数组。这是额外的工作,但是这可以使得工作完成。

ColorChooserComponentFactory类的另一个方法就是public static JComponent getPreviewPanel()方法,这个方法会在JColorChooser的previewPanel属性为null时获取默认的预览面板。这就是向JColorChooser的setPreviewPanel()方法提供null参数并不会移除预览面板的原因。对于空面板,我们必须提供一个没有尺寸的JComponent。

colorChooser.setPreviewPanel(new JPanel());

9.4.4 自定义JColorChooser观感

JColorChooser的外观几乎与所有已安装的观感类型相同。唯一的区别与每一个观感如何显示内部组件相关,例如JTabbedPane,JLabel,JButton,或是JSlider。修改这些组件的UIResource相关属性可以影响新创建的JColorChooser的外观。另外,表9-9中列出了JColorChooser类用于自定义的39个UIResource相关属性。这些属性中的大多数与显示在各种默认颜色选择面板上的文本标签有关。

Swing_table_9_11_1

Swing_table_9_11_2

Swing_table_9_11_3

Swing_table_9_11_4

分享到:
评论

相关推荐

    自定义弹出窗口

    自定义弹出窗口,正如其名,允许开发者根据需求设计并构建出与系统默认样式不同的对话框,提供更个性化的用户体验。在这里,我们将深入探讨如何创建和实现这样的功能。 首先,我们需要理解弹出窗口的基本概念。在...

    SIEMENS-西门子wincc弹出窗口怎么做?.txt

    在探讨如何在SIEMENS-西门子WinCC软件中创建弹出窗口之前,我们首先需要了解WinCC是什么以及它的一些基本概念。 ### WinCC简介 WinCC(Windows Control Center)是西门子公司开发的一款人机界面(HMI)与监控控制...

    asp.net mvc 弹出窗口 技巧

    1. **JavaScript与jQuery库**:在ASP.NET MVC中,通常会利用JavaScript和jQuery来实现前端交互,包括弹出窗口。jQuery库简化了DOM操作,使得创建和控制弹出窗口变得简单。 2. **Bootstrap Modal**:Bootstrap是广泛...

    js 自动弹出窗口 下来菜单效果

    在探讨“js自动弹出窗口下来菜单效果”的知识点时,我们不仅关注JavaScript代码本身,还应当深入了解其背后的逻辑与应用场景。这段代码展示了如何利用JavaScript创建一个动态下拉菜单,并在用户选择菜单项时自动打开...

    很好用的模态弹出窗口,可自定义弹出窗口外观源码

    模态弹出窗口是一种覆盖在主页面上的对话框,用户必须先关闭弹出窗口才能继续与主页面交互。这种设计常用于显示警告、确认、输入表单等场景。在HTML和JavaScript中,通常使用`<div>`元素配合CSS样式实现,而在这个...

    .NET弹出窗口总结

    总结一下,.NET框架提供了各种弹出窗口供开发者使用,包括简单的`MessageBox`、文件选择对话框、颜色和字体选择器,以及自定义的表单。通过灵活运用这些窗口,开发者可以构建出具有丰富用户交互的应用程序。了解并...

    jquery实现弹出窗口

    3. **jQuery 事件**:使用 jQuery 选择器和事件监听来控制弹出窗口的显示和关闭。例如: ```javascript $(document).ready(function() { var modal = $("#myModal"); // 当点击关闭按钮时关闭弹出窗口 $("....

    谷歌浏览器弹出窗口拦截取消的设置操作说明(1).docx

    ### 谷歌浏览器弹出窗口拦截取消的设置操作说明 #### 一、引言 在日常使用浏览器的过程中,我们可能会遇到一些网站自动弹出广告或者其他通知窗口的情况。虽然这些弹窗有时候会提供有用的信息或者服务,但很多时候...

    百度的弹出窗口

    在IT行业中,弹出窗口是一种常见的用户交互设计,它能够吸引用户的注意力或者提供额外的信息。在Web开发领域,JavaScript(Js)是实现这种功能的主要工具。"百度的弹出窗口"可能指的是百度搜索引擎或其相关服务中...

    弹出窗口灰色背景

    在`asyncbox.js`中,我们可以预期找到与弹出窗口相关的函数,比如打开和关闭窗口的逻辑,以及灰色背景的添加和移除。可能的函数名包括`showBox`、`hideBox`、`createMask`和`removeMask`等。此外,代码可能会使用...

    IE设置弹出窗口、安全站点

    ### IE浏览器设置详解:弹出窗口与安全站点配置 #### 一、引言 随着互联网技术的发展,浏览器作为用户接入互联网的重要工具之一,其安全性与便捷性显得尤为重要。Internet Explorer(简称IE)作为曾经占据市场主导...

    17、Jquery支持自定义弹出窗口插件

    本主题将深入探讨如何使用jQuery实现自定义弹出窗口插件,这对于创建交互式用户界面至关重要。 首先,我们需要理解什么是弹出窗口。弹出窗口通常是在主页面上覆盖一层半透明或全屏的元素,用来显示额外的信息、提示...

    JQUERY 弹出窗口

    综上所述,"JQUERY 弹出窗口"是一个关于利用jQuery创建和管理弹出对话框或弹出层的实践主题,涉及到的基本知识点包括jQuery的选择器、DOM操作、显示/隐藏方法以及可能的CSS样式和动画效果。在实际开发中,理解并熟练...

    jQuery点击按钮弹出窗口动画特效.zip

    4. **弹出窗口的创建与控制**:弹出窗口可能是一个模态对话框或者简单的div元素,通过CSS定位和jQuery的显示/隐藏方法控制其可见性。例如,`.show()`和`.hide()`方法用于控制元素的显示与隐藏,`.fadeIn()`和`....

    flex 弹出窗口选择,支持autocomplete功能

    在本文中,我们将深入探讨如何在Flex环境中实现一个具有autocomplete(自动补全)功能的弹出窗口选择器。Flex是一种基于ActionScript的开源框架,用于构建富互联网应用程序(RIA),它允许开发者创建交互性强、用户...

    Jquery弹出窗口,带例子参数说明 非常好用

    本篇文章将深入探讨 jQuery 中的弹出窗口功能,以及如何利用 AJAX 进行数据异步加载。我们将通过实例和参数说明来详细解释这一过程。 首先,jQuery 提供了多种弹出窗口的实现方式,如 `alert()`, `confirm()`, 和 `...

    页面右下角弹出窗口

    1. **选择器与DOM操作**:jQuery提供了丰富的选择器来选取页面中的元素,如ID选择器(#id),类选择器(.class)等。首先,我们需要一个隐藏的弹出窗口元素,通过选择器选取该元素,并将其初始状态设置为隐藏(如CSS样式...

    CSS3 jQuery自定义弹出窗口

    在网页设计中,弹出窗口是一种常见的交互元素,用于显示通知、警告、确认信息或进行更复杂的用户交互。本文将深入探讨如何利用CSS3和jQuery来创建自定义弹出窗口,提升用户体验的同时,确保设计的灵活性和可扩展性。...

    弹出窗口_Elastic Transition

    以上就是关于“弹出窗口_Elastic Transition”这一主题的相关知识点,包括弹出窗口的设计与实现、图片轮播的功能和应用,以及弹性过渡的原理和技术。在实际项目中,灵活运用这些技术可以极大地提升网页的互动性和...

    实用弹出窗口组件

    6. **可访问性**:考虑到无障碍(Accessibility)需求,弹出窗口应遵循WCAG(Web Content Accessibility Guidelines)标准,确保键盘导航和屏幕阅读器的支持。 7. **关闭机制**:用户应能方便地关闭弹出窗口,这...

Global site tag (gtag.js) - Google Analytics