Swing不丑系列:JComboBox
一直都是一只菜鳥..不管別人怎么說.
一直認為Swing不丑..所以打算這段時間寫個Swing不丑系列(獻丑了)



話說JComboBox 默認外觀確實不是太好看..在由于本人有時實在太賤.就是想要它好看...所以..這不..又折騰了..
其實這個ComboBox 剛開始想改變外觀 只考慮到renderer 畢竟swing上所有的界面 顯示全靠renderer來控制..
所以 著手寫ComboBoxRenderer. 總是覺的 JComboBox 似乎不太好搞定 因為它不但有顯示框 還有小鍵頭.
還有彈出的List 還有ScrollBar..等等.. 似乎不那么好搞...不過Swing是強大的 ..只要你能想到..就可以做到.
那么我們要做幾件事.
1: 重載JComboBox 并且設置面板透明
2: 新建renderer 實現ListCellRenderer接口
3: 重載BasicComboBoxUI
1.重載JComboBox 并且設置面板透明 設置renderer 以及設置 ui
- public class IComboBox extends JComboBox{
- 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
- 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
- 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() {
- IScrollPane sp = new IScrollPane(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啦);
- 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;
- }
- }
【編輯推薦】