forked from fanruan/design
zheng
6 years ago
8 changed files with 923 additions and 335 deletions
@ -0,0 +1,233 @@
|
||||
package com.fr.design.gui.icombocheckbox; |
||||
|
||||
import com.fr.base.BaseUtils; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.imenu.UIPopupMenu; |
||||
import com.fr.design.icon.IconPathConstants; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.awt.event.*; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class UICheckListPopup extends UIPopupMenu { |
||||
private List<ActionListener> listeners = new ArrayList<ActionListener>(); |
||||
private List<JCheckBox> checkBoxList = new ArrayList<JCheckBox>(); |
||||
|
||||
private Object[] values; |
||||
private JPanel checkboxPane; |
||||
private UIScrollPane jScrollPane; |
||||
private Color mouseEnteredColor = UIConstants.CHECKBOX_HOVER_SELECTED; |
||||
private int maxDisplayNumber = 8; |
||||
|
||||
public static final String COMMIT_EVENT = "commit"; |
||||
public static final String SELECT_ALL = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Choose_All"); |
||||
private static final int CHECKBOX_HEIGHT = 25; |
||||
|
||||
public UICheckListPopup(Object[] value) { |
||||
super(); |
||||
values = value; |
||||
initComponent(); |
||||
} |
||||
|
||||
public void setMouseEnteredColor(Color color) { |
||||
this.mouseEnteredColor = color; |
||||
} |
||||
|
||||
public void setMaxDisplayNumber(int maxDisplayNumber) { |
||||
this.maxDisplayNumber = maxDisplayNumber; |
||||
addCheckboxValues(values); |
||||
} |
||||
|
||||
private void initComponent() { |
||||
checkboxPane = new JPanel(); |
||||
checkboxPane.setLayout(new GridLayout(checkBoxList.size(), 1, 0, 0)); |
||||
checkboxPane.setBackground(Color.WHITE); |
||||
jScrollPane = new UIScrollPane(checkboxPane); |
||||
|
||||
this.setLayout(new BorderLayout()); |
||||
this.add(jScrollPane, BorderLayout.CENTER); |
||||
|
||||
addCheckboxValues(values); |
||||
} |
||||
|
||||
public void addCheckboxValues(Object[] value) { |
||||
checkboxPane.removeAll(); |
||||
checkBoxList.clear(); |
||||
|
||||
//全选加在第一个位置
|
||||
addOneCheckValue(SELECT_ALL); |
||||
for (Object checkValue : value) { |
||||
addOneCheckValue(checkValue); |
||||
} |
||||
addSelectListener(); |
||||
|
||||
jScrollPane.setPreferredSize(new Dimension(200, checkBoxList.size() * CHECKBOX_HEIGHT + 10)); |
||||
//超过1页的数量时显示滚动条
|
||||
if (checkBoxList.size() > maxDisplayNumber) { |
||||
jScrollPane.setPreferredSize(new Dimension(200, maxDisplayNumber * CHECKBOX_HEIGHT)); |
||||
} |
||||
checkboxPane.repaint(); |
||||
jScrollPane.repaint(); |
||||
} |
||||
|
||||
private void addOneCheckValue(Object checkValue) { |
||||
JPanel checkPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||
checkPane.setPreferredSize(new Dimension(185, CHECKBOX_HEIGHT)); |
||||
final JCheckBox temp = createCheckbox(); |
||||
final UILabel label = new UILabel(checkValue.toString()); |
||||
label.setBackground(Color.WHITE); |
||||
label.setPreferredSize(new Dimension(156, 20)); |
||||
checkPane.setBackground(Color.WHITE); |
||||
checkPane.add(temp); |
||||
checkPane.add(label); |
||||
addMouseListener(temp, label); |
||||
|
||||
checkBoxList.add(temp); |
||||
checkboxPane.add(checkPane); |
||||
} |
||||
|
||||
private JCheckBox createCheckbox() { |
||||
JCheckBox checkBox = new JCheckBox(); |
||||
checkBox.setPreferredSize(new Dimension(20, 20)); |
||||
checkBox.setBackground(Color.WHITE); |
||||
checkBox.setIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_NORMAL)); |
||||
checkBox.setSelectedIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_SELECTED)); |
||||
|
||||
return checkBox; |
||||
} |
||||
|
||||
/** |
||||
* 设置鼠标事件,鼠标进入时背景色变换 |
||||
* |
||||
* @param checkBox |
||||
* @param label |
||||
*/ |
||||
private void addMouseListener(final JCheckBox checkBox, final UILabel label) { |
||||
label.addMouseListener(new MouseAdapter() { |
||||
public void mouseExited(MouseEvent e) { |
||||
label.setBackground(Color.WHITE); |
||||
} |
||||
|
||||
public void mouseEntered(MouseEvent e) { |
||||
label.setOpaque(true); |
||||
label.setBackground(mouseEnteredColor); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
checkBox.doClick(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 单选框选中事件 |
||||
*/ |
||||
private void addSelectListener() { |
||||
for (int i = 0; i < checkBoxList.size(); i++) { |
||||
JCheckBox checkBox = checkBoxList.get(i); |
||||
if (i == 0) { |
||||
checkBox.addItemListener(new ItemListener() { |
||||
public void itemStateChanged(ItemEvent e) { |
||||
//全选checkbox事件
|
||||
doSelectAll(checkBoxList.get(0).isSelected()); |
||||
} |
||||
}); |
||||
} else { |
||||
checkBox.addItemListener(new ItemListener() { |
||||
public void itemStateChanged(ItemEvent e) { |
||||
//do半选判断放在commit事件里
|
||||
commit(); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 全选 |
||||
* |
||||
* @param isSelected 选中是true,未选是false |
||||
*/ |
||||
private void doSelectAll(boolean isSelected) { |
||||
for (int i = 1; i < checkBoxList.size(); i++) { |
||||
//全选和反全选都不考虑全选按钮本身
|
||||
if (!SELECT_ALL.equals(checkBoxList.get(i).getText())) |
||||
checkBoxList.get(i).setSelected(isSelected); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取所有选中的值 |
||||
* |
||||
* @return |
||||
*/ |
||||
public Object[] getSelectedValues() { |
||||
List<Object> selectedValues = new ArrayList<Object>(); |
||||
int selectCount = 0; |
||||
|
||||
for (int i = 1; i < checkBoxList.size(); i++) { |
||||
if (checkBoxList.get(i).isSelected()) { |
||||
selectedValues.add(values[i - 1]); |
||||
selectCount++; |
||||
} |
||||
} |
||||
//全选半选切换
|
||||
switchSelectIcon(selectCount); |
||||
|
||||
return selectedValues.toArray(new Object[selectedValues.size()]); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 切换全选半选图片 |
||||
*/ |
||||
private void switchSelectIcon(int selectCount) { |
||||
JCheckBox checkBox = checkBoxList.get(0); |
||||
if (selectCount == 0) { |
||||
checkBox.setIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_NORMAL)); |
||||
} else if (selectCount < checkBoxList.size() - 1) { |
||||
//虽然有选中,但是要判断此时全选状态去换图标
|
||||
if (checkBoxList.get(0).isSelected()) { |
||||
checkBox.setSelectedIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_HATFSELECT)); |
||||
} else { |
||||
checkBox.setIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_HATFSELECT)); |
||||
} |
||||
} else { |
||||
//全选了,图标要换回来
|
||||
checkBox.setSelectedIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_SELECTED)); |
||||
} |
||||
} |
||||
|
||||
public void commit() { |
||||
fireActionPerformed(new ActionEvent(this, 0, COMMIT_EVENT)); |
||||
} |
||||
|
||||
@Override |
||||
public Insets getInsets() { |
||||
return new Insets(0, 0, 0, 0); |
||||
} |
||||
|
||||
public void addActionListener(ActionListener listener) { |
||||
if (!listeners.contains(listener)) |
||||
listeners.add(listener); |
||||
} |
||||
|
||||
public void removeActionListener(ActionListener listener) { |
||||
if (listeners.contains(listener)) { |
||||
listeners.remove(listener); |
||||
} |
||||
} |
||||
|
||||
protected void fireActionPerformed(ActionEvent e) { |
||||
for (ActionListener l : listeners) { |
||||
l.actionPerformed(e); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,330 @@
|
||||
package com.fr.design.gui.icombocheckbox; |
||||
|
||||
import com.fr.base.BaseUtils; |
||||
import com.fr.design.event.GlobalNameListener; |
||||
import com.fr.design.event.GlobalNameObserver; |
||||
import com.fr.design.event.UIObserver; |
||||
import com.fr.design.event.UIObserverListener; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.icon.IconPathConstants; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 设计器下拉复选框组件 |
||||
* 支持全选、半选 |
||||
* 可以设置悬停颜色、一页最多显示单选框个数 |
||||
* 可以省略显示 |
||||
*/ |
||||
public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNameObserver { |
||||
//下拉框的值
|
||||
private Object[] values; |
||||
//已经选中的值
|
||||
private Object[] selectedValues; |
||||
|
||||
private List<ActionListener> listeners = new ArrayList<ActionListener>(); |
||||
private UICheckListPopup popup; |
||||
private UITextField editor; |
||||
private UIButton arrowButton; |
||||
//选中的值之间显示的分隔符
|
||||
private String valueSperator; |
||||
private static final String DEFAULT_VALUE_SPERATOR = ","; |
||||
private static final String OMIT_TEXT = "..."; |
||||
|
||||
private UIObserverListener uiObserverListener; |
||||
private GlobalNameListener globalNameListener = null; |
||||
private String multiComboName = StringUtils.EMPTY; |
||||
private boolean showOmitText = true; |
||||
|
||||
public UIComboCheckBox(Object[] value) { |
||||
this(value, DEFAULT_VALUE_SPERATOR); |
||||
} |
||||
|
||||
/** |
||||
* 自定义分隔符的复选框 |
||||
* |
||||
* @param value |
||||
* @param valueSperator |
||||
*/ |
||||
public UIComboCheckBox(Object[] value, String valueSperator) { |
||||
values = value; |
||||
this.valueSperator = valueSperator; |
||||
initComponent(); |
||||
} |
||||
|
||||
/** |
||||
* 设置鼠标悬停的背景色 |
||||
* |
||||
* @param color |
||||
*/ |
||||
public void setCheckboxEnteredColor(Color color) { |
||||
this.popup.setMouseEnteredColor(color); |
||||
} |
||||
|
||||
/** |
||||
* 设置弹出框最多显示单选的个数,超过显示滚动条 |
||||
*/ |
||||
public void setPopupMaxDisplayNumber(int maxDisplayNumber) { |
||||
this.popup.setMaxDisplayNumber(maxDisplayNumber); |
||||
} |
||||
|
||||
/** |
||||
* 是否要超过文本框长度后显示省略号 |
||||
* |
||||
* @param isShowOmitText |
||||
*/ |
||||
public void isShowOmitText(boolean isShowOmitText) { |
||||
this.showOmitText = isShowOmitText; |
||||
} |
||||
|
||||
private void initComponent() { |
||||
this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); |
||||
this.popup = new UICheckListPopup(values); |
||||
this.popup.addActionListener(new PopupAction()); |
||||
this.editor = createEditor(); |
||||
this.arrowButton = createArrowButton(); |
||||
this.add(editor); |
||||
this.add(arrowButton); |
||||
setText(); |
||||
} |
||||
|
||||
private UIButton createArrowButton() { |
||||
final UIButton arrowBtn = new UIButton(); |
||||
arrowBtn.setNormalPainted(false); |
||||
arrowBtn.setPreferredSize(new Dimension(20, 5)); |
||||
arrowBtn.setBackground(new Color(218, 218, 218)); |
||||
arrowBtn.setOpaque(true); |
||||
arrowBtn.setIcon(getIcon()); |
||||
arrowBtn.setExtraPainted(false); |
||||
addPopupListener(arrowBtn); |
||||
arrowBtn.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
arrowBtn.setBackground(new Color(200, 200, 200)); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
arrowBtn.setBackground(new Color(218, 218, 218)); |
||||
} |
||||
}); |
||||
|
||||
return arrowBtn; |
||||
} |
||||
|
||||
private UITextField createEditor() { |
||||
UITextField editor = new UITextField(); |
||||
editor.setEditable(false); |
||||
editor.setPreferredSize(new Dimension(180, 20)); |
||||
addPopupListener(editor); |
||||
|
||||
return editor; |
||||
} |
||||
|
||||
/** |
||||
* 弹出框事件 |
||||
* |
||||
* @param component |
||||
*/ |
||||
private void addPopupListener(Component component) { |
||||
component.addMouseListener(new MouseAdapter() { |
||||
public void mouseClicked(MouseEvent e) { |
||||
togglePopup(); |
||||
} |
||||
}); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 刷新复选框的列表值 |
||||
* |
||||
* @param value |
||||
*/ |
||||
public void refreshCombo(Object[] value) { |
||||
this.values = value; |
||||
this.popup.addCheckboxValues(value); |
||||
} |
||||
|
||||
/** |
||||
* 获取复选框选中的值 |
||||
* |
||||
* @return 复选框选中的值 |
||||
*/ |
||||
public Object[] getSelectedValues() { |
||||
return popup.getSelectedValues(); |
||||
} |
||||
|
||||
private class PopupAction implements ActionListener { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (e.getActionCommand().equals(UICheckListPopup.COMMIT_EVENT)) { |
||||
selectedValues = popup.getSelectedValues(); |
||||
setText(); |
||||
//把事件继续传递出去
|
||||
fireActionPerformed(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void togglePopup() { |
||||
if (this.arrowButton.isEnabled()) { |
||||
popup.show(this, 0, getHeight()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 清除文本框 |
||||
*/ |
||||
public void clearText() { |
||||
editor.setText(StringUtils.EMPTY); |
||||
} |
||||
|
||||
/** |
||||
* 获取文本框内容 |
||||
*/ |
||||
public String getText() { |
||||
return editor.getText(); |
||||
} |
||||
|
||||
/** |
||||
* 文本框设置显示值 |
||||
*/ |
||||
private void setText() { |
||||
StringBuilder builder = new StringBuilder(); |
||||
if (selectedValues != null) { |
||||
for (Object value : selectedValues) { |
||||
builder.append(value); |
||||
builder.append(valueSperator); |
||||
} |
||||
} |
||||
//去掉末尾多余的逗号
|
||||
String text = builder.length() > 0 ? builder.substring(0, builder.length() - 1) : StringUtils.EMPTY; |
||||
//计算加省略号后的文本
|
||||
editor.setText(this.showOmitText ? omitEditorText(editor, text) : text); |
||||
} |
||||
|
||||
/** |
||||
* 根据字体大小计算得到省略后的文字 |
||||
* |
||||
* @param textEditor |
||||
* @param text |
||||
* @return 省略后的文字 |
||||
*/ |
||||
private static String omitEditorText(UITextField textEditor, String text) { |
||||
char[] omitChars = OMIT_TEXT.toCharArray(); |
||||
//获取字体的大小
|
||||
FontMetrics fontMetrics = textEditor.getFontMetrics(textEditor.getFont()); |
||||
//计算省略号的长度
|
||||
int omitLength = fontMetrics.charsWidth(omitChars, 0, omitChars.length); |
||||
String omitText = StringUtils.EMPTY; |
||||
char[] chars = text.toCharArray(); |
||||
|
||||
for (int i = 1; i <= chars.length; i++) { |
||||
//如果原文本+省略号长度超过文本框
|
||||
if (fontMetrics.charsWidth(chars, 0, i) + omitLength > textEditor.getPreferredSize().getWidth()) { |
||||
//从第i-1的位置截断再拼上省略号
|
||||
omitText = text.substring(0, i - 2) + OMIT_TEXT; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return omitText == StringUtils.EMPTY ? text : omitText; |
||||
} |
||||
|
||||
/** |
||||
* 给组件登记一个观察者监听事件 |
||||
* |
||||
* @param listener 观察者监听事件 |
||||
*/ |
||||
@Override |
||||
public void registerChangeListener(UIObserverListener listener) { |
||||
this.uiObserverListener = listener; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void setGlobalName(String name) { |
||||
multiComboName = name; |
||||
} |
||||
|
||||
/** |
||||
* 组件是否需要响应添加的观察者事件 |
||||
* |
||||
* @return 如果需要响应观察者事件则返回true,否则返回false |
||||
*/ |
||||
@Override |
||||
public boolean shouldResponseChangeListener() { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 注册观察者监听事件 |
||||
* |
||||
* @param listener 观察者监听事件 |
||||
*/ |
||||
@Override |
||||
public void registerNameListener(GlobalNameListener listener) { |
||||
globalNameListener = listener; |
||||
} |
||||
|
||||
private Icon getIcon() { |
||||
return BaseUtils.readIcon(IconPathConstants.ARROW_ICON_PATH); |
||||
} |
||||
|
||||
/** |
||||
* 组件是否需要响应观察者事件 |
||||
* |
||||
* @return 如果需要响应观察者事件则返回true,否则返回false |
||||
*/ |
||||
@Override |
||||
public boolean shouldResponseNameListener() { |
||||
return true; |
||||
} |
||||
|
||||
public void addActionListener(ActionListener listener) { |
||||
if (!listeners.contains(listener)) |
||||
listeners.add(listener); |
||||
} |
||||
|
||||
public void removeActionListener(ActionListener listener) { |
||||
if (listeners.contains(listener)) |
||||
listeners.remove(listener); |
||||
} |
||||
|
||||
protected void fireActionPerformed(ActionEvent e) { |
||||
for (ActionListener l : listeners) { |
||||
l.actionPerformed(e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 简单的测试demo |
||||
* @param args |
||||
*/ |
||||
public static void main(String args[]) { |
||||
UIComboCheckBox comboBox = new UIComboCheckBox(new Object[] |
||||
{"MATA", "HANA", "KAKA", "KUKA", "INFI", "LILY", "RIBO", "CUBE", "MATA", "HANA", "KAKA", "KUKA"}); |
||||
|
||||
comboBox.isShowOmitText(false); |
||||
comboBox.setPopupMaxDisplayNumber(6); |
||||
|
||||
JPanel jPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||
jPanel.add(comboBox); |
||||
|
||||
JFrame jFrame = new JFrame(); |
||||
jFrame.setVisible(true); |
||||
jFrame.setSize(600, 400); |
||||
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
||||
jFrame.add(jPanel, BorderLayout.CENTER); |
||||
} |
||||
} |
After Width: | Height: | Size: 164 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 337 B |
Loading…
Reference in new issue