Swing不丑系列:JComboBox

开发 后端
话说JComboBox 默认外观确实不是太好看..在由于本人有时实在太贱.就是想要它好看,所以这不又折腾了,其实这个ComboBox 刚开始想改变外观 只考虑到renderer 毕竟swing上所有的界面 显示全靠renderer来控制.

一直都是一只菜鸟..不管别人怎么说.

[[20608]]

 

一直认为Swing不丑..所以打算这段时间写个Swing不丑系列(献丑了)

[[20609]]

 

 

-----------------------------

 

话说JComboBox 默认外观确实不是太好看..在由于本人有时实在太贱.就是想要它好看...所以..这不..又折腾了..

其实这个ComboBox 刚开始想改变外观 只考虑到renderer 毕竟swing上所有的界面 显示全靠renderer来控制..

所以 着手写ComboBoxRenderer. 总是觉的 JComboBox 似乎不太好搞定 因为它不但有显示框 还有小键头.

还有弹出的List 还有ScrollBar..等等.. 似乎不那么好搞...不过Swing是强大的 ..只要你能想到..就可以做到.

那么我们要做几件事.

1: 重载JComboBox 并且设置面板透明

2: 新建renderer 实现ListCellRenderer接口

3: 重载BasicComboBoxUI

1.重载JComboBox 并且设置面板透明 设置renderer 以及设置 ui

 

  1. public class IComboBox extends JComboBox{  
  2.    
  3.  public IComboBox(){  
  4.   super();  
  5.   init();  
  6.  }  
  7.  public IComboBox(ComboBoxModel model){  
  8.   super(model);  
  9.   init();  
  10.  }  
  11.  public IComboBox(Object[] items){  
  12.   super(items);  
  13.   init();  
  14.  }  
  15.  public IComboBox(Vector items){  
  16.   super(items);  
  17.   init();  
  18.  }  
  19.  private void init(){  
  20.   setOpaque(false);  
  21.   setUI(new IComboBoxUI());  
  22.   setRenderer(new IComboBoxRenderer());  
  23.   setBackground(XUtil.defaultComboBoxColor);  
  24.  }  
  25.  public Dimension getPreferredSize(){  
  26.   return super.getPreferredSize();  
  27.  }  

 

 

2.新建renderer 实现ListCellRenderer接口.注意.这里的ComboBoxRenderer它是控制combobox弹出的List 并非控制JComboBox的 注意 他实现的是ListCellRenderer

 

  1. public class IComboBoxRenderer implements ListCellRenderer {  
  2.    
  3.  private DefaultListCellRenderer defaultCellRenderer = new DefaultListCellRenderer();  
  4.  
  5.  public IComboBoxRenderer() {  
  6.   super();  
  7.  }  
  8.  
  9.  public Component getListCellRendererComponent(JList list, Object value,  
  10.    int index, boolean isSelected, boolean cellHasFocus) {  
  11.  
  12.   JLabel renderer = (JLabel)defaultCellRenderer.getListCellRendererComponent(  
  13.     list, value, index, isSelected, cellHasFocus);  
  14.   if(isSelected){  
  15.    renderer.setBackground(XUtil.defaultComboBoxBoundsColor);  
  16.    renderer.setForeground(Color.WHITE);  
  17.   }else{  
  18.    renderer.setBackground(Color.WHITE);  
  19.   }  
  20.   list.setSelectionBackground(XUtil.defaultComboBoxColor);  
  21.   list.setBorder(null);  
  22.   renderer.setFont(XUtil.defaultComboBoxFont);  
  23.   renderer.setHorizontalAlignment(JLabel.CENTER);  
  24.   return renderer;  
  25.  }  

 

 

3重载BasicComboBoxUI .sure 这里当然要注意.因为他是JComboBox的绘制机制

这里包括ComboBox右边的那个箭头的Button.(我们已经通过重写 createArrowButton 来改变这个Button);

至于弹出的List ,it in here, look it ..createPoput(); it create ComboPopup.(不好意思 最近在学英文 总是那么顺口来那么几句.)

这里存在一个ScrollPane 它包含了List.并且我们重写ScrollPane的paintBorder方法 来让我们画出List的Border

 

  1. public class IComboBoxUI extends BasicComboBoxUI {  
  2.  
  3.  private JButton arrow;  
  4.  private boolean boundsLight = false;  
  5.  private static final int ARCWIDTH = 15;  
  6.  private static final int ARCHEIGHT = 15;  
  7.  
  8.  public IComboBoxUI() {  
  9.   super();  
  10.  }  
  11.  
  12.  protected JButton createArrowButton() {  
  13.   arrow = new JButton();  
  14.   arrow.setIcon(XUtil.defaultComboBoxArrowIcon);  
  15.   arrow.setRolloverEnabled(true);  
  16.   arrow.setRolloverIcon(XUtil.defaultComboBoxArrowIcon_Into);  
  17.   arrow.setBorder(null);  
  18.   arrow.setBackground(XUtil.defaultComboBoxColor);  
  19.   arrow.setOpaque(false);  
  20.   arrow.setContentAreaFilled(false);  
  21.   return arrow;  
  22.  }  
  23.  
  24.  public void paint(Graphics g, JComponent c) {  
  25.   hasFocus = comboBox.hasFocus();  
  26.   Graphics2D g2 = (Graphics2D)g;  
  27.   if (!comboBox.isEditable()) {  
  28.    Rectangle r = rectangleForCurrentValue();  
  29.    //重点:JComboBox的textfield 的绘制 并不是靠Renderer来控制 这点让我很吃惊.  
  30.    //它会通过paintCurrentValueBackground来绘制背景  
  31.    //然后通过paintCurrentValue();去绘制JComboBox里显示的值  
  32.    paintCurrentValueBackground(g2, r, hasFocus);  
  33.    paintCurrentValue(g2, r, hasFocus);  
  34.   }  
  35.     
  36.   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  37.     RenderingHints.VALUE_ANTIALIAS_ON);  
  38.   int width = (intthis.getPreferredSize(c).getWidth()  
  39.     + arrow.getWidth() - 2;  
  40.   int height = 0;  
  41.   int heightOffset = 0;  
  42.   if (comboBox.isPopupVisible()) {  
  43.    heightOffset = 5;  
  44.    height = (intthis.getPreferredSize(c).getHeight();  
  45.    arrow.setIcon(XUtil.defaultComboBoxArrowIcon_Into);  
  46.   } else {  
  47.    heightOffset = 0;  
  48.    height = (intthis.getPreferredSize(c).getHeight() - 1;  
  49.    arrow.setIcon(XUtil.defaultComboBoxArrowIcon);  
  50.   }  
  51.   if (comboBox.isFocusable()) {  
  52.    g2.setColor(new Color(150207254));  
  53.   }  
  54.   g2.drawRoundRect(00, width, height + heightOffset,ARCWIDTH,ARCHEIGHT);  
  55.  }  
  56.  
  57.  public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) {  
  58.   Font oldFont = comboBox.getFont();  
  59.   comboBox.setFont(XUtil.defaultComboBoxFont);  
  60.     
  61.   super.paintCurrentValue(g, bounds, hasFocus);  
  62.   comboBox.setFont(oldFont);  
  63.  }  
  64.  
  65.  public Dimension getPreferredSize(JComponent c) {  
  66.   return super.getPreferredSize(c);  
  67.  }  
  68.  
  69.  public boolean isBoundsLight() {  
  70.   return boundsLight;  
  71.  }  
  72.  
  73.  public void setBoundsLight(boolean boundsLight) {  
  74.   this.boundsLight = boundsLight;  
  75.  }  
  76.  
  77.  protected ComboPopup createPopup() {  
  78.   ComboPopup popup = new BasicComboPopup(comboBox) {  
  79.    protected JScrollPane createScroller() {  
  80.     IScrollPane sp = new IScrollPane(list,  
  81.       ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,  
  82.       ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);  
  83.     sp.setHorizontalScrollBar(null);  
  84.     return sp;  
  85.    }  
  86.    //重载paintBorder方法 来画出我们想要的边框..  
  87.    public void paintBorder(Graphics g){  
  88.     Graphics2D g2 = (Graphics2D) g;  
  89.     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  90.       RenderingHints.VALUE_ANTIALIAS_ON);  
  91.     g2.setColor(new Color(150207254));  
  92.     g2.drawRoundRect(0,-arrow.getHeight(),getWidth()-1,getHeight()+arrow.getHeight()-1,0,0);  
  93.    }  
  94.   };  
  95.   return popup;  
  96.  }  

 

 

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啦);

 

  1. public class IScrollBarUI extends BasicScrollBarUI{  
  2.  public IScrollBarUI(){  
  3.   super();  
  4.  }  
  5.  
  6.  protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {  
  7.   int width = thumbBounds.width;  
  8.   int height = thumbBounds.height;  
  9.   Graphics2D g2 = (Graphics2D)g;  
  10.   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  11.           RenderingHints.VALUE_ANTIALIAS_ON);  
  12.     
  13.   g2.translate(thumbBounds.x, thumbBounds.y);  
  14.   g2.setColor(XUtil.defaultComboBoxBoundsColor);  
  15.   g2.drawRoundRect(1,1,width-2, height-2,5,5);  
  16.     
  17.   g2.setColor(Color.ORANGE);  
  18.   g2.drawLine(3,height/2,width-4,height/2);  
  19.   g2.drawLine(3,height/2+3,width-4,height/2+3);  
  20.   g2.translate(-thumbBounds.x, -thumbBounds.y);  
  21.  }  
  22.  
  23.  protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {  
  24.   g.setColor(XUtil.defaultComboBoxColor);  
  25.   int x = trackBounds.x;  
  26.   int y = trackBounds.y;  
  27.   int width = trackBounds.width;  
  28.   int height = trackBounds.height;  
  29.   Graphics2D g2 = (Graphics2D)g;  
  30.   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  31.           RenderingHints.VALUE_ANTIALIAS_ON);  
  32.   g2.setComposite(AlphaComposite  
  33.     .getInstance(AlphaComposite.SRC_OVER, 0.1f));  
  34.     
  35.   g2.fill3DRect(x, y, width, height, true);  
  36.   g2.setComposite(AlphaComposite  
  37.     .getInstance(AlphaComposite.SRC_OVER, 1f));  
  38.   g2.setColor(XUtil.defaultComboBoxBoundsColor.brighter());  
  39.   g2.fill3DRect(x, y, 1, height+1true);  
  40.   if(trackHighlight == DECREASE_HIGHLIGHT) {  
  41.       paintDecreaseHighlight(g);  
  42.   }   
  43.   else if(trackHighlight == INCREASE_HIGHLIGHT)  {  
  44.       paintIncreaseHighlight(g);  
  45.   }  
  46.  }  
  47.  
  48.  protected JButton createIncreaseButton(int orientation) {  
  49.   JButton button = new BasicArrowButton(orientation){  
  50.    public void paint(Graphics g) {  
  51.     Graphics2D g2 = (Graphics2D)g;  
  52.     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  53.             RenderingHints.VALUE_ANTIALIAS_ON);  
  54.     g2.setColor(XUtil.defaultComboBoxBoundsColor);  
  55.     g2.drawLine(0,0,0,getHeight());  
  56.     g2.drawLine(0,0,getWidth(),0-1);  
  57.     g2.drawImage(((ImageIcon)XUtil.defaultComboBoxArrowIcon_Into).getImage(),-1,0,null);  
  58.    }  
  59.   };  
  60.   button.setOpaque(false);  
  61.   return button;  
  62.  }  
  63.  
  64.  protected JButton createDecreaseButton(int orientation) {  
  65.  
  66.     
  67.   JButton button = new BasicArrowButton(orientation){  
  68.    public void paint(Graphics g) {  
  69.     Graphics2D g2 = (Graphics2D)g;  
  70.     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  71.             RenderingHints.VALUE_ANTIALIAS_ON);  
  72.     g2.setColor(XUtil.defaultComboBoxBoundsColor);  
  73.     g2.drawLine(0,0,0,getHeight());  
  74.     g2.drawLine(0,getHeight()-1,getWidth(),getHeight());  
  75.     g2.drawImage(((ImageIcon)XUtil.defaultComboBoxArrowIcon_Into).getImage(),-1,0,null);  
  76.    }  
  77.   };  
  78.   button.setOpaque(false);  
  79.   return button;  
  80.  }  

【编辑推荐】

  1. 探秘JDK 7之二:半透明和任意形状的窗口
  2. 探秘JDK 7:将会出现新的语言特性
  3. 我们真的能没有Java吗?
  4. 探秘Java 7:JVM动态语言支持详解
  5. 探秘Java 7新增垃圾回收器G1特性
责任编辑:金贺 来源: 博客园
相关推荐

2016-12-28 17:59:28

MongoDBNoSQL数据

2009-07-15 13:48:26

Swing模型和渲染器

2009-07-16 08:53:03

Swing任务Swing线程

2009-07-15 15:35:59

Swing程序Swing性能

2009-07-16 16:01:55

EventQueue

2009-06-22 13:44:00

JSFJava Web开发

2023-11-20 17:38:07

Djangoagtailadmin

2009-07-10 18:06:59

JTree Swing

2009-07-15 10:37:28

Swing外观

2009-07-14 09:52:10

TableModelESwing

2009-07-10 15:41:27

Swing AWT

2009-07-16 12:58:50

Swing控件

2009-07-17 12:54:13

2009-07-17 12:44:01

NetBeans开发S

2009-07-10 14:26:28

实现SwingActionListe

2009-07-15 14:29:24

构造JListSwing

2009-07-10 10:37:50

Swing Set示例

2009-07-15 09:06:07

BeanTableMoSwing

2009-07-14 18:28:58

Swing入门

2009-07-10 13:36:32

Swing容器
点赞
收藏

51CTO技术栈公众号