A component that combines a button or editable field and a drop-down list.
The user can select a value from the drop-down list, which appears at the user's request.
If you make the combo box editable, then the combo box includes an editable field into which the user can type a value.
话说JComboBox 默认外观确实不是太好看..在由于本人有时实在太贱.就是想要它好看...所以..这不..又折腾了..
其实这个ComboBox 刚开始想改变外观 只考虑到renderer 毕竟swing上所有的界面 显示全靠renderer来控制..
所以 着手写ComboBoxRenderer. 总是觉的 JComboBox 似乎不太好搞定 因为它不但有显示框 还有小键头.
还有弹出的List 还有ScrollBar..等等.. 似乎不那么好搞...不过Swing是强大的 ..只要你能想到..就可以做到.
那么我们要做几件事.
1: 重载JComboBox 并且设置面板透明
2: 新建renderer 实现ListCellRenderer接口
3: 重载BasicComboBoxUI
1.重载JComboBox 并且设置面板透明 设置renderer 以及设置 ui
package swing.combox.customize; import java.awt.Dimension; import java.util.Vector; import javax.swing.ComboBoxModel; import javax.swing.JComboBox; public class IComboBox extends JComboBox { private static final long serialVersionUID = 1L; public IComboBox() { super(); init(); } public IComboBox(ComboBoxModel model) { super(model); init(); } public IComboBox(Object[] items) { super(items); init(); } public IComboBox(Vector items) { super(items); init(); } private void init() { setOpaque(false); setUI(new IComboBoxUI()); setRenderer(new IComboBoxRenderer()); // setBackground(XUtil.defaultComboBoxColor); } public Dimension getPreferredSize() { return super.getPreferredSize(); } }
2.新建renderer 实现ListCellRenderer接口.注意.这里的ComboBoxRenderer它是控制combobox弹出的List 并非控制JComboBox的 注意 他实现的是ListCellRenderer
package swing.combox.customize; import java.awt.Color; import java.awt.Component; import javax.swing.DefaultListCellRenderer; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; public class IComboBoxRenderer implements ListCellRenderer { private DefaultListCellRenderer defaultCellRenderer = new DefaultListCellRenderer(); public IComboBoxRenderer() { super(); } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel renderer = (JLabel) defaultCellRenderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); if (isSelected) { // renderer.setBackground(XUtil.defaultComboBoxBoundsColor); renderer.setForeground(Color.WHITE); } else { renderer.setBackground(Color.WHITE); } // list.setSelectionBackground(XUtil.defaultComboBoxColor); list.setBorder(null); // renderer.setFont(XUtil.defaultComboBoxFont); renderer.setHorizontalAlignment(JLabel.CENTER); return renderer; } }
3.重载BasicComboBoxUI .sure 这里当然要注意.因为他是JComboBox的绘制机制
这里包括ComboBox右边的那个箭头的Button.(我们已经通过重写 createArrowButton 来改变这个Button);
至于弹出的List ,it in here, look it ..createPoput(); it create ComboPopup.(不好意思 最近在学英文 总是那么顺口来那么几句.)
这里存在一个ScrollPane 它包含了List.并且我们重写ScrollPane的paintBorder方法 来让我们画出List的Border
package swing.combox.customize; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; import javax.swing.plaf.basic.BasicComboBoxUI; import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.ComboPopup; public class IComboBoxUI extends BasicComboBoxUI { private JButton arrow; private boolean boundsLight = false; private static final int ARCWIDTH = 15; private static final int ARCHEIGHT = 15; public IComboBoxUI() { super(); } protected JButton createArrowButton() { arrow = new JButton(); // arrow.setIcon(XUtil.defaultComboBoxArrowIcon); arrow.setRolloverEnabled(true); // arrow.setRolloverIcon(XUtil.defaultComboBoxArrowIcon_Into); arrow.setBorder(null); // arrow.setBackground(XUtil.defaultComboBoxColor); arrow.setOpaque(false); arrow.setContentAreaFilled(false); return arrow; } public void paint(Graphics g, JComponent c) { hasFocus = comboBox.hasFocus(); Graphics2D g2 = (Graphics2D) g; if (!comboBox.isEditable()) { Rectangle r = rectangleForCurrentValue(); // 重点:JComboBox的textfield 的绘制 并不是靠Renderer来控制 这点让我很吃惊. // 它会通过paintCurrentValueBackground来绘制背景 // 然后通过paintCurrentValue();去绘制JComboBox里显示的值 paintCurrentValueBackground(g2, r, hasFocus); paintCurrentValue(g2, r, hasFocus); } g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int width = (int) this.getPreferredSize(c).getWidth() + arrow.getWidth() - 2; int height = 0; int heightOffset = 0; if (comboBox.isPopupVisible()) { heightOffset = 5; height = (int) this.getPreferredSize(c).getHeight(); // arrow.setIcon(XUtil.defaultComboBoxArrowIcon_Into); } else { heightOffset = 0; height = (int) this.getPreferredSize(c).getHeight() - 1; // arrow.setIcon(XUtil.defaultComboBoxArrowIcon); } if (comboBox.isFocusable()) { g2.setColor(new Color(150, 207, 254)); } g2.drawRoundRect(0, 0, width, height + heightOffset, ARCWIDTH, ARCHEIGHT); } public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) { Font oldFont = comboBox.getFont(); // comboBox.setFont(XUtil.defaultComboBoxFont); super.paintCurrentValue(g, bounds, hasFocus); comboBox.setFont(oldFont); } public Dimension getPreferredSize(JComponent c) { return super.getPreferredSize(c); } public boolean isBoundsLight() { return boundsLight; } public void setBoundsLight(boolean boundsLight) { this.boundsLight = boundsLight; } protected ComboPopup createPopup() { ComboPopup popup = new BasicComboPopup(comboBox) { protected JScrollPane createScroller() { JScrollPane sp = new JScrollPane(list, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); sp.setHorizontalScrollBar(null); return sp; } // 重载paintBorder方法 来画出我们想要的边框.. public void paintBorder(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(new Color(150, 207, 254)); g2.drawRoundRect(0, -arrow.getHeight(), getWidth() - 1, getHeight() + arrow.getHeight() - 1, 0, 0); } }; return popup; } }
ok. 那么到这里 ComboBox这块已经end 但是似乎还有个问题存在 那就是createPopup 方法里的ScrollPane的滚动条还是有点丑.
so。.next 我们搞定 it.
1:继承 ScrollBar 并且 setUI();
2:继承 BasicScrollBarUI 我们来G出我们的效果.
paintThumb 绘制scrollbar里拖动的小box 我们先画个边框 and draw two Orange line.
paintTrack 绘制scrollbar里小box的轨迹.也就是那个啥(术语怎么说来着?拖拽滑块?).
注意:我们首先将Graphics设置透明后 在去画面板 然后立刻把Graphics设置为不透明..
这样是为了能让我们把轨迹左边边界画出来...
createIncreaseButton draw down arrowButton 小心 千万不要use JButton button = new JButton();
should use BasicArrowButton 不然你将无法click this button 并产生你想要的效果..
你猜的到 createDecreaseButton(); 方法是干什么的..(笨蛋 上面那个Button啦);
package swing.combox.customize; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.plaf.basic.BasicArrowButton; import javax.swing.plaf.basic.BasicScrollBarUI; public class IScrollBarUI extends BasicScrollBarUI { public IScrollBarUI() { super(); } protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { int width = thumbBounds.width; int height = thumbBounds.height; Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.translate(thumbBounds.x, thumbBounds.y); // g2.setColor(XUtil.defaultComboBoxBoundsColor); g2.drawRoundRect(1, 1, width - 2, height - 2, 5, 5); g2.setColor(Color.ORANGE); g2.drawLine(3, height / 2, width - 4, height / 2); g2.drawLine(3, height / 2 + 3, width - 4, height / 2 + 3); g2.translate(-thumbBounds.x, -thumbBounds.y); } protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { // g.setColor(XUtil.defaultComboBoxColor); int x = trackBounds.x; int y = trackBounds.y; int width = trackBounds.width; int height = trackBounds.height; Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setComposite(AlphaComposite .getInstance(AlphaComposite.SRC_OVER, 0.1f)); g2.fill3DRect(x, y, width, height, true); g2.setComposite(AlphaComposite .getInstance(AlphaComposite.SRC_OVER, 1f)); // g2.setColor(XUtil.defaultComboBoxBoundsColor.brighter()); g2.fill3DRect(x, y, 1, height + 1, true); if (trackHighlight == DECREASE_HIGHLIGHT) { paintDecreaseHighlight(g); } else if (trackHighlight == INCREASE_HIGHLIGHT) { paintIncreaseHighlight(g); } } protected JButton createIncreaseButton(int orientation) { JButton button = new BasicArrowButton(orientation) { public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // g2.setColor(XUtil.defaultComboBoxBoundsColor); g2.drawLine(0, 0, 0, getHeight()); g2.drawLine(0, 0, getWidth(), 0 - 1); // g2.drawImage(((ImageIcon) XUtil.defaultComboBoxArrowIcon_Into).getImage(), -1, 0, null); } }; button.setOpaque(false); return button; } protected JButton createDecreaseButton(int orientation) { JButton button = new BasicArrowButton(orientation) { public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // g2.setColor(XUtil.defaultComboBoxBoundsColor); g2.drawLine(0, 0, 0, getHeight()); g2.drawLine(0, getHeight() - 1, getWidth(), getHeight()); // g2.drawImage(((ImageIcon) XUtil.defaultComboBoxArrowIcon_Into).getImage(), -1, 0, null); } }; button.setOpaque(false); return button; } }
http://blog.chinaunix.net/uid-12888785-id-2384253.html
http://www.blogjava.net/chensiyu04/archive/2011/03/27/346868.html
http://blog.sina.com.cn/s/blog_4e6d7e6901000bvm.html
http://blog.chinaunix.net/uid-12888785-id-2384254.html
http://www.2cto.com/kf/201103/86224.html
http://blog.csdn.net/bradwoo8621/article/details/1523118
http://blog.sina.com.cn/s/blog_4412ae250100062n.html
设置JComboBox中JList中元素的ToolTipText需要JComboBox.setRenderer(实现设置ToolTipText的ListCellRenderer);
设置JComboBox的ToolTipText需要JComboBox.addItemListener(new ItemListener()的itemStateChanged方法中调用JComboBox.setToolTipText("tips")
package swing.combox; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListCellRenderer; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JTextField; import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; /*2015-6-1*/ public class ComboxDemo extends JFrame { private static final long serialVersionUID = 1L; public ComboxDemo() { this.setLayout(new FlowLayout()); final JTextField text = new JTextField("test", 10); this.add(text); String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig", "Tiger", "Lion", "Egg", "Swan", "Goose", "Chinese sturgeon" }; final JComboBox petList = new JComboBox(petStrings); this.add(petList); petList.setRenderer(new ListCellRendererImpl1()); // petList.setRenderer(new ListCellRendererImpl2()); petList.setPreferredSize(new Dimension(100, 20)); petList.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { text.setText(petList.getSelectedItem().toString() + ":" + petList.getSelectedIndex()); petList.setToolTipText(petList.getSelectedItem().toString()); } }); petList.setSelectedIndex(4); // petList.setSelectedItem("Swan"); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ComboxDemo comboBox = new ComboxDemo(); comboBox.setDefaultCloseOperation(EXIT_ON_CLOSE); comboBox.setSize(400, 200); comboBox.setVisible(true); comboBox.setLocationRelativeTo(null); } }); } } /** * for JList ToolTextTip */ class ListCellRendererImpl1 extends JTextField implements ListCellRenderer { private static final long serialVersionUID = 1L; @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { String item = (value == null) ? "" : value.toString(); setText(item); setBorder(null); list.setToolTipText("第" + index + "被选中:" + item); return this; } } class ListCellRendererImpl2 extends DefaultListCellRenderer { private static final long serialVersionUID = 1L; @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JComponent component = (JComponent) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); setToolTipText(value + ":" + index); return component; } @Override public void setToolTipText(String text) { super.setToolTipText(text); } }