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

}

 


 

 

相关文章
|
6天前
|
Web App开发 人工智能 架构师
备考神器!基于通义听悟和Xmind快速生成思维导图
使用阿里通义听悟与Xmind,高效创建思维导图。通义听悟支持PDF、Word等格式文档分析,可一键转为Xmind格式。视频分析需下载,支持最大6GB,可用通义听悟插件实现在线视频内容提取。B站部分视频自带AI总结,或使用特定网站直接在线解析视频生成MD文档。结合Xmind,优化学习和工作效率。
23524 13
|
18天前
|
缓存 运维 关系型数据库
数据库容灾 | MySQL MGR与阿里云PolarDB-X Paxos的深度对比
经过深入的技术剖析与性能对比,PolarDB-X DN凭借其自研的X-Paxos协议和一系列优化设计,在性能、正确性、可用性及资源开销等方面展现出对MySQL MGR的多项优势,但MGR在MySQL生态体系内也占据重要地位,但需要考虑备库宕机抖动、跨机房容灾性能波动、稳定性等各种情况,因此如果想用好MGR,必须配备专业的技术和运维团队的支持。 在面对大规模、高并发、高可用性需求时,PolarDB-X存储引擎以其独特的技术优势和优异的性能表现,相比于MGR在开箱即用的场景下,PolarDB-X基于DN的集中式(标准版)在功能和性能都做到了很好的平衡,成为了极具竞争力的数据库解决方案。
|
10天前
|
存储 弹性计算 监控
几百T的视频、图片数据如何更有效地存储和管理?
采用传统硬盘搭建存储方案,看起来成本低廉,但是再加上各种附加因素后却大幅攀升,而云存储厂商通常提供基于订阅的定价模型、一些免费服务和一定的折扣。现在,我们就来了解一下如何更省钱地使用云存储。
18891 26
几百T的视频、图片数据如何更有效地存储和管理?
|
11天前
|
Kubernetes Dubbo Cloud Native
将Dubbo应用部署到服务网格中
本文主要就Dubbo应用如何接入服务网格、获得各项云原生能力进行了探讨,并提出了最佳实践以及过渡两种实践场景。我们首先推荐您使用Dubbo社区提供的最佳实践场景来接入服务网格,在必要时可以通过过渡方案来向最佳实践方案逐步实现过渡。
19207 7
|
9天前
|
人工智能 自然语言处理 搜索推荐
解读阿里云搜索开发工作台如何快速搭建AI语义搜索及RAG链路
本文介绍阿里云搜索开发工作台如何通过内置数据处理、查询分析、排序、效果测评、大模型等服务,结合阿里云搜索引擎及开源引擎,灵活打造AI语义搜索及RAG链路。
19137 12
|
8天前
|
分布式计算 监控 Serverless
E-MapReduce Serverless Spark 版测评
E-MapReduce Serverless Spark 版测评
11520 9
|
9天前
|
弹性计算 Prometheus 监控
如何从自建开源 Prometheus 迁移到阿里云托管 Prometheus 服务
阿里云可观测监控 Prometheus 版提供高性能、高可用、全托管的监控服务,对接开源生态,支持 Kubernetes、ECS 等场景,解决了自建 Prometheus+Thanos 高成本、运维复杂的问题。本文讨论在各个典型场景下的迁移方案。
10275 13
|
22天前
|
监控 Kubernetes Go
全链路追踪 & 性能监控,GO 应用可观测全面升级
当前,大多数面向 Golang 应用的监控能力主要是通过 SDK 方式接入,需要开放人员手动进行埋点,会存在一定问题。对此,可观测 Go Agent 应运而生。本文介绍的阿里云可观测 Go Agent 方案,能通过无侵入的方式实现应用监控能力。
108114 21
|
8天前
|
机器学习/深度学习 算法 PyTorch
使用Pytorch中从头实现去噪扩散概率模型(DDPM)
在本文中,我们将构建基础的无条件扩散模型,即去噪扩散概率模型(DDPM)。从探究算法的直观工作原理开始,然后在PyTorch中从头构建它。本文主要关注算法背后的思想和具体实现细节。
8554 3
|
17天前
|
机器学习/深度学习 算法 开发工具
大语言模型的直接偏好优化(DPO)对齐在PAI-QuickStart实践
阿里云的人工智能平台PAI,作为一站式的机器学习和深度学习平台,对DPO算法提供了全面的技术支持。无论是开发者还是企业客户,都可以通过PAI-QuickStart轻松实现大语言模型的DPO对齐微调。本文以阿里云最近推出的开源大型语言模型Qwen2(通义千问2)系列为例,介绍如何在PAI-QuickStart实现Qwen2的DPO算法对齐微调。