Chinaunix首页 | 论坛 | 博客
  • 博客访问: 335380
  • 博文数量: 104
  • 博客积分: 2815
  • 博客等级: 少校
  • 技术积分: 595
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 16:32
文章分类

全部博文(104)

文章存档

2013年(1)

2012年(2)

2011年(21)

2010年(80)

我的朋友

分类: Java

2011-08-17 21:57:48

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

一直认为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;
     }
    }


阅读(2060) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~