文档章节

Swing之文件选择器

思想永无止境
 思想永无止境
发布于 2016/11/04 11:59
字数 5615
阅读 16
收藏 0

Swing里默认的文件选择器非常丑,所以,文件选择器一般需要重写。

以下代码非常完整,copy可以直接运行。

一、类CustomFileChooser

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Locale;
import java.util.Vector;

import javax.accessibility.AccessibleContext;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.filechooser.FileView;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.FileChooserUI;
import javax.swing.plaf.basic.BasicDirectoryModel;
import javax.swing.plaf.basic.BasicFileChooserUI;

import sun.awt.shell.ShellFolder;
import sun.swing.FilePane;
import sun.swing.SwingUtilities2;

/**
 * 自定义文件选择器
 * 
 * @author tang
 * 
 * @since 2014/8/19
 * 
 */
@SuppressWarnings({ "serial", "restriction" })
public class CustomFileChooser extends JFileChooser {

	public static void main(String[] args) {

		UIManager.put("ScrollBarUI", "com.sun.java.swing.plaf.windows.WindowsScrollBarUI");// 设置滚动条样式为window风格的滚动条样式

		// 设置文件夹在swing中所显示的图标
		UIManager.put("FileView.directoryIcon", FileSystemView.getFileSystemView().getSystemIcon(new File(System.getProperty("user.dir"))));

		// 如果觉得默认的图标太丑可以自己设置文件选择对话框的一系列图标
		//	UIManager.put("FileChooser.newFolderIcon", newFolderIcon);
		//	UIManager.put("FileChooser.upFolderIcon", upFolderIcon);
		//	UIManager.put("FileChooser.homeFolderIcon", homeFolderIcon);
		//	UIManager.put("FileChooser.detailsViewIcon", detailsViewIcon);
		//	UIManager.put("FileChooser.listViewIcon", listViewIcon);

		// 设置工具提示的默认样式
		Color toolTipColor = new Color(80, 80, 80);
		UIManager.put("ToolTip.border",
				BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(toolTipColor), BorderFactory.createEmptyBorder(2, 3, 2, 3)));
		UIManager.put("ToolTip.background", Color.WHITE);
		UIManager.put("ToolTip.foreground", toolTipColor);

		CustomFileChooser chooser = new CustomFileChooser();
		chooser.showOpenDialog(null);
	}

	public CustomFileChooser() {
		super();
	}

	public CustomFileChooser(File currentDirectory, FileSystemView fsv) {
		super(currentDirectory, fsv);
	}

	public CustomFileChooser(File currentDirectory) {
		super(currentDirectory);
	}

	public CustomFileChooser(FileSystemView fsv) {
		super(fsv);
	}

	public CustomFileChooser(String currentDirectoryPath, FileSystemView fsv) {
		super(currentDirectoryPath, fsv);
	}

	public CustomFileChooser(String currentDirectoryPath) {
		super(currentDirectoryPath);
	}

	{
		setUI(new CustomFileChooserUI(this));
	}

	@Override
	protected JDialog createDialog(Component parent) throws HeadlessException {
		FileChooserUI ui = getUI();
		String title = ui.getDialogTitle(this);
		putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY, title);

		Window window = getWindowForComponent(parent);
		JDialog dialog = new JDialog(window, title);
		dialog.setModal(true);
		dialog.setComponentOrientation(this.getComponentOrientation());

		if (JDialog.isDefaultLookAndFeelDecorated()) {
			boolean supportsWindowDecorations = UIManager.getLookAndFeel().getSupportsWindowDecorations();
			if (supportsWindowDecorations) {
				dialog.getRootPane().setWindowDecorationStyle(JRootPane.FILE_CHOOSER_DIALOG);
			}
		}
		dialog.getRootPane().setDefaultButton(ui.getDefaultButton(this));
		dialog.getContentPane().add(this);
		dialog.pack();
		setLocationRelativeTo(parent, dialog);

		return dialog;
	}

	/**
	 * 自定义文件选择器UI,代码主要来源于MetalFileChooserUI
	 * 
	 * @author tang
	 * 
	 * @since 2014/8/19
	 * 
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static class CustomFileChooserUI extends BasicFileChooserUI {

		private static Font labelFont14 = new Font(Font.DIALOG, Font.PLAIN, 14);
		private static Font labelFont12 = new Font(Font.DIALOG, Font.PLAIN, 12);
		private static Color boxBorderColor = Color.GRAY;
		private static Color boxForegroundColor = new Color(51, 51, 51);
		// private static int boxHeight = 25;
		// private static int buttonWidth=30;
		// private static int buttonHeight=30;

		// Much of the Metal UI for JFilechooser is just a copy of
		// the windows implementation, but using Metal themed buttons, lists,
		// icons, etc. We are planning a complete rewrite, and hence we've
		// made most things in this class private.

		private BasicFileView fileView = new CustomFileView();

		private JLabel lookInLabel;
		private CustomComboBox directoryComboBox;
		private DirectoryComboBoxModel directoryComboBoxModel;
		private Action directoryComboBoxAction = new DirectoryComboBoxAction();

		private FilterComboBoxModel filterComboBoxModel;

		private JTextField fileNameTextField;

		private FilePane filePane;
		private JToggleButton listViewButton;
		private JToggleButton detailsViewButton;

		private JButton approveButton;
		private JButton cancelButton;

		private JPanel buttonPanel;
		private JPanel bottomPanel;

		private CustomComboBox filterComboBox;

		private static final Dimension hstrut5 = new Dimension(5, 1);
		// private static final Dimension hstrut11 = new Dimension(11, 1);

		private static final Dimension vstrut5 = new Dimension(1, 5);

		private static final Insets shrinkwrap = new Insets(0, 0, 0, 0);

		// Preferred and Minimum sizes for the dialog box
		private static int PREF_WIDTH = 500;
		private static int PREF_HEIGHT = 326;
		private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT);

		private static int MIN_WIDTH = 500;
		private static int MIN_HEIGHT = 326;
		private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);

		private static int LIST_PREF_WIDTH = 405;
		private static int LIST_PREF_HEIGHT = 135;
		private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT);

		// Labels, mnemonics, and tooltips (oh my!)
		private int lookInLabelMnemonic = 0;
		private String lookInLabelText = null;
		private String saveInLabelText = null;

		private int fileNameLabelMnemonic = 0;
		private String fileNameLabelText = null;
		private int folderNameLabelMnemonic = 0;
		private String folderNameLabelText = null;

		private int filesOfTypeLabelMnemonic = 0;
		private String filesOfTypeLabelText = null;

		private String upFolderToolTipText = null;
		private String upFolderAccessibleName = null;

		private String homeFolderToolTipText = null;
		private String homeFolderAccessibleName = null;

		private String newFolderToolTipText = null;
		private String newFolderAccessibleName = null;

		private String listViewButtonToolTipText = null;
		private String listViewButtonAccessibleName = null;

		private String detailsViewButtonToolTipText = null;
		private String detailsViewButtonAccessibleName = null;

		private AlignedLabel fileNameLabel;

		private void populateFileNameLabel() {
			if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
				fileNameLabel.setText(folderNameLabelText);
				fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic);
			} else {
				fileNameLabel.setText(fileNameLabelText);
				fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic);
			}
		}

		//
		// ComponentUI Interface Implementation methods
		//
		public static ComponentUI createUI(JComponent c) {
			return new CustomFileChooserUI((JFileChooser) c);
		}

		public CustomFileChooserUI(JFileChooser filechooser) {
			super(filechooser);
		}

		public void installUI(JComponent c) {
			super.installUI(c);
		}

		public void uninstallComponents(JFileChooser fc) {
			fc.removeAll();
			bottomPanel = null;
			buttonPanel = null;
		}

		private class CustomFileChooserUIAccessor implements FilePane.FileChooserUIAccessor {
			public JFileChooser getFileChooser() {
				return CustomFileChooserUI.this.getFileChooser();
			}

			public BasicDirectoryModel getModel() {
				return CustomFileChooserUI.this.getModel();
			}

			public JPanel createList() {
				return CustomFileChooserUI.this.createList(getFileChooser());
			}

			public JPanel createDetailsView() {
				return CustomFileChooserUI.this.createDetailsView(getFileChooser());
			}

			public boolean isDirectorySelected() {
				return CustomFileChooserUI.this.isDirectorySelected();
			}

			public File getDirectory() {
				return CustomFileChooserUI.this.getDirectory();
			}

			public Action getChangeToParentDirectoryAction() {
				return CustomFileChooserUI.this.getChangeToParentDirectoryAction();
			}

			public Action getApproveSelectionAction() {
				return CustomFileChooserUI.this.getApproveSelectionAction();
			}

			public Action getNewFolderAction() {
				return CustomFileChooserUI.this.getNewFolderAction();
			}

			public MouseListener createDoubleClickListener(JList list) {
				return CustomFileChooserUI.this.createDoubleClickListener(getFileChooser(), list);
			}

			public ListSelectionListener createListSelectionListener() {
				return CustomFileChooserUI.this.createListSelectionListener(getFileChooser());
			}
		}

		public void installComponents(JFileChooser fc) {
			FileSystemView fsv = fc.getFileSystemView();

			fc.setBorder(new EmptyBorder(12, 12, 11, 11));
			fc.setLayout(new BorderLayout(0, 11));

			filePane = new FilePane(new CustomFileChooserUIAccessor());
			fc.addPropertyChangeListener(filePane);

			// ********************************* //
			// **** Construct the top panel **** //
			// ********************************* //

			// Directory manipulation buttons
			JPanel topPanel = new JPanel(new BorderLayout(11, 0));
			JPanel topButtonPanel = new JPanel();
			topButtonPanel.setLayout(new BoxLayout(topButtonPanel, BoxLayout.LINE_AXIS));
			topPanel.add(topButtonPanel, BorderLayout.AFTER_LINE_ENDS);

			// Add the top panel to the fileChooser
			fc.add(topPanel, BorderLayout.NORTH);

			// ComboBox Label
			lookInLabel = new JLabel(lookInLabelText);
			lookInLabel.setFont(labelFont14);
			lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
			topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS);

			// CurrentDir ComboBox
			directoryComboBox = new CustomComboBox() {
				public Dimension getPreferredSize() {
					Dimension d = super.getPreferredSize();
					// Must be small enough to not affect total width.
					d.width = 150;
					return d;
				}
			};
			setCustomComboBox(directoryComboBox);
			directoryComboBox.putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY, lookInLabelText);
			directoryComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
			lookInLabel.setLabelFor(directoryComboBox);
			directoryComboBoxModel = createDirectoryComboBoxModel(fc);
			directoryComboBox.setModel(directoryComboBoxModel);
			directoryComboBox.addActionListener(directoryComboBoxAction);
			directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
			directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
			directoryComboBox.setAlignmentY(JComponent.TOP_ALIGNMENT);
			directoryComboBox.setMaximumRowCount(8);

			topPanel.add(directoryComboBox, BorderLayout.CENTER);

			// Up Button
			JButton upFolderButton = getButton(upFolderIcon, getChangeToParentDirectoryAction());
			upFolderButton.setToolTipText(upFolderToolTipText);
			upFolderButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, upFolderAccessibleName);

			topButtonPanel.add(upFolderButton);
			topButtonPanel.add(Box.createRigidArea(hstrut5));

			// Home Button
			File homeDir = fsv.getHomeDirectory();
			String toolTipText = homeFolderToolTipText;
			if (fsv.isRoot(homeDir)) {
				toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop".
			}

			JButton goHomeButton = getButton(homeFolderIcon, getGoHomeAction());
			goHomeButton.setToolTipText(toolTipText);
			goHomeButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, homeFolderAccessibleName);

			topButtonPanel.add(goHomeButton);
			topButtonPanel.add(Box.createRigidArea(hstrut5));

			// New Directory Button
			if (!UIManager.getBoolean("FileChooser.readOnly")) {
				JButton newFolderButton = getButton(newFolderIcon, filePane.getNewFolderAction());
				newFolderButton.setToolTipText(newFolderToolTipText);
				newFolderButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, newFolderAccessibleName);
				topButtonPanel.add(newFolderButton);
				topButtonPanel.add(Box.createRigidArea(hstrut5));
			}

			// View button group
			ButtonGroup viewButtonGroup = new ButtonGroup();

			// List Button
			listViewButton = getToggleButton(listViewIcon, filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST));
			listViewButton.setToolTipText(listViewButtonToolTipText);
			listViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, listViewButtonAccessibleName);
			listViewButton.setSelected(true);
			topButtonPanel.add(listViewButton);
			viewButtonGroup.add(listViewButton);
			topButtonPanel.add(Box.createRigidArea(hstrut5));

			// Details Button
			detailsViewButton = getToggleButton(detailsViewIcon, filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS));
			detailsViewButton.setToolTipText(detailsViewButtonToolTipText);
			detailsViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, detailsViewButtonAccessibleName);
			topButtonPanel.add(detailsViewButton);
			viewButtonGroup.add(detailsViewButton);

			filePane.addPropertyChangeListener(new PropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent e) {
					if ("viewType".equals(e.getPropertyName())) {
						int viewType = filePane.getViewType();
						switch (viewType) {
						case FilePane.VIEWTYPE_LIST:
							listViewButton.setSelected(true);
							break;

						case FilePane.VIEWTYPE_DETAILS:
							detailsViewButton.setSelected(true);
							break;
						}
					}
				}
			});

			// ************************************** //
			// ******* Add the directory pane ******* //
			// ************************************** //
			fc.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
			JComponent accessory = fc.getAccessory();
			if (accessory != null) {
				getAccessoryPanel().add(accessory);
			}
			filePane.setPreferredSize(LIST_PREF_SIZE);
			fc.add(filePane, BorderLayout.CENTER);

			// ********************************** //
			// **** Construct the bottom panel ** //
			// ********************************** //
			JPanel bottomPanel = getBottomPanel();
			bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
			fc.add(bottomPanel, BorderLayout.SOUTH);

			// FileName label and textfield
			JPanel fileNamePanel = new JPanel();
			fileNamePanel.setLayout(new BoxLayout(fileNamePanel, BoxLayout.LINE_AXIS));
			bottomPanel.add(fileNamePanel);
			bottomPanel.add(Box.createRigidArea(vstrut5));

			fileNameLabel = new AlignedLabel();
			populateFileNameLabel();
			fileNamePanel.add(fileNameLabel);

			fileNameTextField = new JTextField(35) {
				public Dimension getMaximumSize() {
					return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
				}
			};
			setTextField(fileNameTextField);
			fileNamePanel.add(fileNameTextField);
			fileNameLabel.setLabelFor(fileNameTextField);
			fileNameTextField.addFocusListener(new FocusAdapter() {
				public void focusGained(FocusEvent e) {
					if (!getFileChooser().isMultiSelectionEnabled()) {
						filePane.clearSelection();
					}
				}
			});
			if (fc.isMultiSelectionEnabled()) {
				setFileName(fileNameString(fc.getSelectedFiles()));
			} else {
				setFileName(fileNameString(fc.getSelectedFile()));
			}

			// Filetype label and combobox
			JPanel filesOfTypePanel = new JPanel();
			filesOfTypePanel.setLayout(new BoxLayout(filesOfTypePanel, BoxLayout.LINE_AXIS));
			bottomPanel.add(filesOfTypePanel);

			AlignedLabel filesOfTypeLabel = new AlignedLabel(filesOfTypeLabelText);
			filesOfTypeLabel.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
			filesOfTypePanel.add(filesOfTypeLabel);

			filterComboBoxModel = createFilterComboBoxModel();
			fc.addPropertyChangeListener(filterComboBoxModel);
			filterComboBox = new CustomComboBox(filterComboBoxModel);
			setCustomComboBox(filterComboBox);
			filterComboBox.putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY, filesOfTypeLabelText);
			filesOfTypeLabel.setLabelFor(filterComboBox);
			filterComboBox.setRenderer(createFilterComboBoxRenderer());
			filesOfTypePanel.add(filterComboBox);

			// buttons
			getButtonPanel().setLayout(new ButtonAreaLayout());

			approveButton = createRolloverBackgroundButton(getApproveButtonText(fc));

			// Note: Metal does not use mnemonics for approve and cancel
			approveButton.addActionListener(getApproveSelectionAction());
			approveButton.setToolTipText(getApproveButtonToolTipText(fc));
			getButtonPanel().add(approveButton);

			cancelButton = createRolloverBackgroundButton(cancelButtonText);
			cancelButton.setToolTipText(cancelButtonToolTipText);
			cancelButton.addActionListener(getCancelSelectionAction());
			getButtonPanel().add(cancelButton);

			if (fc.getControlButtonsAreShown()) {
				addControlButtons();
			}

			groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel });
		}

		/**
		 * 创建一个有默认样式的按钮
		 * 
		 * @param text
		 * @return
		 */
		public static RolloverBackgroundButton createRolloverBackgroundButton(String text) {
			RolloverBackgroundButton button = new RolloverBackgroundButton(text);
			button.setFont(new Font(Font.DIALOG, Font.PLAIN, 16));
			return button;
		}

		protected void setTextField(JTextField textField) {
			textField.setFont(labelFont12);
			textField.setPreferredSize(new Dimension(0, 25));
			textField.setSelectedTextColor(Color.WHITE);
			textField.setSelectionColor(new Color(51, 153, 255));
			textField.setBorder(BorderFactory.createLineBorder(boxBorderColor));
			textField.setForeground(boxForegroundColor);
		}

		protected JButton getButton(Icon icon, Action action) {
			JButton button = new JButton(action);
			button.setIcon(icon);
			if (icon != null) {
				button.setPressedIcon(new MoveIcon(icon, 1, 1));
			}
			button.setText(null);
			button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
			button.setBorderPainted(true);
			button.setContentAreaFilled(false);
			button.setFocusPainted(false);
			button.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(boxBorderColor), new EmptyBorder(2, 2, 2, 2)));
			button.setAlignmentX(JComponent.LEFT_ALIGNMENT);
			button.setAlignmentY(JComponent.CENTER_ALIGNMENT);
			button.setMargin(shrinkwrap);
			return button;
		}

		protected JToggleButton getToggleButton(Icon icon, Action action) {
			JToggleButton button = new JToggleButton(action);
			button.setIcon(icon);
			if (icon != null) {
				button.setPressedIcon(new MoveIcon(icon, 1, 1));
			}
			button.setText(null);
			button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
			button.setHorizontalTextPosition(SwingConstants.CENTER);
			button.setVerticalTextPosition(SwingConstants.CENTER);
			button.setRolloverEnabled(true);
			button.setFocusPainted(false);
			button.setOpaque(false);
			button.setContentAreaFilled(false);
			button.setBorderPainted(true);
			button.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(boxBorderColor), new EmptyBorder(2, 2, 2, 2)));
			button.setAlignmentX(JComponent.LEFT_ALIGNMENT);
			button.setAlignmentY(JComponent.CENTER_ALIGNMENT);
			button.setMargin(shrinkwrap);
			return button;
		}

		protected CustomComboBox setCustomComboBox(CustomComboBox CustomComboBox) {
			CustomComboBox.setFont(labelFont12);
			CustomComboBox.setPreferredSize(new Dimension(0, 25));
			CustomComboBox.setSelectionBackground(Color.decode("#d7d7d7"));
			CustomComboBox.setBorder(BorderFactory.createLineBorder(boxBorderColor));
			CustomComboBox.setForeground(boxForegroundColor);
			CustomComboBox.synchAllToPopup();
			return CustomComboBox;
		}

		protected JPanel getButtonPanel() {
			if (buttonPanel == null) {
				buttonPanel = new JPanel();
			}
			return buttonPanel;
		}

		protected JPanel getBottomPanel() {
			if (bottomPanel == null) {
				bottomPanel = new JPanel();
			}
			return bottomPanel;
		}

		protected void installStrings(JFileChooser fc) {
			super.installStrings(fc);

			Locale l = fc.getLocale();

			lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l);
			lookInLabelText = UIManager.getString("FileChooser.lookInLabelText", l);
			saveInLabelText = UIManager.getString("FileChooser.saveInLabelText", l);

			fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l);
			fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText", l);
			folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l);
			folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText", l);

			filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l);
			filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText", l);

			upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText", l);
			upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName", l);

			homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText", l);
			homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName", l);

			newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText", l);
			newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName", l);

			listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText", l);
			listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName", l);

			detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText", l);
			detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName", l);
		}

		private Integer getMnemonic(String key, Locale l) {
			return SwingUtilities2.getUIDefaultsInt(key, l);
		}

		protected void installListeners(JFileChooser fc) {
			super.installListeners(fc);
			ActionMap actionMap = getActionMaping();
			SwingUtilities.replaceUIActionMap(fc, actionMap);
		}

		private ActionMap getActionMaping() {
			return createActionMaping();
		}

		private ActionMap createActionMaping() {
			ActionMap map = new ActionMapUIResource();
			FilePane.addActionsToMap(map, filePane.getActions());
			return map;
		}

		protected JPanel createList(JFileChooser fc) {
			return filePane.createList();
		}

		protected JPanel createDetailsView(JFileChooser fc) {
			return filePane.createDetailsView();
		}

		/**
		 * Creates a selection listener for the list of files and directories.
		 * 
		 * @param fc
		 *            a <code>JFileChooser</code>
		 * @return a <code>ListSelectionListener</code>
		 */
		public ListSelectionListener createListSelectionListener(JFileChooser fc) {
			return super.createListSelectionListener(fc);
		}

		// Obsolete class, not used in this version.
		protected class SingleClickListener extends MouseAdapter {
			public SingleClickListener(JList list) {
			}
		}

		// Obsolete class, not used in this version.
		protected class FileRenderer extends DefaultListCellRenderer {
		}

		public void uninstallUI(JComponent c) {
			// Remove listeners
			c.removePropertyChangeListener(filterComboBoxModel);
			c.removePropertyChangeListener(filePane);
			cancelButton.removeActionListener(getCancelSelectionAction());
			approveButton.removeActionListener(getApproveSelectionAction());
			fileNameTextField.removeActionListener(getApproveSelectionAction());

			if (filePane != null) {
				filePane.uninstallUI();
				filePane = null;
			}

			super.uninstallUI(c);
		}

		/**
		 * Returns the preferred size of the specified <code>JFileChooser</code>
		 * . The preferred size is at least as large, in both height and width,
		 * as the preferred size recommended by the file chooser's layout
		 * manager.
		 * 
		 * @param c
		 *            a <code>JFileChooser</code>
		 * @return a <code>Dimension</code> specifying the preferred width and
		 *         height of the file chooser
		 */
		public Dimension getPreferredSize(JComponent c) {
			int prefWidth = PREF_SIZE.width;
			Dimension d = c.getLayout().preferredLayoutSize(c);
			if (d != null) {
				return new Dimension(d.width < prefWidth ? prefWidth : d.width, d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height);
			} else {
				return new Dimension(prefWidth, PREF_SIZE.height);
			}
		}

		/**
		 * Returns the minimum size of the <code>JFileChooser</code>.
		 * 
		 * @param c
		 *            a <code>JFileChooser</code>
		 * @return a <code>Dimension</code> specifying the minimum width and
		 *         height of the file chooser
		 */
		public Dimension getMinimumSize(JComponent c) {
			return MIN_SIZE;
		}

		/**
		 * Returns the maximum size of the <code>JFileChooser</code>.
		 * 
		 * @param c
		 *            a <code>JFileChooser</code>
		 * @return a <code>Dimension</code> specifying the maximum width and
		 *         height of the file chooser
		 */
		public Dimension getMaximumSize(JComponent c) {
			return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
		}

		private String fileNameString(File file) {
			if (file == null) {
				return null;
			} else {
				JFileChooser fc = getFileChooser();
				if ((fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled())
						|| (fc.isDirectorySelectionEnabled() && fc.isFileSelectionEnabled() && fc.getFileSystemView().isFileSystemRoot(file))) {
					return file.getPath();
				} else {
					return file.getName();
				}
			}
		}

		private String fileNameString(File[] files) {
			StringBuffer buf = new StringBuffer();
			for (int i = 0; files != null && i < files.length; i++) {
				if (i > 0) {
					buf.append(" ");
				}
				if (files.length > 1) {
					buf.append("\"");
				}
				buf.append(fileNameString(files[i]));
				if (files.length > 1) {
					buf.append("\"");
				}
			}
			return buf.toString();
		}

		/* The following methods are used by the PropertyChange Listener */

		private void doSelectedFileChanged(PropertyChangeEvent e) {
			File f = (File) e.getNewValue();
			JFileChooser fc = getFileChooser();
			if (f != null && ((fc.isFileSelectionEnabled() && !f.isDirectory()) || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {

				setFileName(fileNameString(f));
			}
		}

		private void doSelectedFilesChanged(PropertyChangeEvent e) {
			File[] files = (File[]) e.getNewValue();
			JFileChooser fc = getFileChooser();
			if (files != null && files.length > 0 && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) {
				setFileName(fileNameString(files));
			}
		}

		private void doDirectoryChanged(PropertyChangeEvent e) {
			JFileChooser fc = getFileChooser();
			FileSystemView fsv = fc.getFileSystemView();

			clearIconCache();
			File currentDirectory = fc.getCurrentDirectory();
			if (currentDirectory != null) {
				directoryComboBoxModel.addItem(currentDirectory);

				if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
					if (fsv.isFileSystem(currentDirectory)) {
						setFileName(currentDirectory.getPath());
					} else {
						setFileName(null);
					}
				}
			}
		}

		private void doFilterChanged(PropertyChangeEvent e) {
			clearIconCache();
		}

		private void doFileSelectionModeChanged(PropertyChangeEvent e) {
			if (fileNameLabel != null) {
				populateFileNameLabel();
			}
			clearIconCache();

			JFileChooser fc = getFileChooser();
			File currentDirectory = fc.getCurrentDirectory();
			if (currentDirectory != null && fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()
					&& fc.getFileSystemView().isFileSystem(currentDirectory)) {

				setFileName(currentDirectory.getPath());
			} else {
				setFileName(null);
			}
		}

		private void doAccessoryChanged(PropertyChangeEvent e) {
			if (getAccessoryPanel() != null) {
				if (e.getOldValue() != null) {
					getAccessoryPanel().remove((JComponent) e.getOldValue());
				}
				JComponent accessory = (JComponent) e.getNewValue();
				if (accessory != null) {
					getAccessoryPanel().add(accessory, BorderLayout.CENTER);
				}
			}
		}

		private void doApproveButtonTextChanged(PropertyChangeEvent e) {
			JFileChooser chooser = getFileChooser();
			approveButton.setText(getApproveButtonText(chooser));
			approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
		}

		private void doDialogTypeChanged(PropertyChangeEvent e) {
			JFileChooser chooser = getFileChooser();
			approveButton.setText(getApproveButtonText(chooser));
			approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
			if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) {
				lookInLabel.setText(saveInLabelText);
			} else {
				lookInLabel.setText(lookInLabelText);
			}
		}

		private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) {
			// Note: Metal does not use mnemonics for approve and cancel
		}

		private void doControlButtonsChanged(PropertyChangeEvent e) {
			if (getFileChooser().getControlButtonsAreShown()) {
				addControlButtons();
			} else {
				removeControlButtons();
			}
		}

		/*
		 * Listen for filechooser property changes, such as the selected file
		 * changing, or the type of the dialog changing.
		 */
		public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
			return new PropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent e) {
					String s = e.getPropertyName();
					if (s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
						doSelectedFileChanged(e);
					} else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
						doSelectedFilesChanged(e);
					} else if (s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
						doDirectoryChanged(e);
					} else if (s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
						doFilterChanged(e);
					} else if (s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
						doFileSelectionModeChanged(e);
					} else if (s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
						doAccessoryChanged(e);
					} else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY)
							|| s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) {
						doApproveButtonTextChanged(e);
					} else if (s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
						doDialogTypeChanged(e);
					} else if (s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
						doApproveButtonMnemonicChanged(e);
					} else if (s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
						doControlButtonsChanged(e);
					} else if (s.equals("componentOrientation")) {
						ComponentOrientation o = (ComponentOrientation) e.getNewValue();
						JFileChooser cc = (JFileChooser) e.getSource();
						if (o != e.getOldValue()) {
							cc.applyComponentOrientation(o);
						}
					} else if (s == "FileChooser.useShellFolder") {
						doDirectoryChanged(e);
					} else if (s.equals("ancestor")) {
						if (e.getOldValue() == null && e.getNewValue() != null) {
							// Ancestor was added, set initial focus
							fileNameTextField.selectAll();
							fileNameTextField.requestFocus();
						}
					}
				}
			};
		}

		protected void removeControlButtons() {
			getBottomPanel().remove(getButtonPanel());
		}

		protected void addControlButtons() {
			getBottomPanel().add(getButtonPanel());
		}

		public void ensureFileIsVisible(JFileChooser fc, File f) {
			filePane.ensureFileIsVisible(fc, f);
		}

		public void rescanCurrentDirectory(JFileChooser fc) {
			filePane.rescanCurrentDirectory();
		}

		public String getFileName() {
			if (fileNameTextField != null) {
				return fileNameTextField.getText();
			} else {
				return null;
			}
		}

		public void setFileName(String filename) {
			if (fileNameTextField != null) {
				fileNameTextField.setText(filename);
			}
		}

		/**
		 * Property to remember whether a directory is currently selected in the
		 * UI. This is normally called by the UI on a selection event.
		 * 
		 * @param directorySelected
		 *            if a directory is currently selected.
		 * @since 1.4
		 */
		protected void setDirectorySelected(boolean directorySelected) {
			super.setDirectorySelected(directorySelected);
			JFileChooser chooser = getFileChooser();
			if (directorySelected) {
				if (approveButton != null) {
					approveButton.setText(directoryOpenButtonText);
					approveButton.setToolTipText(directoryOpenButtonToolTipText);
				}
			} else {
				if (approveButton != null) {
					approveButton.setText(getApproveButtonText(chooser));
					approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
				}
			}
		}

		public String getDirectoryName() {
			// PENDING(jeff) - get the name from the directory combobox
			return null;
		}

		public void setDirectoryName(String dirname) {
			// PENDING(jeff) - set the name in the directory combobox
		}

		protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
			return new DirectoryComboBoxRenderer();
		}

		//
		// Renderer for DirectoryComboBox
		//
		class DirectoryComboBoxRenderer extends DefaultListCellRenderer {
			IndentIcon ii = new IndentIcon();

			public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {

				super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

				if (value == null) {
					setText("");
					return this;
				}
				File directory = (File) value;
				setText(getFileChooser().getName(directory));
				Icon icon = getFileChooser().getIcon(directory);
				ii.icon = icon;
				ii.depth = directoryComboBoxModel.getDepth(index);
				setIcon(ii);

				return this;
			}
		}

		final static int space = 10;

		class IndentIcon implements Icon {

			Icon icon = null;
			int depth = 0;

			public void paintIcon(Component c, Graphics g, int x, int y) {
				if (c.getComponentOrientation().isLeftToRight()) {
					icon.paintIcon(c, g, x + depth * space, y);
				} else {
					icon.paintIcon(c, g, x, y);
				}
			}

			public int getIconWidth() {
				return icon.getIconWidth() + depth * space;
			}

			public int getIconHeight() {
				return icon.getIconHeight();
			}

		}

		//
		// DataModel for DirectoryComboxbox
		//
		protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {
			return new DirectoryComboBoxModel();
		}

		/**
		 * Data model for a type-face selection combo-box.
		 */
		protected class DirectoryComboBoxModel extends AbstractListModel<Object> implements ComboBoxModel<Object> {
			Vector<File> directories = new Vector<File>();
			int[] depths = null;
			File selectedDirectory = null;
			JFileChooser chooser = getFileChooser();
			FileSystemView fsv = chooser.getFileSystemView();

			public DirectoryComboBoxModel() {
				// Add the current directory to the model, and make it the
				// selectedDirectory
				File dir = getFileChooser().getCurrentDirectory();
				if (dir != null) {
					addItem(dir);
				}
			}

			/**
			 * Adds the directory to the model and sets it to be selected,
			 * additionally clears out the previous selected directory and the
			 * paths leading up to it, if any.
			 */
			private void addItem(File directory) {

				if (directory == null) {
					return;
				}

				boolean useShellFolder = FilePane.usesShellFolder(chooser);

				directories.clear();

				File[] baseFolders;
				if (useShellFolder) {
					baseFolders = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
						public File[] run() {
							return (File[]) ShellFolder.get("fileChooserComboBoxFolders");
						}
					});
				} else {
					baseFolders = fsv.getRoots();
				}
				directories.addAll(Arrays.asList(baseFolders));

				// Get the canonical (full) path. This has the side
				// benefit of removing extraneous chars from the path,
				// for example /foo/bar/ becomes /foo/bar
				File canonical;
				try {
					canonical = ShellFolder.getNormalizedFile(directory);
				} catch (IOException e) {
					// Maybe drive is not ready. Can't abort here.
					canonical = directory;
				}

				// create File instances of each directory leading up to the top
				try {
					File sf = useShellFolder ? ShellFolder.getShellFolder(canonical) : canonical;
					File f = sf;
					Vector<File> path = new Vector<File>(10);
					do {
						path.addElement(f);
					} while ((f = f.getParentFile()) != null);

					int pathCount = path.size();
					// Insert chain at appropriate place in vector
					for (int i = 0; i < pathCount; i++) {
						f = path.get(i);
						if (directories.contains(f)) {
							int topIndex = directories.indexOf(f);
							for (int j = i - 1; j >= 0; j--) {
								directories.insertElementAt(path.get(j), topIndex + i - j);
							}
							break;
						}
					}
					calculateDepths();
					setSelectedItem(sf);
				} catch (FileNotFoundException ex) {
					calculateDepths();
				}
			}

			private void calculateDepths() {
				depths = new int[directories.size()];
				for (int i = 0; i < depths.length; i++) {
					File dir = directories.get(i);
					File parent = dir.getParentFile();
					depths[i] = 0;
					if (parent != null) {
						for (int j = i - 1; j >= 0; j--) {
							if (parent.equals(directories.get(j))) {
								depths[i] = depths[j] + 1;
								break;
							}
						}
					}
				}
			}

			public int getDepth(int i) {
				return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0;
			}

			public void setSelectedItem(Object selectedDirectory) {
				this.selectedDirectory = (File) selectedDirectory;
				fireContentsChanged(this, -1, -1);
			}

			public Object getSelectedItem() {
				return selectedDirectory;
			}

			public int getSize() {
				return directories.size();
			}

			public Object getElementAt(int index) {
				return directories.elementAt(index);
			}
		}

		//
		// Renderer for Types ComboBox
		//
		protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
			return new FilterComboBoxRenderer();
		}

		/**
		 * Render different type sizes and styles.
		 */
		public class FilterComboBoxRenderer extends DefaultListCellRenderer {
			{
				setFont(labelFont12);
			}

			public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {

				super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

				if (value != null && value instanceof FileFilter) {
					setText(((FileFilter) value).getDescription());
				}

				return this;
			}
		}

		//
		// DataModel for Types Comboxbox
		//
		protected FilterComboBoxModel createFilterComboBoxModel() {
			return new FilterComboBoxModel();
		}

		/**
		 * Data model for a type-face selection combo-box.
		 */
		protected class FilterComboBoxModel extends AbstractListModel<Object> implements ComboBoxModel<Object>, PropertyChangeListener {
			protected FileFilter[] filters;

			protected FilterComboBoxModel() {
				super();
				filters = getFileChooser().getChoosableFileFilters();
			}

			public void propertyChange(PropertyChangeEvent e) {
				String prop = e.getPropertyName();
				if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
					filters = (FileFilter[]) e.getNewValue();
					fireContentsChanged(this, -1, -1);
				} else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
					fireContentsChanged(this, -1, -1);
				}
			}

			public void setSelectedItem(Object filter) {
				if (filter != null) {
					getFileChooser().setFileFilter((FileFilter) filter);
					fireContentsChanged(this, -1, -1);
				}
			}

			public Object getSelectedItem() {
				// Ensure that the current filter is in the list.
				// NOTE: we shouldnt' have to do this, since JFileChooser adds
				// the filter to the choosable filters list when the filter
				// is set. Lets be paranoid just in case someone overrides
				// setFileFilter in JFileChooser.
				FileFilter currentFilter = getFileChooser().getFileFilter();
				boolean found = false;
				if (currentFilter != null) {
					for (FileFilter filter : filters) {
						if (filter == currentFilter) {
							found = true;
						}
					}
					if (found == false) {
						getFileChooser().addChoosableFileFilter(currentFilter);
					}
				}
				return getFileChooser().getFileFilter();
			}

			public int getSize() {
				if (filters != null) {
					return filters.length;
				} else {
					return 0;
				}
			}

			public Object getElementAt(int index) {
				if (index > getSize() - 1) {
					// This shouldn't happen. Try to recover gracefully.
					return getFileChooser().getFileFilter();
				}
				if (filters != null) {
					return filters[index];
				} else {
					return null;
				}
			}
		}

		public void valueChanged(ListSelectionEvent e) {
			JFileChooser fc = getFileChooser();
			File f = fc.getSelectedFile();
			if (!e.getValueIsAdjusting() && f != null && !getFileChooser().isTraversable(f)) {
				setFileName(fileNameString(f));
			}
		}

		/**
		 * Acts when DirectoryComboBox has changed the selected item.
		 */
		protected class DirectoryComboBoxAction extends AbstractAction {
			protected DirectoryComboBoxAction() {
				super("DirectoryComboBoxAction");
			}

			public void actionPerformed(ActionEvent e) {
				directoryComboBox.hidePopup();
				File f = (File) directoryComboBox.getSelectedItem();
				if (!getFileChooser().getCurrentDirectory().equals(f)) {
					getFileChooser().setCurrentDirectory(f);
				}
			}
		}

		protected JButton getApproveButton(JFileChooser fc) {
			return approveButton;
		}

		/**
		 * <code>ButtonAreaLayout</code> behaves in a similar manner to
		 * <code>FlowLayout</code>. It lays out all components from left to
		 * right, flushed right. The widths of all components will be set to the
		 * largest preferred size width.
		 */
		private static class ButtonAreaLayout implements LayoutManager {
			private int hGap = 5;
			private int topMargin = 17;

			public void addLayoutComponent(String string, Component comp) {
			}

			public void layoutContainer(Container container) {
				Component[] children = container.getComponents();

				if (children != null && children.length > 0) {
					int numChildren = children.length;
					Dimension[] sizes = new Dimension[numChildren];
					Insets insets = container.getInsets();
					int yLocation = insets.top + topMargin;
					int maxWidth = 0;

					for (int counter = 0; counter < numChildren; counter++) {
						sizes[counter] = children[counter].getPreferredSize();
						maxWidth = Math.max(maxWidth, sizes[counter].width);
					}
					int xLocation, xOffset;
					if (container.getComponentOrientation().isLeftToRight()) {
						xLocation = container.getSize().width - insets.left - maxWidth;
						xOffset = hGap + maxWidth;
					} else {
						xLocation = insets.left;
						xOffset = -(hGap + maxWidth);
					}
					for (int counter = numChildren - 1; counter >= 0; counter--) {
						children[counter].setBounds(xLocation, yLocation, maxWidth, sizes[counter].height);
						xLocation -= xOffset;
					}
				}
			}

			public Dimension minimumLayoutSize(Container c) {
				if (c != null) {
					Component[] children = c.getComponents();

					if (children != null && children.length > 0) {
						int numChildren = children.length;
						int height = 0;
						Insets cInsets = c.getInsets();
						int extraHeight = topMargin + cInsets.top + cInsets.bottom;
						int extraWidth = cInsets.left + cInsets.right;
						int maxWidth = 0;

						for (int counter = 0; counter < numChildren; counter++) {
							Dimension aSize = children[counter].getPreferredSize();
							height = Math.max(height, aSize.height);
							maxWidth = Math.max(maxWidth, aSize.width);
						}
						return new Dimension(extraWidth + numChildren * maxWidth + (numChildren - 1) * hGap, extraHeight + height);
					}
				}
				return new Dimension(0, 0);
			}

			public Dimension preferredLayoutSize(Container c) {
				return minimumLayoutSize(c);
			}

			public void removeLayoutComponent(Component c) {
			}
		}

		private static void groupLabels(AlignedLabel[] group) {
			for (int i = 0; i < group.length; i++) {
				group[i].group = group;
			}
		}

		private class AlignedLabel extends JLabel {
			private AlignedLabel[] group;
			private int maxWidth = 0;

			AlignedLabel() {
				super();
			}

			AlignedLabel(String text) {
				super(text);
			}

			{
				setAlignmentX(JComponent.LEFT_ALIGNMENT);
				setFont(labelFont14);
			}

			public Dimension getPreferredSize() {
				Dimension d = super.getPreferredSize();
				// Align the width with all other labels in group.
				return new Dimension(getMaxWidth() + 11, d.height);
			}

			private int getMaxWidth() {
				if (maxWidth == 0 && group != null) {
					int max = 0;
					for (int i = 0; i < group.length; i++) {
						max = Math.max(group[i].getSuperPreferredWidth(), max);
					}
					for (int i = 0; i < group.length; i++) {
						group[i].maxWidth = max;
					}
				}
				return maxWidth;
			}

			private int getSuperPreferredWidth() {
				return super.getPreferredSize().width;
			}
		}

		@Override
		public void clearIconCache() {
			fileView.clearIconCache();
		}

		@Override
		public FileView getFileView(JFileChooser fc) {
			return fileView;
		}

		// ***********************
		// * FileView operations *
		// ***********************
		protected class CustomFileView extends BasicFileView {

			public Icon getIcon(File f) {
				Icon icon = getCachedIcon(f);
				if (icon != null) {
					return icon;
				}
				icon = FileSystemView.getFileSystemView().getSystemIcon(f);
				cacheIcon(f, icon);
				return icon;
			}
		}
	}

	///////////////////////////////////////////////////////////////

	public static Window getWindowForComponent(Component parentComponent) throws HeadlessException {
		if (parentComponent == null)
			return JOptionPane.getRootFrame();
		if (parentComponent instanceof Window)
			return (Window) parentComponent;
		return getWindowForComponent(parentComponent.getParent());
	}

	public static void setLocationRelativeTo(Component parent, Window child) {
		if (parent == null) {
			child.setLocationRelativeTo(null);
		} else {
			Window window = getWindowForComponent(parent);
			if (window != null && window.isShowing()) {
				child.setLocationRelativeTo(parent);
			} else {
				child.setLocationRelativeTo(null);
			}
		}
	}

	/**
	 * 将原Icon位置移动的Icon
	 * 
	 * @author PC
	 * 
	 */
	public static class MoveIcon implements Icon {
		Icon icon;
		int moveX;
		int moveY;

		public MoveIcon(Icon icon, int moveX, int moveY) {
			this.icon = icon;
			this.moveX = moveX;
			this.moveY = moveY;
		}

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y) {
			icon.paintIcon(c, g, x + moveX, y + moveY);
		}

		@Override
		public int getIconWidth() {
			return icon.getIconWidth();
		}

		@Override
		public int getIconHeight() {
			return icon.getIconHeight();
		}
	}

	/**
	 * 箭头Icon
	 * 
	 * @author tang
	 */
	public static class ArrowIcon implements Icon {

		protected int iconWidth;
		protected int iconHeight;
		protected int triangleWidth;
		protected int triangleHeight;
		protected Color triangleColor;
		protected int direction;
		protected Polygon triangle = new Polygon();

		public ArrowIcon(int width, int height, Color arrowColor, int direction) {
			this(width, height, width, height, arrowColor, direction);
		}

		public ArrowIcon(int iconWidth, int iconHeight, int triangleWidth, int triangleHeight, Color triangleColor, int direction) {
			this.iconWidth = iconWidth;
			this.iconHeight = iconHeight;
			this.triangleWidth = triangleWidth;
			this.triangleHeight = triangleHeight;
			this.triangleColor = triangleColor;
			this.direction = direction;

			createTriangle();
		}

		protected void createTriangle() {
			int x = (iconWidth - triangleWidth) / 2;
			int y = (iconHeight - triangleHeight) / 2;

			if (direction == SwingConstants.TOP) {// 箭头向上
				triangle.addPoint(triangleWidth / 2 + x, y);
				triangle.addPoint(triangleWidth + x, triangleHeight + y);
				triangle.addPoint(x, triangleHeight + y);
			} else if (direction == SwingConstants.BOTTOM) {// 箭头向下
				triangle.addPoint(x, y);
				triangle.addPoint(triangleWidth + x, y);
				triangle.addPoint(triangleWidth / 2 + x, triangleHeight + y);
			} else if (direction == SwingConstants.LEFT) {
				triangle.addPoint(x, triangleHeight / 2 + y);
				triangle.addPoint(triangleWidth + x, y);
				triangle.addPoint(triangleWidth + x, triangleHeight + y);
			} else if (direction == SwingConstants.RIGHT) {
				triangle.addPoint(x, y);
				triangle.addPoint(triangleWidth + x, triangleHeight / 2 + y);
				triangle.addPoint(x, triangleHeight + y);
			}
		}

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g2.setColor(triangleColor);
			AffineTransform af = new AffineTransform();
			af.translate(x, y);
			Shape shape = af.createTransformedShape(triangle);
			g2.fill(shape);
		}

		@Override
		public int getIconWidth() {
			return iconWidth;
		}

		@Override
		public int getIconHeight() {
			return iconHeight;
		}
	}
}


二、CustomFileChooser所需要的类RolloverBackgroundButton

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;

import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;

/**
 * 鼠标悬浮和按下以及选中时能切换背景颜色/边框颜色/前景颜色的Button
 * 
 * @author tang
 * @since 2014/8/23
 * 
 */
public class RolloverBackgroundButton extends JButton {

	private static final long serialVersionUID = 1L;

	protected Color normalBackground;// 默认无状态时背景颜色,此属性父类中已定义(background)
	protected Color pressedBackground;// 鼠标按下时背景颜色
	protected Color rolloverBackground;// 鼠标悬浮时背景颜色
	protected Color selectedBackground;// 选中时背景颜色

	protected Color normalBorderColor;// 默认无状态时边框颜色
	protected Color pressedBorderColor;// 鼠标按下时边框颜色
	protected Color rolloverBorderColor;// 鼠标悬浮时边框颜色
	protected Color selectedBorderColor;// 选中时边框颜色

	protected Color normalForeground;// 默认时前景颜色
	protected Color pressedForeground;// 鼠标按下时前景颜色
	protected Color rolloverForeground;// 鼠标悬浮时前景颜色
	protected Color selectedForeground;// 选中时前景颜色

	{
		initRolloverButton();
	}

	public RolloverBackgroundButton() {
	}

	public RolloverBackgroundButton(Icon icon) {
		super(icon);
	}

	public RolloverBackgroundButton(String text, Icon icon) {
		super(text, icon);
	}

	public RolloverBackgroundButton(String text) {
		super(text);
	}

	public RolloverBackgroundButton(Action a) {
		super(a);
	}

	private void initRolloverButton() {
		setRolloverEnabled(true);
		setBorderPainted(false);
		setContentAreaFilled(false);
		setFocusPainted(false);
		setFont(new Font(Font.DIALOG, Font.PLAIN, 14));

		setNormalBackground(new Color(216, 216, 216));
		setPressedBackground(new Color(216, 216, 216, 100));
		setNormalBorderColor(new Color(174, 174, 174));
		setRolloverBorderColor(new Color(95, 205, 245));
		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
	}

	@Override
	public void paint(Graphics g) {
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		Paint oldPaint = g2d.getPaint();
		if (isSelected() && selectedBackground != null) {// 选中时
			g2d.setPaint(selectedBackground);
			g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
		} else if (getModel().isPressed() && pressedBackground != null) {// 鼠标按下时
			g2d.setPaint(pressedBackground);
			g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
		} else if (getModel().isRollover() && rolloverBackground != null) {// 鼠标悬浮时
			g2d.setPaint(rolloverBackground);
			g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
		} else if (normalBackground != null) {// 默认无状态时
			g2d.setPaint(normalBackground);
			g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
		}
		g2d.setPaint(oldPaint);

		if (isSelected() && selectedForeground != null) {// 选中时
			setForeground(selectedForeground);
		} else if (getModel().isPressed() && pressedForeground != null) {// 鼠标按下时
			setForeground(pressedForeground);
		} else if (getModel().isRollover() && rolloverForeground != null) {// 鼠标悬浮时
			setForeground(rolloverForeground);
		} else if (normalForeground != null) {// 默认无状态时
			setForeground(normalForeground);
		}

		super.paint(g2d);

		if (isSelected() && selectedBorderColor != null) {// 选中时
			g2d.setPaint(selectedBorderColor);
			g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
		} else if (getModel().isPressed() && pressedBorderColor != null) {// 鼠标按下时
			g2d.setPaint(pressedBorderColor);
			g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
		} else if (getModel().isRollover() && rolloverBorderColor != null) {// 鼠标悬浮时
			g2d.setPaint(rolloverBorderColor);
			g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
		} else if (normalBorderColor != null) {// 默认无状态时
			g2d.setPaint(normalBorderColor);
			g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
		}
		g2d.setPaint(oldPaint);
	}

	/**
	 * 清空设置的默认属性值:<br>
	 * 
	 * setNormalBackground(null);<br>
	 * setPressedBackground(null); <br>
	 * setNormalBorderColor(null); <br>
	 * setRolloverBorderColor(null);
	 * 
	 */
	public void clearDefaultAttribute() {
		setNormalBackground(null);
		setPressedBackground(null);
		setNormalBorderColor(null);
		setRolloverBorderColor(null);
	}

	public Color getNormalBackground() {
		return normalBackground;
	}

	public void setNormalBackground(Color normalBackground) {
		this.normalBackground = normalBackground;
	}

	public Color getPressedBackground() {
		return pressedBackground;
	}

	public void setPressedBackground(Color pressedBackground) {
		this.pressedBackground = pressedBackground;
	}

	public Color getRolloverBackground() {
		return rolloverBackground;
	}

	public void setRolloverBackground(Color rolloverBackground) {
		this.rolloverBackground = rolloverBackground;
	}

	public Color getNormalBorderColor() {
		return normalBorderColor;
	}

	public void setNormalBorderColor(Color normalBorderColor) {
		this.normalBorderColor = normalBorderColor;
	}

	public Color getPressedBorderColor() {
		return pressedBorderColor;
	}

	public void setPressedBorderColor(Color pressedBorderColor) {
		this.pressedBorderColor = pressedBorderColor;
	}

	public Color getRolloverBorderColor() {
		return rolloverBorderColor;
	}

	public void setRolloverBorderColor(Color rolloverBorderColor) {
		this.rolloverBorderColor = rolloverBorderColor;
	}

	public Color getPressedForeground() {
		return pressedForeground;
	}

	public void setPressedForeground(Color pressedForeground) {
		this.pressedForeground = pressedForeground;
	}

	public Color getRolloverForeground() {
		return rolloverForeground;
	}

	public void setRolloverForeground(Color rolloverForeground) {
		this.rolloverForeground = rolloverForeground;
	}

	public Color getNormalForeground() {
		return normalForeground;
	}

	public void setNormalForeground(Color normalForeground) {
		this.normalForeground = normalForeground;
	}

	public Color getSelectedBackground() {
		return selectedBackground;
	}

	public void setSelectedBackground(Color selectedBackground) {
		this.selectedBackground = selectedBackground;
	}

	public Color getSelectedBorderColor() {
		return selectedBorderColor;
	}

	public void setSelectedBorderColor(Color selectedBorderColor) {
		this.selectedBorderColor = selectedBorderColor;
	}

	public Color getSelectedForeground() {
		return selectedForeground;
	}

	public void setSelectedForeground(Color selectedForeground) {
		this.selectedForeground = selectedForeground;
	}
}

三、CustomFileChooser所需要的类CustomComboBox

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.Serializable;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;

import test.CustomFileChooser.ArrowIcon;
import test.CustomFileChooser.MoveIcon;

/**
 * 自定义下拉框
 * <p>
 * 
 * @author tang
 */
@SuppressWarnings({ "rawtypes", "unchecked", "serial" })
public class CustomComboBox<E> extends JComboBox<E> {

	protected Icon arrowIcon = new ArrowIcon(16, 10, 10, 10, Color.decode("#707070"), SwingConstants.BOTTOM);

	protected Color selectionBackground;
	protected Color selectionForeground;
	protected Color popupBackground;
	protected Color popupForeground;
	protected Border popupBorder;

	public CustomComboBox() {
		super();
		init();
	}

	public CustomComboBox(ComboBoxModel<E> aModel) {
		super(aModel);
		init();
	}

	public CustomComboBox(E[] items) {
		super(items);
		init();
	}

	public CustomComboBox(Vector<E> items) {
		super(items);
		init();
	}

	public CustomComboBox(Icon arrowIcon) {
		super();
		this.arrowIcon = arrowIcon;
		init();
	}

	private void init() {

		setUI(new CustomComboBoxUI());
		setOpaque(true);
		setForeground(Color.decode("#9a9a9a"));
		setBackground(Color.WHITE);
		Border lineBorder = BorderFactory.createLineBorder(Color.decode("#c5c7c8"));
		setBorder(lineBorder);
		setFont(new Font(Font.DIALOG, Font.PLAIN, 16));
		setPopupForeground(getForeground());
		setPopupBackground(getBackground());
		setSelectionBackground(Color.LIGHT_GRAY);
		// getPopup().setOpaque(true);
		// getPopup().setBackground(popupBackground);
		setPopupBorder(lineBorder);
		setRenderer(new CustomComboBoxRenderer());
	}

	@Override
	public synchronized void addMouseListener(MouseListener l) {
		super.addMouseListener(l);
		if (getArrowButton() != null) {
			getArrowButton().addMouseListener(l);
		}
	}

	public void setSelectionBackground(Color selectionBackground) {
		this.selectionBackground = selectionBackground;
		getPopup().getList().setSelectionBackground(selectionBackground);
	}

	public void setSelectionForeground(Color selectionForeground) {
		this.selectionForeground = selectionForeground;
		getPopup().getList().setSelectionForeground(selectionForeground);
	}

	public void setPopupBackground(Color popupBackground) {
		this.popupBackground = popupBackground;
		getPopup().getList().setBackground(popupBackground);
	}

	public void setPopupForeground(Color popupForeground) {
		this.popupForeground = popupForeground;
		getPopup().getList().setForeground(popupForeground);
	}

	public void setPopupBorder(Border popupBorder) {
		this.popupBorder = popupBorder;
		getPopup().setBorder(popupBorder);
	}

	public void setArrowIcon(Icon icon) {
		this.arrowIcon = icon;
		updateUI();
	}

	@Override
	public void setUI(ComboBoxUI ui) {
		if (ui instanceof CustomComboBoxUI) {
			super.setUI(ui);
		} else {
			super.setUI(new CustomComboBoxUI());
		}
	}

	@Override
	public void updateUI() {

		setUI(new CustomComboBoxUI());

		setSelectionBackground(selectionBackground);
		setSelectionForeground(selectionForeground);
		setPopupBackground(popupBackground);
		setPopupForeground(popupForeground);
		setPopupBorder(popupBorder);

		ListCellRenderer<?> renderer = getRenderer();
		if (renderer instanceof Component) {
			SwingUtilities.updateComponentTreeUI((Component) renderer);
		}
	}

	/**
	 * 如果想将ComboBox的Background和Foreground与弹出的Popup的Background和Foreground保持一致则可以调用此方法
	 */
	public void synchGroundToPopup() {
		setPopupBackground(getBackground());
		setPopupForeground(getForeground());
	}

	/**
	 * 如果想将ComboBox的Background和Foreground和Border与弹出的Popup的Background和Foreground和Border保持一致则可以调用此方法
	 */
	public void synchAllToPopup() {
		setPopupBackground(getBackground());
		setPopupForeground(getForeground());
		setPopupBorder(getBorder());
	}

	/**
	 * 设置ComboBox的Background和Popup的Background
	 * 
	 * @param color
	 */
	public void setBackgroundAndToPopup(Color color) {
		setBackground(color);
		setPopupBackground(color);
	}

	/**
	 * 设置ComboBox的Foreground和Popup的Foreground
	 * 
	 * @param color
	 */
	public void setForegroundAndToPopup(Color color) {
		setForeground(color);
		setPopupForeground(color);
	}

	/**
	 * 设置ComboBox的Border和Popup的Border
	 * 
	 * @param border
	 */
	public void setBorderAndToPopup(Border border) {
		setBorder(border);
		setPopupBorder(border);
	}

	public Icon getArrowIcon() {
		if (arrowIcon == null) {
			arrowIcon = new ArrowIcon(16, 10, 12, 10, Color.decode("#707070"), SwingConstants.BOTTOM);
		}
		return arrowIcon;
	}

	public BasicComboPopup getPopup() {
		return ((CustomComboBoxUI) getUI()).getPopup();
	}

	public JButton getArrowButton() {
		return ((CustomComboBoxUI) getUI()).getArrowButton();
	}

	public static boolean isMenuShortcutKeyDown(InputEvent event) {
		return (event.getModifiers() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0;
	}

	public static class CustomList<E> extends JList<E> {

		public CustomList() {
			super();
		}

		public CustomList(E[] listData) {
			super(listData);
		}

		public CustomList(ListModel<E> dataModel) {
			super(dataModel);
		}

		public CustomList(Vector<? extends E> listData) {
			super(listData);
		}

		@Override
		public void processMouseEvent(MouseEvent e) {
			if (isMenuShortcutKeyDown(e)) {
				// Fix for 4234053. Filter out the Control Key from the list.
				// ie., don't allow CTRL key deselection.
				Toolkit toolkit = Toolkit.getDefaultToolkit();
				e = new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(), e.getX(), e.getY(),
						e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON);
			}
			super.processMouseEvent(e);
		}
	}

	public static class CustomComboBoxUI extends MetalComboBoxUI {

		@Override
		protected JButton createArrowButton() {
			final CustomComboBox box = (CustomComboBox) comboBox;
			Icon arrowIcon = box.getArrowIcon();
			JButton button = new JButton(arrowIcon);
			button.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
			button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
			button.setHorizontalTextPosition(SwingConstants.CENTER);
			button.setVerticalTextPosition(SwingConstants.CENTER);
			button.setRolloverEnabled(true);
			button.setFocusPainted(false);
			button.setOpaque(false);
			button.setContentAreaFilled(false);
			button.setBorderPainted(false);
			button.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
			if (arrowIcon != null) {
				button.setPressedIcon(new MoveIcon(arrowIcon, 0, 1));
			}
			button.setName("ComboBox.arrowButton");
			return button;
		}

		/**
		 * Paints the currently selected item.
		 */
		@Override
		public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) {
			Component c = comboBox.getRenderer().getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, hasFocus && !isPopupVisible(comboBox),
					false);
			c.setBackground(comboBox.getBackground());// 清除渲染器原来设置的背景色,将渲染器的背景设置成ComboBox的背景色
			c.setForeground(comboBox.getForeground());// 清除渲染器原来设置的前景色,将渲染器的前景设置成ComboBox的前景色
			if (c instanceof JComponent) {
				JComponent jc = (JComponent) c;
				jc.setOpaque(comboBox.isOpaque());
			}

			int x = bounds.x, y = bounds.y, w = bounds.width, h = bounds.height;
			if (padding != null) {
				x = bounds.x + padding.left;
				y = bounds.y + padding.top;
				w = bounds.width - (padding.left + padding.right);
				h = bounds.height - (padding.top + padding.bottom);
			}

			currentValuePane.paintComponent(g, c, comboBox, x, y, w, h, c instanceof JPanel);
		}

		/**
		 * Paints the background of the currently selected item.
		 */
		@Override
		public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) {
			Color t = g.getColor();
			g.setColor(comboBox.getBackground());
			g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
			g.setColor(t);
		}

		public BasicComboPopup getPopup() {
			return (BasicComboPopup) popup;
		}

		public JButton getArrowButton() {
			return arrowButton;
		}
	}

	public static class CustomComboBoxRenderer extends DefaultListCellRenderer implements ListCellRenderer<Object>, Serializable {

		private Border rendererBorder = BorderFactory.createEmptyBorder(0, 5, 0, 5);

		public CustomComboBoxRenderer() {
			setBorder(rendererBorder);
		}

		@Override
		public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
			super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
			setBorder(rendererBorder);
			return this;
		}

		public Border getRendererBorder() {
			return rendererBorder;
		}

		public void setRendererBorder(Border rendererBorder) {
			this.rendererBorder = rendererBorder;
		}
	}
}

运行效果:





© 著作权归作者所有

思想永无止境
粉丝 4
博文 257
码字总数 292814
作品 0
昌平
程序员
私信 提问
JLunarDatePicke r0.1 发布,农历日期选择器

JLunarDatePicker是中国农历日期选择器,是开源的Java Swing包 示例代码: 运行结果: 实例化JLunarDatePicker时,有两个构造函数: 1.JLunarDatePicker(),获取默认风格的日历选择器对象 ...

刘学炜
2013/03/05
2.7K
31
JFormDesigner 5.2 发布,Swing 设计工具

JFormDesigner 5.2 发布,此版本引入了 JDeveloper 插件;支持 Java 8 和 JGoodies Forms 1.8;改进了 GroupLayout 设计;提供 GroupLayout 差异可视化;改进了树文件选择器。 JFormDesigne...

oschina
2014/05/20
4.9K
4
monkeyk7/jcalendarchooser

#jcalendarchooser Java Swing 日期,日期时间选择组件 使用要求: JDK 1.6 + 截图 JCalendarChooser JTimeChooser 说明与使用 JCalendarChooser 封装的日期选择器 使用: 1.创建JCalendarChoo...

monkeyk7
2015/01/06
0
0
前端(jQuery样式操作、特殊效果、动画......)

1、jQuery选择器 2、选择器转移 prev()是同级的上一个元素,prevAll()是同级的上面所有的元素 next()是同级的下一个元素,nextAll()是同级的下面所有的元素 3、样式操作 <...

埃菲尔上的铁塔梦i
2018/08/27
0
0
轴动效果插件,类似Github404页面

轴动效果 axial3d 3D效果页插件,类似 Github404 页面动画。 安装引入 Install or 例子 Example Demo 属性 Props options imgs options 方法 Methods 喜欢的欢迎star👏👏...

bestvist
2018/10/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【AI实战】手把手教你深度学习文字识别(文字检测篇:基于MSER, CTPN, SegLink, EAST等方法)

文字检测是文字识别过程中的一个非常重要的环节,文字检测的主要目标是将图片中的文字区域位置检测出来,以便于进行后面的文字识别,只有找到了文本所在区域,才能对其内容进行识别。 文字检...

雪饼
今天
5
0
思维导图XMind 8 Pro 绿化方法(附序列号)

按部就班: Step 1 -全新下载最新版本的 Xmind 8(注必须是英文官方的版本,中文代{过}{滤}理网站的版本修改过,无法使用pj); Step 2 -安装完毕后,点击文末的下载按钮下载pj补丁文件包,将...

一只小青蛙
今天
10
0
数据结构(ER数据库)设计规范

表命名规范 表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为: [leavel]_[type]_[name] [leavel] 表示数据库表的层级和功能,分为: s:业务无关的系统...

随风溜达的向日葵
今天
5
0
阿里Sentinel控制台源码修改-对接Apollo规则持久化

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel 动态规则扩展 https://github.com/alibaba/Sentinel/wiki......

jxlgzwh
昨天
7
0
在Linux系统中创建SSH服务器别名

如果你经常通过 SSH 访问许多不同的远程系统,这个技巧将为你节省一些时间。你可以通过 SSH 为频繁访问的系统创建 SSH 别名,这样你就不必记住所有不同的用户名、主机名、SSH 端口号和 IP 地...

老孟的Linux私房菜
昨天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部