重构之美:Java Swing中 如何对指定行文本进行CSS样式渲染,三种实现思路分享

news2024/11/15 18:36:30

文章目录

    • 需求分析
    • Document 应用
    • 彩蛋

需求分析

在这里插入图片描述

在Swing中,如果期望实现对JTextArea 或者 TextPane等文本区域实现单行渲染改怎么做?如上图所示

总的来说有两种实现方案

  • 文本行数可控,那么构造一组JLabel集合按表单顺序添加,这样可以预先调整特定位置的颜色

  • 文本行数未知,想基于关键字模糊匹配,甚至将所在行进行统一控制,那么需要借助Document对象完成

如果行数可控的文本控制,直接使用label.setColor(XXX)即可设置,无需过多考虑,下面主要探讨行数可变,且不同需求下的文本渲染问题。


Document 应用

在行数可变前提下 还得你的技术选型是什么,不同的Component的渲染方式思路一样,但实现上略有差异。否则东施效颦,结果啥也出不来

  1. 基于JTextArea 的 Document
 private JTextArea jTextArea = new JTextArea();
 # 引入样式组件
 private StyleContext styleContext = new StyleContext();
 # 添加全局样式
 private Style redStyle = styleContext.addStyle("red", null);
  private Style common = styleContext.addStyle("common", null);
 StyleConstants.setForeground(redStyle, Color.RED);
 StyleConstants.setForeground(common, Color.BLACK);
 # 使用 
 
 
 Document document = jTextArea.getDocument();
 # 注意这个方式是以插入方式渲染,也就是说其他默认样式也需要通过插入方式到textArea,否则就会出现内容丢失
 //document.insertString(document.getLength(), "特定文本之前内容", common);
 document.insertString(document.getLength(), "特定文本", redStyle);
  //document.insertString(document.getLength(), "特定文本之后的内容", common);

  1. 基于JTextPane 的StyleDocument
    本文开头使用的便是如下这种方式
		JTextPane textPane = new JTextPane();
        textPane.setEditable(false); // 可编辑
        textPane.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 设置字体

        textPane.setText("hello swing this is red\n hello java, this is blue\n hello word\n");
        StyledDocument styledDocument = textPane.getStyledDocument();

        SimpleAttributeSet red = new SimpleAttributeSet();
        StyleConstants.setForeground(red, Color.RED);
		// 关键字渲染
        String text = textPane.getText();
        int swing = text.indexOf("swing");
        styledDocument.setCharacterAttributes(swing, swing, red, true);

        SimpleAttributeSet blue = new SimpleAttributeSet();
        StyleConstants.setForeground(blue, Color.BLUE);
        StyleConstants.setBold(blue, true);
		// 按行渲染
        int java = text.indexOf("java");
        Element defaultRootElement = styledDocument.getDefaultRootElement();
        int offset = defaultRootElement.getElementIndex(java);

        int start = defaultRootElement.getElement(offset).getStartOffset();
        int end = defaultRootElement.getElement(offset).getEndOffset();
        styledDocument.setCharacterAttributes(start, end - start, blue, true);

  1. 基于JTextPane的HTML文档
 		// 创建一个 JTextPane
        JTextPane textPane = new JTextPane();
        textPane.setEditable(false); // 不可编辑

        // 创建一个 HTML 文档
        HTMLEditorKit kit = new HTMLEditorKit();
        StyleSheet styleSheet = kit.getStyleSheet();
        styleSheet.addRule("body { font-size: 16px; font-family: Arial; }"); // 自定义样式
        String htmlContent = "<html><body><h1>Hello, <span style='color: blue;'>World</span></h1></body></html>";

        try {
            textPane.setEditorKit(kit);
            textPane.setText(htmlContent);
        } catch (Exception e) {
            e.printStackTrace();
        }

彩蛋

重构之美系列文章一定存在通用解决方案的工具方法,大家可参考使用:


/**
 重点介绍:
 String... tags  统一渲染的关键字集合
 replaceAll: 是否对tag 进行全文样式替换
 */
private void repaintCaseTitle(StyledDocument doc, SimpleAttributeSet style, boolean replaceAll, String... tags) {

        String text = jTextPane.getText();
       for (String tag : tags) {
            int i = text.indexOf(tag);
            if (i < 0) {
                log.info(tag + "无效渲染");
                return;
            }
            Element defaultRootElement = doc.getDefaultRootElement();
            if (!replaceAll) {
                int offset = defaultRootElement.getElementIndex(i);
                int startIndex = defaultRootElement.getElement(offset).getStartOffset();
                int endIndex = defaultRootElement.getElement(offset).getEndOffset();
                doc.setCharacterAttributes(startIndex, endIndex - startIndex, style, true);
                continue;
            }
            // 全部替换
            for (int j = 0; j < defaultRootElement.getElementCount(); j++) {
                Element line = defaultRootElement.getElement(j);
                try {
                    String lineText = doc.getText(line.getStartOffset(), line.getEndOffset() - line.getStartOffset());
                    if (lineText.contains(tag)) {
                        doc.setCharacterAttributes(line.getStartOffset(), line.getEndOffset() - line.getStartOffset(), style, true);
                    }
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }

            }

        }
    }

改工具方法基于JTextPane提供通用样式渲染提供简便调用
使用时仅仅需要通过一行代码便可以对目标关键字进行按行渲染, 如果还有定制化需求,可自行修改

  repaintCaseTitle(doc, redStyle, false, "测试", "分析", "异常");

研发不易,多多支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1134397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频相关学习笔记

YUV 和rgb一样是一种表示色彩的格式&#xff0c;Y表示亮度&#xff0c;UV表示色度&#xff08;U是蓝色投影&#xff0c;V是红色投影&#xff09;&#xff0c;只有Y就是黑白的&#xff0c;所以这个格式的视频图片可以兼容黑白电视&#xff0c;所以彩色电视使用的都是YUV 存储方…

查找算法-斐波那契查找法(Fibonacci Search)

目录 查找算法-斐波那契查找法&#xff08;Fibonacci Search&#xff09; 1、说明 2、算法分析 3、C代码 查找算法-斐波那契查找法&#xff08;Fibonacci Search&#xff09; 1、说明 斐波那契查找法又称为斐氏查找法&#xff0c;此查找法和二分法一样都是以分割范围来进…

第12章 PyTorch图像分割代码框架-1

从本章开始&#xff0c;本书将会进行深度学习图像分割的实战阶段。PyTorch作为目前最为流行的一款深度学习计算框架&#xff0c;在计算机视觉和图像分割任务中已经广泛使用。本章将介绍基于PyTorch的深度学习图像分割代码框架&#xff0c;在总体框架的基础上&#xff0c;基于PA…

kuaishou web端did注册激活 学习记录

快手web端 did 注册激活的流程大概如下&#xff1a; 1.访问web端的接口&#xff0c;主动触发滑块&#xff0c;拿到滑块信息 2.然后滑块验证did 获取captchaToken 3.携带captchaToken访问接口 4.最后校验web端的did 是否激活 最后激活以后的效果如下&#xff1a; 经过测试&…

微服务-服务拆分

文章目录 服务拆分及注意事项服务拆分案例案例代码分析 服务拆分及注意事项 每个服务有独立的数据库&#xff0c;订单模块需要查询用户信息时&#xff0c;通过调用用户模块的接口&#xff0c;自身的数据库并没有用户信息。 服务拆分案例 案例结构 案例有2个微服务&#xff0c;…

【跟小嘉学 Rust 编程】三十三、Rust的Web开发框架之一: Actix-Web的基础

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…

基于Kubesphere容器云平台物联网云平台Devops实践

基于Kubesphere容器云平台物联网云平台Devops实践 项目背景 ​ 公司是做工业物联网相关业务的&#xff0c;现业务是云平台&#xff0c;技术栈 后端为 Springboot2.7JDK11 &#xff0c;前端为 Vue3Ts&#xff0c;需要搭建自动化运维平台以实现业务代码自动部署上线&#xff0c;…

【C++笔记】如何用检查TCP或UDP端口是否被占用

一、检查步骤 使用socket函数创建socket_fd套接字。使用sockaddr_in结构体配置协议和端口号。使用bind函数尝试与端口进行绑定&#xff0c;成功返回0表示未被占用&#xff0c;失败返回-1表示已被占用。 二、步骤详解 2.1 socket函数 socket 函数是用于创建套接字的函数&…

【MySql】9- 实践篇(七)

文章目录 1. 一主多从的主备切换1.1 基于位点的主备切换1.2 GTID1.3 基于 GTID 的主备切换1.4 GTID 和在线 DDL 2. 读写分离问题2.1 强制走主库方案2.2 Sleep 方案2.3 判断主备无延迟方案2.4 配合 semi-sync方案2.5 等主库位点方案2.6 GTID 方案 3. 如何判断数据库是否出问题了…

Django 实战开发(一)项目搭建

1.项目搭建 用pycharm 编辑器可以直接 New 一个 Django 项目 2.新建应用 python manage.py startapp demo项目结构如下: 3.编写第一个Django 视图函数 /demo/views: from django.http import HttpResponse def welcome(request):return HttpResponse("welcome to dja…

品牌媒介工作流程是什么,媒体投放目标怎么做?

品牌媒介其实说简单也很简单&#xff0c;说难也很难&#xff0c;简单在于其实事情流程简洁&#xff0c;难呢&#xff0c;在于很多东西如果不亲身体验是无法领悟到精髓的。今天为大家分享下品牌媒介工作流程是什么&#xff0c;媒体投放目标怎么做&#xff1f; 我们怎么才能在媒体…

JWT的封装、[Authorize]的使用

JWT的封装 需要安装两个包。 包1&#xff1a;System.IdentityModel.Tokens.Jwt Install-Package System.IdentityModel.Tokens.Jwt 包2&#xff1a;Microsoft.AspNetCore.Authentication.JwtBearer Install-Package Microsoft.AspNetCore.Authentication.JwtBearer 我们创建一…

【Unity】3D跑酷游戏

展示 finish_all * 方块跑酷 1.教程链接 翻墙&#xff1a;https://www.youtube.com/watch?v9ZEu_I-ido4&listPLPV2KyIb3jR53Jce9hP7G5xC4O9AgnOuL&index3 2.基础制作 最终成果 2.1 基本场景 1.创建Cube作为跑道 1&#xff09;记得把位置Reset&#xff1b; 2&#…

C#使用mysql-connector-net驱动连接mariadb报错

给树莓派用最新的官方OS重刷了一下&#xff0c;并且用apt install mariadb-server装上“mysql”作为我的测试服务器。然后神奇的事情发生了&#xff0c;之前用得好好的程序突然就报错了&#xff0c;经过排查&#xff0c;发现在连接数据库的Open阶段就报错了。写了个最单纯的Con…

CSDN学院 < 华为战略方法论进阶课 > 正式上线!

目录 你将收获 适用人群 课程内容 内容目录 CSDN学院 作者简介 你将收获 提升职场技能提升战略规划的能力实现多元化发展综合能力进阶 适用人群 主要适合公司中高层、创业者、产品经理、咨询顾问&#xff0c;以及致力于改变现状的学员。 课程内容 本期课程主要介绍华为…

【发展史】鼠标的发展史

最早可以追溯到1952年&#xff0c;皇家加拿大海军将5针保龄球放在能够侦测球面转动的硬件上&#xff0c;这个硬件再将信息转化成光标在屏幕上移动&#xff0c;用作军事计算机输入。这是我们能够追溯到的最早的依靠手部运动进行光标移动的输入设备。但当时这个东西不叫鼠标&…

Ps:套索工具

Ps 的套索工具有三种&#xff0c;主要通过手动绘制的方式创建选区。 套索工具 Lasso Tool 又称“自由套索工具”&#xff0c;可绘制任意形状的选区&#xff0c;灵活快速但不够精确&#xff0c;是仅需粗略选区时&#xff08;比如&#xff0c;生成式填充等&#xff09;最常用的工…

XTU-OJ 1178-Rectangle

题目描述 给你两个平行于坐标轴的矩形&#xff0c;请判断两者是不是相交&#xff08;面积有重合的部分&#xff09;&#xff1f; 输入 第一行是一个整数K&#xff0c;表示样例数。 每个样例占两行&#xff0c;每行是4个整数&#xff0c;表示一个矩形的对角线点的坐标&#xff0…

【API篇】十一、Flink水位线传递与迟到数据处理

文章目录 1、水位线传递2、水位线设置空闲等待3、迟到数据处理&#xff1a;窗口允许迟到4、迟到数据处理&#xff1a;侧流输出5、问 1、水位线传递 上游task处理完水位线&#xff0c;时钟改变后&#xff0c;要把数据和当前水位线继续往下游算子的task发送。当一个任务接收到多…

对mysql的联合索引的深刻理解

背景 对mysql的联合索引的考察是Java程序员面试高频考点&#xff01;必须深刻理解掌握否则容易丢分非常可惜。 技术难点 考察对最左侧匹配原理理解。 原理 暂且不表。网上讲这非常多。我理解就是&#xff0c;B树每个非叶子节点的值都是有序存放索引的值。 比如对A、B、C …