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

}

 


 

 

相关文章
|
5天前
|
人工智能 开发工具 C++
利用通义灵码AI在VS Code中快速开发扫雷游戏:Qwen2.5-Max模型的应用实例
本文介绍了如何利用阿里云通义灵码AI程序员的Qwen2.5-Max模型,在VS Code中一键生成扫雷小游戏。通过安装通义灵码插件并配置模型,输入指令即可自动生成包含游戏逻辑与UI设计的Python代码。生成的游戏支持难度选择,运行稳定无Bug。实践表明,AI工具显著提升开发效率,但人机协作仍是未来趋势。建议开发者积极拥抱新技术,同时不断提升自身技能以适应行业发展需求。
22046 6
|
14天前
|
人工智能 自然语言处理 Java
快速带你上手通义灵码 2.0,体验飞一般的感觉
通义灵码个人版为开发者免费提供智能编码能力,专业版限免期内开放更多功能。使用需先注册阿里云账号,支持JetBrains IDEs、Visual Studio Code等开发工具。以Visual Studio Code为例,安装插件并登录后即可体验其强大功能。通义灵码2.0在代码生成、需求理解及单元测试自动化等方面有显著提升,支持多语言和复杂场景,大幅提高开发效率。
134778 10
快速带你上手通义灵码 2.0,体验飞一般的感觉
|
1月前
|
人工智能 运维 前端开发
基于阿里百炼的DeepSeek-R1满血版模型调用【零门槛保姆级2084小游戏开发实战】
本文介绍基于阿里百炼的DeepSeek-R1满血版模型调用,提供零门槛保姆级2048小游戏开发实战。文章分为三部分:定位与核心优势、实战部署操作指南、辅助实战开发。通过详细步骤和案例展示,帮助开发者高效利用DeepSeek-R1的强大推理能力,优化游戏逻辑与视觉效果,解决官网响应延迟问题,提升开发效率和用户体验。适合企业开发者、教育行业及多模态探索者使用。
89975 24
基于阿里百炼的DeepSeek-R1满血版模型调用【零门槛保姆级2084小游戏开发实战】
|
1月前
|
存储 人工智能 测试技术
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
141118 25
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
|
1月前
|
人工智能 自然语言处理 API
快速使用 DeepSeek-R1 满血版
DeepSeek是一款基于Transformer架构的先进大语言模型,以其强大的自然语言处理能力和高效的推理速度著称。近年来,DeepSeek不断迭代,从DeepSeek-V2到参数达6710亿的DeepSeek-V3,再到性能比肩GPT-4的DeepSeek-R1,每次都带来重大技术突破。其开源策略降低了AI应用门槛,推动了AI普惠化。通过阿里云百炼调用满血版API,用户可以快速部署DeepSeek,享受高效、低成本的云端服务,最快10分钟完成部署,且提供免费token,极大简化了开发流程。
191191 28
快速使用 DeepSeek-R1 满血版
|
1月前
|
人工智能 自然语言处理 Shell
深度评测 | 仅用3分钟,百炼调用满血版 Deepseek-r1 API,百万Token免费用,简直不要太爽。
仅用3分钟,百炼调用满血版Deepseek-r1 API,享受百万免费Token。阿里云提供零门槛、快速部署的解决方案,支持云控制台和Cloud Shell两种方式,操作简便。Deepseek-r1满血版在推理能力上表现出色,尤其擅长数学、代码和自然语言处理任务,使用过程中无卡顿,体验丝滑。结合Chatbox工具,用户可轻松掌控模型,提升工作效率。阿里云大模型服务平台百炼不仅速度快,还确保数据安全,值得信赖。
358105 68
深度评测 | 仅用3分钟,百炼调用满血版 Deepseek-r1 API,百万Token免费用,简直不要太爽。
|
18天前
|
人工智能 搜索推荐 数据可视化
Manus:或将成为AI Agent领域的标杆
随着人工智能技术的飞速发展,AI Agent(智能体)作为人工智能领域的重要分支,正逐渐从概念走向现实,并在各行各业展现出巨大的应用潜力。在众多AI Agent产品中,Manus以其独特的技术优势和市场表现,有望成为该领域的标杆。作为资深AI工程师,本文将深入探讨Manus的背景知识、主要业务场景、底层原理、功能的优缺点,并尝试使用Java搭建一个属于自己的Manus助手,以期为AI Agent技术的发展和应用提供参考。
11305 15
|
18天前
|
机器学习/深度学习 人工智能 测试技术
阿里云百炼已上线超强推理开源模型QwQ-32B,尺寸更小,性能比肩DeepSeek满血版
通义千问团队推出了320亿参数的QwQ-32B模型,通过大规模强化学习和多阶段训练,在数学、编程及通用能力上达到或超越了DeepSeek-R1等先进模型。QwQ-32B模型已在阿里云百炼上线,支持API调用,用户可通过官方文档了解详细使用方法。未来,团队将继续探索智能体与RL集成,推动人工通用智能的发展。
|
10天前
|
人工智能 JavaScript Java
从零开始教你打造一个MCP客户端
Anthropic开源了一套MCP协议,它为连接AI系统与数据源提供了一个通用的、开放的标准,用单一协议取代了碎片化的集成方式。本文教你从零打造一个MCP客户端。