)
Java Swing 自定义组件库分享十一滚动面板 — CusScrollPane一、背景二、核心设计三、类源码四、核心功能说明五、使用示例六、注意事项七、小结一、背景Swing 原生JScrollPane的滚动条 样式是系统默认的不同操作系统下风格不一致且无法自定义颜色、圆角、宽度等。在追求统一 UI 风格的应用中原生滚动条往往显得格格不入。CusScrollPane的作用就是通过自定义BasicScrollBarUI美化滚动条外观支持圆角滑块、自定义颜色、隐藏增减按钮、调整滚动条宽度等功能。二、核心设计CusScrollPane继承JScrollPane内部定义CusScrollBar类继承BasicScrollBarUI重写以下方法实现自定义createDecreaseButton/createIncreaseButton返回空按钮隐藏默认的增减箭头getPreferredSize设置滚动条宽度/高度paintThumb绘制滑块圆角矩形paintTrack绘制滑轨圆角矩形三、类源码importcn.hutool.core.thread.ThreadUtil;importjavax.swing.*;importjavax.swing.plaf.basic.BasicScrollBarUI;importjava.awt.*;importjava.util.concurrent.CompletableFuture;/** * 自定义滚动面板 * 通过自定义 BasicScrollBarUI 美化滚动条支持圆角、自定义颜色、隐藏增减按钮 * * 使用示例 * CusScrollPane scrollPane new CusScrollPane(table); * scrollPane.verticalScrollBar(null, Color.LIGHT_GRAY, Color.GRAY, 8); */publicclassCusScrollPaneextendsJScrollPane{publicCusScrollPane(){super();scrollBar();getVerticalScrollBar().setUnitIncrement(32);getViewport().setOpaque(false);}publicCusScrollPane(Componentview){super(view);scrollBar();getVerticalScrollBar().setUnitIncrement(32);getViewport().setOpaque(false);}publicCusScrollPane(intvsbPolicy,inthsbPolicy){super(vsbPolicy,hsbPolicy);scrollBar();getVerticalScrollBar().setUnitIncrement(32);getViewport().setOpaque(false);}publicCusScrollPane(Componentview,intvsbPolicy,inthsbPolicy){super(view,vsbPolicy,hsbPolicy);scrollBar();getVerticalScrollBar().setUnitIncrement(32);getViewport().setOpaque(false);}/** * 隐藏滚动条不显示 */publicvoidscrollBar(){scrollBar(null,null,null,0,0);}/** * 设置纵向滚动条样式 * param bg 滚动条背景色整体 * param trackColor 滑轨颜色 * param thumbColor 滑块颜色 * param width 滚动条宽度 */publicvoidverticalScrollBar(Colorbg,ColortrackColor,ColorthumbColor,intwidth){intheight0width?0:getPreferredSize().height;scrollBar(bg,trackColor,thumbColor,width,height);}/** * 设置横向滚动条样式 * param bg 滚动条背景色整体 * param trackColor 滑轨颜色 * param thumbColor 滑块颜色 * param height 滚动条高度 */publicvoidhorizontalScrollBar(Colorbg,ColortrackColor,ColorthumbColor,intheight){intwidth0height?0:getPreferredSize().width;scrollBar(bg,trackColor,thumbColor,width,height);}/** * 设置滚动条样式完整参数 * param bg 滚动条背景色整体 * param trackColor 滑轨颜色 * param thumbColor 滑块颜色 * param width 垂直滚动条宽度 * param height 水平滚动条高度 */publicvoidscrollBar(Colorbg,ColortrackColor,ColorthumbColor,intwidth,intheight){JScrollBarverticalScrollBargetVerticalScrollBar();verticalScrollBar.setUI(newCusScrollBar(bg,trackColor,thumbColor,width,height));JScrollBarhorizontalScrollBargetHorizontalScrollBar();horizontalScrollBar.setUI(newCusScrollBar(bg,trackColor,thumbColor,width,height));}/** * 滚动到底部 */publicvoidscrollToBottom(){CompletableFuture.runAsync(()-{ThreadUtil.sleep(100);JScrollBarverticalScrollBargetVerticalScrollBar();verticalScrollBar.setValue(verticalScrollBar.getMaximum());});}/** * 自定义滚动条 UI */staticclassCusScrollBarextendsBasicScrollBarUI{privateColorthumbColornewColor(77,74,74);privatefinalColortrackColor;privatefinalintwidth;privatefinalintheight;/** 固定圆角半径 */privatestaticfinalintARC15;publicCusScrollBar(Colorbg,ColortrackColor,ColorthumbColor,intwidth,intheight){UIManager.put(ScrollBar.background,bg);this.trackColortrackColor;if(thumbColor!null){this.thumbColorthumbColor;}this.widthwidth;this.heightheight;}OverrideprotectedJButtoncreateDecreaseButton(intorientation){returncreateZeroButton();}OverrideprotectedJButtoncreateIncreaseButton(intorientation){returncreateZeroButton();}privateJButtoncreateZeroButton(){JButtonbuttonnewJButton();button.setPreferredSize(newDimension(0,0));button.setMinimumSize(newDimension(0,0));button.setMaximumSize(newDimension(0,0));returnbutton;}OverridepublicDimensiongetPreferredSize(JComponentc){returnnewDimension(this.width,this.height);}OverrideprotectedvoidpaintThumb(Graphicsg,JComponentc,RectanglethumbBounds){if(!thumbBounds.isEmpty()scrollbar.isEnabled()){drawRoundRect(thumbColor,g,thumbBounds);}}OverrideprotectedvoidpaintTrack(Graphicsg,JComponentc,RectangletrackBounds){if(trackColor!null){drawRoundRect(trackColor,g,trackBounds);}}privatevoiddrawRoundRect(Colorcolor,Graphicsg,Rectanglerectangle){Graphics2Dg2(Graphics2D)g.create();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_PURE);g2.setColor(color);g2.fillRoundRect(rectangle.x,rectangle.y,rectangle.width,rectangle.height,ARC,ARC);g2.dispose();}}}四、核心功能说明滚动条样式定制verticalScrollBar/horizontalScrollBar分别设置纵向/横向滚动条样式scrollBar统一设置两个方向的滚动条样式scrollBar()隐藏滚动条宽度/高度设为0CusScrollBar 核心重写createDecreaseButton/createIncreaseButton返回零尺寸按钮隐藏默认箭头getPreferredSize返回自定义滚动条尺寸paintThumb绘制滑块圆角矩形paintTrack绘制滑轨圆角矩形其他功能scrollToBottom异步滚动到底部适用于聊天、日志等场景setUnitIncrement(32)鼠标滚轮滚动步长五、使用示例5.1 基本用法CusScrollPanescrollPanenewCusScrollPane(table);panel.add(scrollPane);5.2 自定义滚动条样式CusScrollPanescrollPanenewCusScrollPane(table);// 设置纵向滚动条滑轨浅灰色滑块灰色宽度8pxscrollPane.verticalScrollBar(null,Color.LIGHT_GRAY,Color.GRAY,8);5.3 隐藏滚动条CusScrollPanescrollPanenewCusScrollPane(table);scrollPane.scrollBar();// 不显示滚动条5.4 滚动到底部scrollPane.scrollToBottom();5.5 完整配置示例CusScrollPanescrollPanenewCusScrollPane(table);scrollPane.verticalScrollBar(Color.WHITE,newColor(220,220,220),newColor(180,180,180),10);scrollPane.setBorder(BorderFactory.createEmptyBorder());六、注意事项宽度/高度为0时隐藏滚动条scrollBar()方法将宽高设为0滚动条不可见异步滚动scrollToBottom使用CompletableFuture异步执行延迟100ms避免滚动条未就绪滑轨颜色trackColor为null时不绘制滑轨透明背景色设置UIManager.put(ScrollBar.background, bg)可设置整体背景色单位增量构造函数中设置了setUnitIncrement(32)可根据需要调整七、小结CusScrollPane通过自定义BasicScrollBarUI实现了滚动条样式美化核心要点继承BasicScrollBarUI重写paintThumb/paintTrack绘制圆角滑块和滑轨重写createDecreaseButton/createIncreaseButton隐藏默认箭头按钮重写getPreferredSize控制滚动条尺寸