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

 

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();  
 }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

 

 

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;  
 }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

 

 

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;  
 }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.

 

 

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;  
 }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.

【编辑推荐】

  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-15 15:35:59

Swing程序Swing性能

2009-07-16 08:53:03

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-15 11:19:17

invokeLaterSwing

2009-07-10 13:36:32

Swing容器

2009-07-15 09:06:07

BeanTableMoSwing

2009-07-14 18:28:58

Swing入门

2009-07-10 10:37:50

Swing Set示例

2009-07-15 14:29:24

构造JListSwing

2009-07-15 13:06:38

Swing组件

2021-09-06 18:54:58

Java代码表达式

2025-02-06 07:30:32

2009-07-15 10:37:28

Swing外观

2009-07-10 15:41:27

Swing AWT

2009-07-10 18:06:59

JTree Swing

2009-07-16 12:58:50

Swing控件
点赞
收藏

51CTO技术栈公众号