SWT/Jface(3): 表格中添加超链接

news2024/11/27 20:25:35

背景

实际业务中经常需要展示某个网站, 并且希望在展示的时候单击网站可直接访问, 本节演示在表格中如何添加超链接支持.

需求

假设我需要渲染一个Study类, 它只有三个属性id,namewebsite, 其中id只支持展示, name只支持编辑, 而website只支持单击时跳转到相应的网站, 效果图如下:
在这里插入图片描述

方案

要在表格中添加超链接支持, 需要特殊的CellLableProvider, Jface提供了ColumnLabelProvider, 要想实现超链接, 只需要重新实现其中的updategetText方法.

方法名方法签名功能描述
getTextString getText(Object element)提供表格渲染后展示的文本的内容
updatevoid update(ViewerCell cell)提供表格对象的额外展示项, 比如背景颜色, 字体的设置等等

我们的超链接支持就可以放在update中来进行扩展实现:

  1. 创建Link对象, 并通过TableEditor将其与TableItem关联起来
  2. 添加Link对象的单击事件监听, 点击时进行跳转
Link link = new Link((Composite) cell.getControl(), SWT.NONE);
link.setText("<a>" + study.website + "</a>");
TableItem item = (TableItem) cell.getItem();
TableEditor editor = new TableEditor(item.getParent());
editor.grabHorizontal = true;
editor.grabVertical = true;
editor.setEditor(link, item, cell.getColumnIndex());
editor.layout();
link.addListener(SWT.Selection, e -> {
    try {
        Desktop.getDesktop().browse(new URI(study.website));
    } catch (IOException | URISyntaxException ex) {
        throw new RuntimeException(ex);
    }
});

注意实现

之前我们设置CellLabelProvider时是通过Tabel级别的对象进行的, 实际上我们往往是根据不同的Column来设置更为个性化的展示的, 因此, 在创建Column的同时设置CellLableProvider更为合理. 伪代码:

TableViewer tableViewer = ...;
Table table = tableViewer.getTable();
TableColumn tableColumn = TableColumnFactory.newTableColumn(SWT.NONE)....create(table);
TableViewerColumn tableViewerColumn = new TableViewerColumn(tableViewer, tableColumn);
// 每一列设置一个特定的cellLabelProvider
tableViewerColumn.setLabelProvider(cellLabelProvider);

源码

import org.eclipse.jface.viewers.*;
import org.eclipse.jface.widgets.TableColumnFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.*;

import java.awt.*;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Optional;

public class Study {
    @Column(value = "ID", labelProviderClass = StudyLabelProvider.class)
    public int id;
    @Column(value = "名称", labelProviderClass = StudyLabelProvider.class, width = 200)
    @TextEditor
    public String name;
    @Column(value = "网站", labelProviderClass = StudyLabelProvider.class, width = 300)
    public String website;

    public Study(int id, String name, String website) {
        this.id = id;
        this.name = name;
        this.website = website;
    }

    private static Study[] studies() {
        return new Study[]{new Study(1, "github", "https://github.com"), new Study(2, "死磕Java", "https://skjava.com")};
    }

    public static void main(String[] args) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        var tableViewer = new TableViewer(shell, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
        Table table = tableViewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        Field[] fields = Study.class.getFields();
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            String columnText = column.value();
            Class<? extends CellLabelProvider> labelProviderClass = column.labelProviderClass();
            CellLabelProvider cellLabelProvider;
            if (!(CellLabelProvider.class == labelProviderClass)) {
                Constructor<? extends CellLabelProvider> constructor = labelProviderClass.getConstructor(String.class);
                cellLabelProvider = constructor.newInstance(columnText);
            } else {
                cellLabelProvider = new StudyLabelProvider(columnText);
            }
            TableColumn tableColumn = TableColumnFactory.newTableColumn(SWT.NONE).width(column.width()).text(columnText)
                    .align(SWT.CENTER).create(table);
            TableViewerColumn tableViewerColumn = new TableViewerColumn(tableViewer, tableColumn);
            tableViewerColumn.setLabelProvider(cellLabelProvider);
            EditingSupport editingSupport = null;
            TextEditor textEditor = field.getAnnotation(TextEditor.class);
            if (textEditor != null) {
                Class<? extends EditingSupport> editingSupportClass = textEditor.editingSupportClass();

                Constructor<? extends EditingSupport> constructor = editingSupportClass.getConstructor(TableViewerColumn.class);
                editingSupport = constructor.newInstance(tableViewerColumn);
            }

            Optional.ofNullable(editingSupport).ifPresent(tableViewerColumn::setEditingSupport);
        }

        ColumnViewerEditorActivationStrategy activationStrategy = new ColumnViewerEditorActivationStrategy(tableViewer) {
            @Override
            protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
                // 只有双击事件才激活编辑器
                return event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL;
            }
        };
        table.setHeaderBackground(display.getSystemColor(SWT.COLOR_TITLE_BACKGROUND));
        table.setHeaderForeground(display.getSystemColor(SWT.COLOR_TITLE_FOREGROUND));
        TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(tableViewer, new FocusCellOwnerDrawHighlighter(tableViewer));
        TableViewerEditor.create(tableViewer, focusCellManager, activationStrategy, ColumnViewerEditor.DEFAULT);
        tableViewer.setContentProvider(ArrayContentProvider.getInstance());

        tableViewer.setInput(Study.studies());
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    public static class StudyEditingSupport extends EditingSupport {
        private final TableViewerColumn tableViewerColumn;

        private final String title;

        public StudyEditingSupport(TableViewerColumn tableViewerColumn) {
            super(tableViewerColumn.getViewer());
            this.tableViewerColumn = tableViewerColumn;
            TableColumn tableColumn = tableViewerColumn.getColumn();
            this.title = tableColumn.getText();
        }

        @Override
        protected CellEditor getCellEditor(Object o) {
            return new TextCellEditor(tableViewerColumn.getColumn().getParent());
        }

        @Override
        protected boolean canEdit(Object o) {
            return true;
        }

        @Override
        protected Object getValue(Object o) {
            if (!(o instanceof Study study)) {
                return "";
            }
            return switch (title) {
                case "名称" -> study.name;
                default -> study.website;
            };
        }

        @Override
        protected void setValue(Object o, Object o1) {
            if (!(o instanceof Study study)) {
                return;
            }
            switch (title) {
                case "名称" -> study.name = String.valueOf(o1);
                default -> study.website = String.valueOf(o1);
            }
            getViewer().refresh(o);
        }
    }

    public static class StudyLabelProvider extends ColumnLabelProvider {
        private final String title;

        public StudyLabelProvider(String title) {
            super();
            this.title = title;
        }

        @Override
        public void update(ViewerCell cell) {
            if (!(cell.getElement() instanceof Study study)) {
                return;
            }
            var text = switch (title) {
                case "ID" -> String.valueOf(study.id);
                case "名称" -> study.name;
                default -> {
                    Link link = new Link((Composite) cell.getControl(), SWT.NONE);
                    link.setText("<a>" + study.website + "</a>");
                    TableItem item = (TableItem) cell.getItem();
                    TableEditor editor = new TableEditor(item.getParent());
                    editor.grabHorizontal = true;
                    editor.grabVertical = true;
                    editor.setEditor(link, item, cell.getColumnIndex());
                    editor.layout();
                    link.addListener(SWT.Selection, e -> {
                        try {
                            Desktop.getDesktop().browse(new URI(study.website));
                        } catch (IOException | URISyntaxException ex) {
                            throw new RuntimeException(ex);
                        }
                    });
                    yield "";
                }
            };
            cell.setText(text);
        }

        @Override
        public String getText(Object element) {
            if (!(element instanceof Study study)) {
                return "";
            }
            return switch (title) {
                case "ID" -> String.valueOf(study.id);
                case "名称" -> study.name;
                default -> study.website;
            };
        }
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface Column {
        String value();

        Class<? extends CellLabelProvider> labelProviderClass() default CellLabelProvider.class;

        int width() default 100;
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface TextEditor {
        Class<? extends EditingSupport> editingSupportClass() default StudyEditingSupport.class;
    }
}

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

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

相关文章

软件介绍02- flameshot截图软件(linux系统可用)

1 软件介绍 在Windows和mac平台一直都使用着snipaste截图&#xff0c;非常好用&#xff0c;又能够钉图。遗憾是并没有开发linux版本&#xff0c;真不知道为什么。 好在终于找到一款截图软件&#xff0c;flameshot截图软件&#xff0c;可以平替snipaste。 下载网址&#xff1a;…

kali linux英文改中文

如果英语基础较好的同学可以不用调整 反之则需要 找到终端&#xff08;就是输入命令的那个地方 如下&#xff09;点击它出现命令终端 切换为root用户&#xff0c;命令为&#xff1a; sudo dpkg-reconfigure locales 然后回车 找到这个zh_CN 然后回车 鼠标下键选中并且回车 输…

【RTP】1: RTPSenderAudio::SendAudio

RTPSenderAudio 可以将一个opus帧封装为rtp包进行发送,以下是其过程:RTPSenderAudio::SendAudio :只需要提供payload部分 创建RtpPacketToSend 并写入各个部分 填充payload部分 sender 本身分配全session唯一的twcc序号 if (!rtp_sender_->

Linux系统---僵尸进程、孤儿进程

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 有了上一篇博客的学习&#xff0c;我们已经简单了解了进程的基础知识&#xff0c;今天我们再来学习两个特殊的进程&#xff0c;僵尸进程和孤儿进程。 …

【STL】string类 (下)

目录 1&#xff0c;insert 2&#xff0c;erase 3&#xff0c;find 4&#xff0c;replace 5&#xff0c;rfind 6&#xff0c;substr 7&#xff0c;find_first_of 8&#xff0c;find_first_not_of 9&#xff0c;find_last_of 10&#xff0c;operator 11&#xff0c;ge…

mysql从库设置为只读

直奔主题&#xff0c;mysql设置为只读后&#xff0c;无法增删改。 设置命令&#xff1a; mysql> set global read_only1; #1是只读&#xff0c;0是读写 mysql> show global variables like %read_only%; 以下是相关说明&#xff1a; 1、对于数据库读写状态&#xf…

[C/C++]数据结构 堆的详解

一:概念 堆通常是一个可以被看做一棵完全二叉树的数组对象,它是一颗完全二叉树,堆存储的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且需要满足每个父亲结点总小于其子节点(或者每个父亲结点总大于其子节点) 堆可以分为两种: 小堆: 任意一个父亲节点都小于其子…

【docker系列】docker高阶篇

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Flask WTForms 表单插件的使用

在Web应用中&#xff0c;表单处理是一个基本而常见的任务。Python的WTForms库通过提供表单的结构、验证和渲染等功能&#xff0c;简化了表单的处理流程。与此同时&#xff0c;Flask的扩展Flask-WTF更进一步地整合了WTForms&#xff0c;为开发者提供了更便捷、灵活的表单处理方式…

VM安装Centos

文章目录 第2章 VM与Linux的安装2.1 VMWare安装2.2 CentOS安装 第3章 Linux文件与目录结构3.1 Linux文件3.2 Linux目录结构 第4章 VI/VIM编辑器4.1 是什么4.2 测试数据准备4.3 一般模式4.4 编辑模式4.5 命令模式4.6 模式间转换 第5章 网络配置和系统管理操作5.1 查看网络IP和网…

linux LVM /dev/sdb mount dir /data【linux LVM 磁盘挂载目录】

添加磁盘 /dev/sdb rootregistry01 ~]# fdisk -lDisk /dev/sda: 53.7 GB, 53687091200 bytes, 104857600 sectors Units sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk lab…

了解FastSam:一个通用分割模型(草记)

想尝试这个FastSam的部署&#xff0c;但至今还没跑通&#xff0c;一个问题能带出一片问题&#xff0c;感觉挺心情挺郁闷的。后来和学长交流的时候&#xff0c;说那就是学少了&#xff0c;没必要急着将跑通它作为目的。也很有道理&#xff0c;这个任务还不太适合我当前的水平&am…

深度学习之基于yolov3学生课堂行为及专注力检测预警监督系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习技术在学生课堂行为及专注力检测预警监督系统的应用是一项极具挑战性和创新性的研究领域。利用YOLOv3&…

华为OD机试 - 围棋的气(Java JS Python C)

题目描述 围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19 x 19 = 361 个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。 “气”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可…

ICPC合肥退役小记

退役了。 现在我坐在合肥回济南的高铁上&#xff0c;外面天都黑了&#xff0c;刚刚刷小红书刷到一句话&#xff0c;“后来啊&#xff0c;一个清晨&#xff0c;大雾散尽&#xff0c;不止清晨&#xff0c;不止大雾”。 遗憾必然是有的。从大一开始每天熬夜刷题打cf…

23.11.26日总结

图片与文字顶部对齐&#xff1a; <div class"addDishImgBox"><span class"addDishImgZi">商品图片&#xff1a;</span><img :src"myStorePhoto" class"addDishImg"> </div> .addDishImgBox{display: f…

学习笔记-瑞吉外卖项目实战(一)

软件开发整体介绍 软件开发流程 角色分工 软件环境 瑞吉外卖项目介绍 项目介绍 产品原型介绍 技术选型 功能架构 角色 开发环境搭建 数据 创建database reggie&#xff0c;在里面创建表&#xff1a; maven 创建springboot项目并导入相关依赖坐标&#xff1a; 我们可以在项目…

Python文件访问和修改时间操作的高级技法

更多Python学习内容&#xff1a;ipengtao.com 在某些应用场景下&#xff0c;我们可能需要对文件的访问时间和修改时间进行定制或修改。Python提供了一些库和方法&#xff0c;使得这一过程变得简单而灵活。本文将深入探讨如何使用Python来实现更新文件的访问和修改时间&#xff…

SpringBoot中如何优雅地使用重试

1 缘起 项目中使用了第三方的服务&#xff0c; 第三方服务偶尔会出现不稳定、连接不上的情况&#xff0c; 于是&#xff0c;在调用时为了保证服务的相对高可用&#xff0c;添加了超时连接重试&#xff0c; 当连接第三方服务超时时&#xff0c;多重试几次&#xff0c;比如3次&a…

详解RT-DETR网络结构/数据集获取/环境搭建/训练/推理/验证/导出/部署

论文地址&#xff1a;RT-DETR论文地址 代码地址&#xff1a;RT-DETR官方下载地址 目录 一、本文介绍 二、RT-DETR的网络结构 2.1、模型概览 2.2、高效混合编码器 2.3、IoU感知查询选择 2.4、 可扩展的RT-DETR 三、RT-DERT的环境搭建 四、免费数据集获取 五、获取RT-D…