Swing不丑系列:JComboBox

一直都是一只菜鸟..不管别人怎么说.
一直认为Swing不丑..所以打算这段时间写个Swing不丑系列(献丑了)

|----------------------------------------------------------------------------------------|
                     版权声明  版权所有 @chensiyu
            引用请注明来源 
www.blogjava.net/chensiyu04

            本文由  陈思羽 于 2011年8月24号 出品..
|----------------------------------------------------------------------------------------|
-------------------------->>>>>>


话说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 = (intthis.getPreferredSize(c).getWidth()
    
+ arrow.getWidth() - 2;
  
int height = 0;
  
int heightOffset = 0;
  
if (comboBox.isPopupVisible()) {
   heightOffset 
= 5;
   height 
= (intthis.getPreferredSize(c).getHeight();
   arrow.setIcon(XUtil.defaultComboBoxArrowIcon_Into);
  }
 else {
   heightOffset 
= 0;
   height 
= (intthis.getPreferredSize(c).getHeight() - 1;
   arrow.setIcon(XUtil.defaultComboBoxArrowIcon);
  }

  
if (comboBox.isFocusable()) {
   g2.setColor(
new Color(150207254));
  }

  g2.drawRoundRect(
00, 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(150207254));
    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+1true);
  
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;
 }

}

posted on 2011-03-23 16:58 相信 阅读(7530) 评论(12)  编辑  收藏 所属分类: Swing文章

评论

# re: Swing不丑系列:JComboBox 2011-03-23 20:53 greatghoul

lz真是有坚强毅力,这样重下来还是挺费劲的嘛。  回复  更多评论   

# re: Swing不丑系列:JComboBox 2011-03-23 20:57 相信

@greatghoul

可以要任何想要的效果....其实有时候觉得 做富客户端的 如果美工底子好的话...会更帅 哈哈 ....  回复  更多评论   

# re: Swing不丑系列:JComboBox 2011-03-24 17:10 郑州SEO

确实好看多了!!!  回复  更多评论   

# re: Swing不丑系列:JComboBox 2011-03-24 17:11 相信

还不算最好看。。有时间继续完美下。。(准备让它边框发光...)  回复  更多评论   

# re: Swing不丑系列:JComboBox[未登录] 2011-03-24 23:09 Charlie

支持楼主  回复  更多评论   

# re: Swing不丑系列:JComboBox 2011-03-27 13:09 penngo

不错!界面重绘用得利害。  回复  更多评论   

# re: Swing不丑系列:JComboBox[未登录] 2011-08-11 09:46 haha

感谢分享 不过缺少了两个类啊  回复  更多评论   

# re: Swing不丑系列:JComboBox 2012-08-15 13:06 hxy

还是放弃单纯的用代码美化Swing组件,想炫 代码很难炫过图片(保证性能的前提下)  回复  更多评论   

# re: Swing不丑系列:JComboBox[未登录] 2012-11-27 21:06 文斌

XUtil是啥?  回复  更多评论   

# re: Swing不丑系列:JComboBox 2013-11-03 21:13 路过

XUtil类和IScrollPane类没有- -搞不出来  回复  更多评论   

# re: Swing不丑系列:JComboBox 2014-07-17 15:07 coverfate

你好,请问能提供缺少的两个类么,还有qq群好像加不来啊  回复  更多评论   

# re: Swing不丑系列:JComboBox 2014-07-17 15:25 相信

@coverfate

群没收到你的消息  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2011年3月>
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

公告

不显示applet

常用链接

留言簿(16)

我参与的团队

随笔档案

文章分类

文章档案

新闻档案

相册

swingchina 专业搞Swing的网站

搜索

最新评论

阅读排行榜

评论排行榜