积微成著 不积跬步,无以至千里

首页   >   web开发   >   Swing界面优化JScrollPane详细图文教程

Swing界面优化JScrollPane详细图文教程

关于JScrollPane的UI优化,之前在iteye上已经发过一篇帖子了,Swing界面优化进阶四,素材找的不是很好,而且还有一个隐藏的小bug,现在来重新优化一版。

Chrome浏览器的滚动条,前端的同学可能都优化过,用css样式就可以控制,由于我对“扁平化”有着近乎痴迷的喜好,所以这次也打算优化成扁平化的滚动条。

Swing界面优化JScrollPane详细图文教程

上图(已经有扁平化的效果了)就是这次发现的bug,给thumb设置的颜色是灰色,点击滑道的时候,下面就出现了一块儿灰蓝色。

优化思路:

1、去掉上下的按钮;

2、去掉thumb的边框;

3、填充颜色,平滑渲染;

相关的概念,在iteye上的帖子中已经讲的很详细了,这里不再细说,值得注意的是那个bug相关的代码,在BasicScrollBarUI中有相关处理的方法,只是上一次没有注意到,主要就是重写两个方法:paintDecreaseHighlight()、paintIncreaseHighlight(),意思很好懂,就是绘制向上或向下滑动的区域,涉及到高度和颜色的控制。

package com.wolffy.ui;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
import javax.swing.plaf.basic.BasicScrollBarUI;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;

/**
 * Created by SongFei on 2017/11/8.
 */
public class MyScrollBarUI extends BasicScrollBarUI {

    // 设置滚动区域宽度,高度默认即可
    @Override
    public Dimension getPreferredSize(JComponent c) {
        Dimension preferredSize = super.getPreferredSize(c);
        return new Dimension(10, preferredSize.height);
    }

    // 重绘滑动把手,主要是颜色和形状
    @Override
    protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
        Graphics2D g2 = (Graphics2D) g;
        // 把绘制区的x,y点坐标定义为坐标系的原点
        // 这句一定要加上,不然拖动就失效了
        g2.translate(thumbBounds.x, thumbBounds.y);
        // 设置把手颜色
        g2.setColor(Color.GRAY);
        // 消除锯齿
        g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
        // 半透明
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        // 填充圆角矩形
        g2.fillRoundRect(0, 0, thumbBounds.width, thumbBounds.height - 1, 0, 0);
    }

    // 自定义向上的箭头按钮
    @Override
    protected JButton createDecreaseButton(int orientation) {
        return nullButton();
    }

    // 自定义向下的箭头按钮
    @Override
    protected JButton createIncreaseButton(int orientation) {
        return nullButton();
    }

    // 重绘当鼠标点击滑动到向上或向左按钮之间的区域
    @Override
    protected void paintDecreaseHighlight(Graphics g) {
        g.setColor(trackColor);
        int x = getTrackBounds().x;
        int y = getTrackBounds().y;
        int w = 0, h = 0;
        if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
            w = getThumbBounds().width;
            h = getThumbBounds().y - y;
        }
        if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL) {
            w = getThumbBounds().x - x;
            h = getThumbBounds().height;
        }
        g.fillRect(x, y, w, h);
    }

    // 重绘当鼠标点击滑块至向下或向右按钮之间的区域
    @Override
    protected void paintIncreaseHighlight(Graphics g) {
        g.setColor(trackColor);
        int x = getThumbBounds().x;
        int y = getThumbBounds().y;
        int w = getTrackBounds().width;
        int h = getTrackBounds().height;
        g.fillRect(x, y, w, h);
    }

    /**
     * 返回一个没有任何内容的Jbutton,连边框都没有
     * @return Jbutton
     */
    private JButton nullButton() {
        JButton button = new JButton();
        button.setBorder(null);
        return button;
    }

}

上下两个按钮,去掉很简单,直接给他一个空按钮,何为空按钮?没有文字,没有颜色,没有边框,就是一个空按钮了,不会占位置。

至于扁平化,这是一个模糊的概念,并没有一个硬性的规定,我理解的就是没有过多的渲染、简洁大方,大家注意在paintThumb方法中,绘制矩形的时候,并没有过多的渲染边框之类的,仅仅就是背景颜色的填充。

package com.wolffy.frame;

import com.wolffy.ui.MyScrollBarUI;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.WindowConstants;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.BorderLayout;


/**
 * Created by SongFei on 2017/11/8.
 */
public class ScrollFrame extends JFrame {

    private static final long serialVersionUID = -3100927143103929215L;

    private JPanel jPanel;

    private JTree jTree;

    private JScrollPane jScrollPane;

    public ScrollFrame() {
        initGUI();
    }

    private void initGUI() {
        setSize(700, 500);
        //setUndecorated(true);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        jPanel = new JPanel();
        jPanel.setLayout(new BorderLayout());
        getContentPane().add(jPanel, BorderLayout.CENTER);

        DefaultMutableTreeNode root = new DefaultMutableTreeNode();
        DefaultTreeModel model = new DefaultTreeModel(root);
        for (int i = 0; i < 100; i++) {
            root.add(new DefaultMutableTreeNode("node" + i));
        }
        jTree = new JTree(model);

        jScrollPane = new JScrollPane(jTree);
        jScrollPane.setBorder(null);// 无边框,更贴合容器
        jScrollPane.getVerticalScrollBar().setUI(new MyScrollBarUI());
        jPanel.add(jScrollPane, BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        ScrollFrame loginFrame = new ScrollFrame();
        loginFrame.setVisible(true);
        //loginFrame.pack();
        loginFrame.setLocationRelativeTo(null);
    }

}

这里大家注意一下,JScrollPane是自带边框的,我们必须给他去掉,否则看起来会很别扭,看起来一直有一条线,逼死强迫症!

QQ群:积微成著官方群(686430774),验证消息:积微成著

站长Q:1347384268(加好友请注明来意)

分享到:

欢迎分享本文,转载请注明出处!

作者:不忘初心

发布时间:2017-11-08

永久地址:http://www.jiweichengzhu.com/article/7bf6460398fd4dc390674dea5b91ceb9