JCombox

简介: A component that combines a button or editable field and a drop-down list. The user can select a value from the drop-down list, which appears at the user's request.

 

A component that combines a button or editable field and a drop-down list.
The user can select a value from the drop-down list, which appears at the user's request.
If you make the combo box editable, then the combo box includes an editable field into which the user can type a value. 

 

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

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

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

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

那么我们要做几件事.

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

2: 新建renderer 实现ListCellRenderer接口

3: 重载BasicComboBoxUI

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

package swing.combox.customize;

import java.awt.Dimension;
import java.util.Vector;

import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;

public class IComboBox extends JComboBox {
    private static final long serialVersionUID = 1L;

    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

package swing.combox.customize;

import java.awt.Color;
import java.awt.Component;

import javax.swing.DefaultListCellRenderer;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.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

package swing.combox.customize;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;

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() {
                JScrollPane sp = new JScrollPane(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啦);

package swing.combox.customize;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.plaf.basic.BasicScrollBarUI;

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

 

http://blog.chinaunix.net/uid-12888785-id-2384253.html

 

 

http://www.blogjava.net/chensiyu04/archive/2011/03/27/346868.html

http://blog.sina.com.cn/s/blog_4e6d7e6901000bvm.html

http://blog.chinaunix.net/uid-12888785-id-2384254.html

http://www.2cto.com/kf/201103/86224.html

http://blog.csdn.net/bradwoo8621/article/details/1523118

 

http://blog.sina.com.cn/s/blog_4412ae250100062n.html

 

设置JComboBox中JList中元素的ToolTipText需要JComboBox.setRenderer(实现设置ToolTipText的ListCellRenderer);
设置JComboBox的ToolTipText需要JComboBox.addItemListener(new ItemListener()的itemStateChanged方法中调用JComboBox.setToolTipText("tips")

 

package swing.combox;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;

/*2015-6-1*/
public class ComboxDemo extends JFrame {
    private static final long serialVersionUID = 1L;

    public ComboxDemo() {
        this.setLayout(new FlowLayout());
        final JTextField text = new JTextField("test", 10);
        this.add(text);

        String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig", "Tiger", "Lion", "Egg", "Swan", "Goose", "Chinese sturgeon" };
        final JComboBox petList = new JComboBox(petStrings);
        this.add(petList);
        petList.setRenderer(new ListCellRendererImpl1());
        // petList.setRenderer(new ListCellRendererImpl2());
        petList.setPreferredSize(new Dimension(100, 20));
        petList.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                text.setText(petList.getSelectedItem().toString() + ":" + petList.getSelectedIndex());
                petList.setToolTipText(petList.getSelectedItem().toString());
            }
        });
        petList.setSelectedIndex(4);
        // petList.setSelectedItem("Swan");

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ComboxDemo comboBox = new ComboxDemo();
                comboBox.setDefaultCloseOperation(EXIT_ON_CLOSE);
                comboBox.setSize(400, 200);
                comboBox.setVisible(true);
                comboBox.setLocationRelativeTo(null);
            }
        });
    }

}

/**
 * for JList ToolTextTip
 */
class ListCellRendererImpl1 extends JTextField implements ListCellRenderer {
    private static final long serialVersionUID = 1L;

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        String item = (value == null) ? "" : value.toString();
        setText(item);
        setBorder(null);
        list.setToolTipText("第" + index + "被选中:" + item);
        return this;
    }

}

class ListCellRendererImpl2 extends DefaultListCellRenderer {
    private static final long serialVersionUID = 1L;

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        JComponent component = (JComponent) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        setToolTipText(value + ":" + index);
        return component;
    }

    @Override
    public void setToolTipText(String text) {
        super.setToolTipText(text);
    }

}

 


 

 

相关文章
|
数据可视化 Java
《IntelliJ IDEA 插件开发》第二节:开发摸鱼看书的侧边栏窗体
一、说明 二、需求目的 三、案例开发 1. 工程结构 2. 创建 UI 窗体 3. ToolWindow 工具框 4. Configurable 配置框 5. 配置 plugin.xml 四、插件测试 五、总结 六、系列推荐
1057 0
《IntelliJ IDEA 插件开发》第二节:开发摸鱼看书的侧边栏窗体
|
Java
JTable设置列宽、自动调整
下面這個方法 你可以用來設置列寬,在你需要的地方調用一下就可以了 Java code public void FitTableColumns(JTable myTable) {               //設置table的列寬隨內容調整         JTableHeader header = myTable.getTableH
2528 0
|
4天前
|
Kubernetes 测试技术 应用服务中间件
基于 Nginx Ingress + 云效 AppStack 实现灰度发布
本文将演示结合云效 AppStack,来看下如何在阿里云 ACK 集群上进行应用的 Ingress 灰度发布。
64292 10
|
8天前
|
人工智能 Linux Docker
一文详解几种常见本地大模型个人知识库工具部署、微调及对比选型(1)
近年来,大模型在AI领域崭露头角,成为技术创新的重要驱动力。从AlphaGo的胜利到GPT系列的推出,大模型展现出了强大的语言生成、理解和多任务处理能力,预示着智能化转型的新阶段。然而,要将大模型的潜力转化为实际生产力,需要克服理论到实践的鸿沟,实现从实验室到现实世界的落地应用。阿里云去年在云栖大会上发布了一系列基于通义大模型的创新应用,标志着大模型技术开始走向大规模商业化和产业化。这些应用展示了大模型在交通、电力、金融、政务、教育等多个行业的广阔应用前景,并揭示了构建具有行业特色的“行业大模型”这一趋势,大模型知识库概念随之诞生。
123362 18
|
10天前
|
存储 SQL 搜索推荐
一站式实时数仓Hologres整体能力介绍—2024实时数仓Hologres公开课 01
一站式实时数仓Hologres整体能力介绍—2024实时数仓Hologres公开课 01
|
10天前
|
存储 运维 安全
Greenplum闭源?平滑迁移到 AnalyticDB 开启Data+AI新范式
知名开源 MPP 数据库 Greenplum 由于其丰富的企业级特性和出色的数据处理能力成为很多企业构建数仓的首选。近期 GP 公开 Github 仓库无法访问仅保留只读归档代码,业界纷纷猜测 GP 即将闭源。云原生数仓 AnalyticDB PostgreSQL 版完全掌控内核代码,完全兼容GP语法,全自研计算及存储引擎较比开源GP有五倍性能提升,全自研企业级特性在实时计算、弹性扩展、安全增强、高可用等方面实现对GP的全面超越,并在数仓能力上扩展了向量检索及一站式 RAG 服务,帮助企业快速构建 AI 应用、开启 Data+AI 新范式。
58848 3
|
12天前
|
搜索推荐 API 对象存储
10分钟学会构建端到端的图片搜索服务
本文介绍在没有向量数据的情况下,怎样通过OpenSearch-向量检索版快速从零搭建图像搜索服务。
81464 69
|
10天前
|
存储 弹性计算 数据可视化
高效、弹性,阿里云工业仿真行业解决方案解读
近日,全球领先的云计算厂商阿里云宣布最新HPC优化实例hpc8ae的正式商业化,该实例依托阿里云自研的「飞天+CIPU」架构体系,搭载第四代AMD EPYC处理器,专为高性能计算应用优化,特别适用于计算流体、有限元分析、多物理场模拟等仿真类应用,CAE场景下的性价比最少提升50%。