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.hqwc.cn/news/211729.html

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

相关文章

Springmvc实现增删改差

一、包结构 二、各层代码 (1)数据User public class User {private Integer id;private String userName;private String note;public User() {super();}public User(Integer i, String userName, String note) {super();this.id i;this.userName userName;this.note note;…

【源码分析】zeebe actor模型源码解读

zeebe actor 模型🙋‍♂️ 如果有阅读过zeebe 源码的朋友一定能够经常看到actor.run() 之类的语法,那么这篇文章就围绕actor.run 方法,说说zeebe actor 的模型。 环境⛅ zeebe release-8.1.14 actor.run() 是怎么开始的🌈 Lon…

程序员接单,宝藏好平台抄底攻略清单!五大平台精选。

前阵子”双十一“购物节狂欢促销,各种好货清单席卷而来。 程序员购不购物我不知道,但是这个兼职、接单清单相信你一定用得着。 搜罗海量信息,整理大量数据与评价,挖出了5个宝藏平台,绝对个个精选,保证量大…

改善钢棒直线度检测可靠性 在线直线度测量仪替代人工检测

根据GB/T908-2019标准规定,钢棒的尺寸包括直径或边长、长度、弯曲度等。因此钢棒在生产中进行尺寸检测,保证成品符合规格,是降低废品率的重要一环。 有些钢棒的弯曲很明显,肉眼可看,但更有很多不明显的需要借助工具检测…

python -opencv 图像锐化

python -opencv 图像锐化 图像锐化其实,是一种增强图片对比度的技术,我们可以通过计算图像的导数,把导数绝对值数值大于零的数值加回原图像,通过这种方法,可以增强图像的对比度。 实现代码如下: import c…

PHP 语法||PHP 变量

PHP 脚本在服务器上执行&#xff0c;然后将纯 HTML 结果发送回浏览器。 基本的 PHP 语法 PHP 脚本可以放在文档中的任何位置。 PHP 脚本以 <?php 开始&#xff0c;以 ?> 结束&#xff1a; <?php // PHP 代码 ?> 值得一提的是&#xff0c;通过设定php.ini的相…

【C++】拷贝构造函数,析构函数详解!

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

国家超级计算济南中心低代码平台应用实践

摘要&#xff1a;文章主要介绍了济南超算使用低代码平台明道云解决了一系列业务问题&#xff0c;包括资产管理、人员与机构管理、流程制度管理等。通过明道云平台&#xff0c;济南超算成功地将不同部门的业务信息进行整合&#xff0c;提高了工作效率和管理水平。文章还强调了明…

(一)C语言之入门:使用Visual Studio Community 2022运行hello world

使用Visual Studio Community 2022运行c语言的hello world 一、下载安装Visual Studio Community 2022 与 新建项目二、编写c helloworld三、编译、链接、运行 c helloworld1. 问题记录&#xff1a;无法打开源文件"stdio.h"2. 问题记录&#xff1a;调试和执行按钮是灰…

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

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

批量将本地N个英文Html文档进行中文翻译-操作篇

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

【LeetCode】挑战100天 Day12(热题+面试经典150题)

【LeetCode】挑战100天 Day12&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-142.1 题目2.2 题解 三、面试经典 150 题-143.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…