SWT/Jface(2): 表格的编辑

前言

上节说到, 创建和渲染表格需要如下几个步骤:

  1. 接收源数据数组(也可以是单个对象或者其他集合类型): TableViewer.setInput(Object)
  2. 渲染接收的数据
    1. 渲染表头: TableViewer.setLabelProvider(IBaseLabelProvider)
    2. 渲染内容: TableViewer.setContentProvider(IContentProvider)

在实际应用中我们往往需要编辑表格并实现双向绑定, 本节内容主要集中讲如何对表格单元格添加编辑支持.

需求

当双击单元格时进入编辑模式

步骤

添加编辑支持

Jface提供了EditingSupport抽象类, 可以很方便的实现, 不过需要配合TableViewerColumn使用, 上节我们根据表头数组创建了列:

        String[] titles = {"ID", "姓名", "性别", "年龄"};// 创建列头信息, 并最终绑定到tableArrays.stream(titles).forEach(title -> TableColumnFactory.newTableColumn(SWT.NONE).width(80).text(title).create(table));

如需添加编辑支持可以直接根据TableColumn创建TableViewerColumn并将每一列对应的EditingSupport实现赋值给TableViewerColumn即可.
实现EditingSupport需要覆写的方法简介:

  1. CellEditor getCellEditor(Object): 当前列对应的编辑器类型, 主要有:
    1. TextCellEditor: 文字编辑器, 非常通用
    2. CheckboxCellEditor: 复选编辑器
    3. ComboBoxCellEditor: 下拉列表编辑器
    4. ColorCellEditor: 颜色编辑器
    5. DialogCellEditor: 对话编辑器, 这是高级用法, 可以实现个性定制
  2. boolean canEdit(Object): 当前列是否支持编辑
  3. Object getValue(Object): 编辑初始状态显示的值
  4. void setValue(Object oldValue, Object newValue): 编辑结束时需要赋值的逻辑, 第一个参数为编辑前对应的值, 第二个为编辑后对应的新值, 值类型取决于编辑器, 比如TextCellEditor对应的就是String类型.

需要注意的是, 当我们接受新值后, 要刷新下当前表格, 否则界面展示依然是之前的值, 也就是说我们在setValue方法的最后需要加上一行

tableViewer.update(o, null);

此时我们丰富一下创建表头的逻辑, 这里列出空实现:

// 创建列头信息, 并最终绑定到table
Arrays.stream(titles).forEach(title -> {TableColumn tableColumn = TableColumnFactory.newTableColumn(SWT.NONE).width(80).text(title).create(table);// 创建TableViewerColumn关联到当前列并添加编辑支持new TableViewerColumn(tableViewer, tableColumn).setEditingSupport(new EditingSupport(tableViewer) {@Overrideprotected CellEditor getCellEditor(Object o) {return null;}@Overrideprotected boolean canEdit(Object o) {return false;}@Overrideprotected Object getValue(Object o) {return null;}@Overrideprotected void setValue(Object o, Object o1) {// 赋值逻辑...tableViewer.update(o, null);}});
});

添加触发条件

仅仅添加编辑支持是不够的, 因为系统不知道什么时候切换为编辑状态, 比如我们只希望在双击当前单元格时开启编辑状态, Jface提供了ColumnViewerEditorActivationStrategy来控制策略:

ColumnViewerEditorActivationStrategy activationStrategy = new ColumnViewerEditorActivationStrategy(tableViewer) {@Overrideprotected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {// 只有双击事件才激活编辑器return event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION;}
};

此时打开界面发现单击表格也进入了编辑状态, 并且一次性就高亮显示整行, 这和需求不符, 我们需要借助TableViewerEditor来强制激活此策略, 并集成TableViewerFocusCellManager来高亮显示本单元格而不是整行:

TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(tableViewer, new FocusCellOwnerDrawHighlighter(tableViewer));
TableViewerEditor.create(tableViewer, focusCellManager, activationStrategy, ColumnViewerEditor.DEFAULT);

此时我们只需要将之前的EditingSupport根据实际业务完善下基本就OK了, 整体源码见下一小节, 先看下效果.

在这里插入图片描述

数据校验

实际业务中可能对某些数据有特殊要求, 此时就要对输入的数据进行校验, 并给出提示, 我们可以借助MessageBox来实现提示, 将校验逻辑放在EdittingSupport.setValue方法中.
比如对年龄的校验可以这样写:

@Override
protected void setValue(Object o, Object o1) {String newValue = String.valueOf(o1);if (o instanceof People people) {switch (title) {case "年龄" -> {try {people.setAge(Integer.parseInt(newValue));} catch (Exception e) {MessageBox messageBox = new MessageBox(shell);messageBox.setText("输入不合法");messageBox.setMessage("必须是数字");messageBox.open();}}// 其他逻辑}}tableViewer.update(o, null);
}

看下效果:
在这里插入图片描述

源码

import org.eclipse.jface.viewers.*;
import org.eclipse.jface.widgets.TableColumnFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.*;import java.util.Arrays;public class Main {public static void main(String[] args) {final Display display = Display.getDefault();final Shell shell = new Shell();shell.setLayout(new FillLayout());shell.setSize(500, 375);shell.setText("SWT Application");//注意这里,SWT.MULTI代表可以选择多行,SWT.FULL_SELECTION代表可以整行选择,SWT.BORDER边框,SWT.V_SCROLL ,SWT.H_SCROLL滚动条TableViewer tableViewer = new TableViewer(shell, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);Table table = tableViewer.getTable();// 表格边框线是否可见table.setLinesVisible(true);// 表头是否可见table.setHeaderVisible(true);// 设置表格大小table.setBounds(97, 79, 373, 154);String[] titles = {"ID", "姓名", "性别", "年龄"};// 创建列头信息, 并最终绑定到tableArrays.stream(titles).forEach(title -> {TableColumn tableColumn = TableColumnFactory.newTableColumn(SWT.NONE).width(80).text(title).create(table);new TableViewerColumn(tableViewer, tableColumn).setEditingSupport(new EditingSupport(tableViewer) {@Overrideprotected CellEditor getCellEditor(Object o) {return new TextCellEditor(tableViewer.getTable());}@Overrideprotected boolean canEdit(Object o) {return !"ID".equalsIgnoreCase(title);}@Overrideprotected Object getValue(Object o) {if (o instanceof People people) {return switch (title) {case "ID" -> String.valueOf(people.getId());case "姓名" -> people.getName();case "性别" -> people.getSex();case "年龄" -> String.valueOf(people.getAge());default -> "";};}return "";}@Overrideprotected void setValue(Object o, Object o1) {String newValue = String.valueOf(o1);if (o instanceof People people) {switch (title) {case "年龄" -> {try {people.setAge(Integer.parseInt(newValue));} catch (Exception e) {MessageBox messageBox = new MessageBox(shell);messageBox.setText("输入不合法");messageBox.setMessage("必须是数字");messageBox.open();}}case "姓名" -> people.setName(newValue);case "性别" -> people.setSex(newValue);}}tableViewer.update(o, null);}});});ColumnViewerEditorActivationStrategy activationStrategy = new ColumnViewerEditorActivationStrategy(tableViewer) {@Overrideprotected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {// 只有双击事件才激活编辑器return event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION;}};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.setLabelProvider(PeopleLabelProvider.getInstance());People people = new People();people.setId(1);people.setName("张三");people.setSex("男");people.setAge(10);tableViewer.setInput(new People[]{people});shell.open();while (!shell.isDisposed()) {if (!display.readAndDispatch()) {display.sleep();}}}
}

其他方案

实现编辑支持还有其他方式, 比如实现ICellModifier, 不过这种方式需要额外指定properties用来指定和列名的对应关系, 个人不是很喜欢这种, 有兴趣可以参考: Swt/Jface tableViewer入门教程三(加入在表格上直接编辑数据)

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

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

相关文章

java.lang.IllegalArgumentException: java.net.UnknownHostException: xxx

windows系统下连接hdfs进行操作时,上来就出现java.lang.IllegalArgumentException: java.net.UnknownHostException: xxx java.lang.IllegalArgumentException: java.net.UnknownHostException: liujianat org.apache.hadoop.security.SecurityUtil.buildTokenServ…

Keil Vision5—新建工程project

注意:创建的工程目录必须是纯英文目录 目录 1.开始配置 2.为该路径下新建个文件夹 3.选择器件 4.工程配置 4.右击魔术棒,设置参数 ​编辑 (1)target配置 (2)output配置 (3)c…

字符串结尾空格比较相关参数BLANK_PAD_MODE(DM8:达梦数据库)

DM8:达梦数据库 字符串结尾空格比较相关参数BLANK_PAD_MODE 环境介绍1 BLANK_PAD_MODE01.1 初始化数据库1.2 创建测试表 T0 2 BLANK_PAD_MODE12.1 初始化数据库2.2 创建测试表 T1 3 BLANK_PAD_MODE只对字段varchar类型生效3.1 BLANK_PAD_MODE 对char 类型对比无效3.2 在两个数据…

计算机中了halo勒索病毒怎么清除,halo勒索病毒解密数据恢复

科技的进步加快了企业发展的步伐,网络技术的不断应用为企业的生产运营提供了极大帮助,但随之而来的网络安全威胁也不断增加,近期,云天数据恢复中心接到很多企业的求助,企业的计算机服务器遭到了halo勒索病毒攻击&#…

Jmeter快速入门

文章目录 1.安装Jmeter1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 1.安装Jmeter Jmeter依赖于JDK,所以必须确保当前计算机上已经安装了JDK,并且配置了环境变量。 1.1.下载 可以Apache Jmeter官网下载,地址&#xf…

uni-app打包后,打开软件时使其横屏显示

找到page.json文件,在global加入以下代码: 这样就可以横屏显示了。

CANdelaStudio 使用教程 1

文章目录 CANdelaStudio 软件下载CANdelaStudio 软件的权限View Edition 和 Admin Edition 区别:打开文件 CDD / CDDT 文件新建 CDD 文件新建 CDDT 文件CDD 和 CDDT 文件的区别 CANdelaStudio 软件下载 1、 来到 Vector 官网下载中心 https://www.vector.com/cn/zh…

[shader] 光照入门(未完结。。。

反射 漫反射:而当物体表面粗糙时,我们把物体表面看作无数不同方向的微小镜面,则这些镜面反射出的光方向均不相同,这就是漫反射。 高光反射:我们假定物体表面光滑,只有一个镜面,那么所有的光都…

报错For debugging consider passing CUDA_LAUNCH_BLOCKING=1.

.报错For debugging consider passing CUDA_LAUNCH_BLOCKING1. /aten/src/ATen/native/cuda/NLLLoss2d.cu:103: nll_loss2d_forward_kernel: block: [29,0,0], thread: [707,0,0] Assertion t > 0 && t < n_classes failed. 报错信息如下&#xff1a; ./aten/…

力扣labuladong——一刷day46

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣971. 翻转二叉树以匹配先序遍历二、力扣987. 二叉树的垂序遍历三、力扣666. 路径总和 IV 前言 二叉树的递归分为「遍历」和「分解问题」两种思维模式&a…

面试:RocketMQ相关问题

文章目录 什么是 RocketMQ&#xff0c;有哪些使用场景&#xff1f;RocketMQ 由哪些⻆色组成&#xff0c;每个⻆色作用和特点是什么&#xff1f;RocketMQ 中的 Topic 和 JMS 的 queue 有什么区别&#xff1f;RocketMQ 消费模式有几种&#xff1f;RocketMQ 的 Consumer 是如何消费…

【深度学习】Python快捷调用InsightFace人脸检测,纯ONNX推理

pypi资料&#xff1a; https://pypi.org/project/insightface/ 模型选择&#xff1a; https://github.com/deepinsight/insightface/tree/master/python-package#model-zoo onnxruntime的GPU对应CUDA &#xff1a; https://onnxruntime.ai/docs/reference/compatibility …

1999-2021年地级市城镇居民人均消费性支出数据

1999-2021年地级市城镇居民人均消费性支出数据 1、时间&#xff1a;1999-2021年 2、指标&#xff1a;城镇居民人均消费性支出 3、范围&#xff1a;290个地级市 4、来源&#xff1a;城市年鉴、地级市统计公报 5、指标解释&#xff1a; 城镇居民人均消费性支出&#xff1a;指…

kubesphere安装依赖文件

yum install socat -y yum install conntrack -y

GAMES101-Homework2

目录 普通作业&#xff1a;提高作业&#xff1a;参考博客博客一博客二博客三 附代码框架的个人一些注释和理解&#xff1a;rasterizer.cppTriangle.cpp 普通作业&#xff1a; // 判断点是否在三角形内的辅助函数 static bool insideTriangle(float x, float y, const Vector3f…

再添千万级罚单,某银行年内罚款过亿!金融行业合规问题亟待解决

11月17日晚间&#xff0c;国家金融监管总局上海监管局披露行政处罚信息显示&#xff0c;某银行因32项违法违规事实收到两张690万元的大额罚单&#xff0c;合计罚款金额达1380万元。但这并不是银行该今年收到的第一张大额罚单。今年4月28日&#xff0c;该行因在结售汇、外币理财…

k8s-pod生命周期 4

容器环境初始化 pod 由pod 镜像来提供&#xff0c;在pod 生命周期里容器主要分为两种&#xff1a;初始化容器和主容器 初始化容器一定要成功运行并退出&#xff0c;当初始化容器运行退出完了之后主容器开始和运行 主容器开始运行的时候&#xff0c;有两个探针&#xff1a;存…

什么是arguments对象?

arguments 对象是 JavaScript 中的一个特殊对象&#xff0c;它包含了函数被调用时传入的所有参数。arguments 对象是一个类数组对象&#xff0c;它有一个 length 属性和按数字索引的元素。 每个函数在执行时都会自动创建一个 arguments 对象。我们可以通过arguments去访问参数…

网络图简单计算规则

单代号进度网络图&#xff08;节点法&#xff09; 概念 计算规则 &#xff08;顺时针计算法&#xff09; &#xff08;TF取之差&#xff09; &#xff08;T&#xff1a;持续时间&#xff09; ES → EF (ES取大EF加T) ↑ T ↑ &#xff08;TF&#xff1a;总时差&…

NOIP2003提高组第二轮T3:加分二叉树

题目链接 [NOIP2003 提高组] 加分二叉树 题目描述 设一个 n n n 个节点的二叉树 tree \text{tree} tree 的中序遍历为 ( 1 , 2 , 3 , … , n ) (1,2,3,\ldots,n) (1,2,3,…,n)&#xff0c;其中数字 1 , 2 , 3 , … , n 1,2,3,\ldots,n 1,2,3,…,n 为节点编号。每个节点都…