QML实现文件十六进制数据展示

2023-11-17

前言

将一个二进制文件直接拖放到Qt Creator中可以直接查看到以十六进制显示的数据格式,如:
在这里插入图片描述
要实现一个这样的效果,还是要花不少时间的。

在网上找了挺多示例,其中一个开源代码效果不错(参考这里),但是是在QWidget中实现的,通过继承QAbstractScrollArea来实现数据滚动绘制。

如果QML中要自定义在paint中绘制,需要继承QQuickPaintedItem,那要实现这样的滚动分页展示就比较麻烦了。尝试了一下直接将Widget中实现的效果封装一下放到QML中去使用,就会比较省事,毕竟原有的开源效果已经做得很好了。
以此思路,开搞!!!

先来看效果:
在这里插入图片描述
这是在QML项目中实现的,中间的数据展示部分是使用QHexView代码Widget实现的。


本文demo 点击下载


正文

将Widget嵌入到QML中使用,先来看会遇到什么问题。

上面说到,QML中要自定义在paint中绘制,需要继承QQuickPaintedItem,然后重写paint函数,而QML Scene Graph场景图绘制是在两个不同的线程中,这个在Qt帮助文档中有说明:
在这里插入图片描述
也就是说,paint()不是从主GUI线程调用的,而是从启用GL的渲染器线程调用的.。

那这会带来什么问题呢,继续看
由于主UI框架是用QML做的,我们想把Widget嵌入到QML中使用,就需要新建一个类继承QQuickPaintedItem然后把Widget放到其中,封装起来后将该类通过qmlRegisterType注册交给QML去引用。那Widget窗口中的各种事件就需要从QML这边发送过去,所以需要进行一次事件转发,也就是说将QQuickPaintedItem获得的事件合理的转发给QWidget让QWidget能处理对应的消息。这个可以通过在QQuickPaintedItem中过滤事件后进行转发。
而UI渲染是在paint中调用widget的rander进行,我们知道Widget中UI渲染是在主线程,上面讲到 QQuickPaintedItem中的paint()不是从主GUI线程调用的,而是从启用GL的渲染器线程调用的,所以这样调用就会出现断言报错:

 "Cannot send events to objects owned by a different thread. Current thread 0x0x24f6d9d9db0. Receiver ''....

好在我们可以直接用Release模式规避这个断言,没办法,只能这样搞了,也只有这种方式能实现这种非常规的调用。

继承QQuickPaintedItem封装的关键代码:

HexViewItem::HexViewItem()
{
    this->setAcceptHoverEvents(true);
    this->setAcceptedMouseButtons(Qt::AllButtons);
    setFlag(ItemAcceptsInputMethod, true);
    setFlag(ItemIsFocusScope, true);
    setFlag(ItemHasContents, true);
}

//不能在构造函数中调用
void HexViewItem::init()
{
    m_pHexContainer = new HexViewContainer();
    m_pHexContainer->init();
    qDebug() << __FUNCTION__ << "this size" << size();
    m_pHexContainer->resize(this->size().toSize());
    if(m_pHexContainer)
    {
        m_pHexContainer->createWinId();
        m_pHexContainer->installEventFilter(this);

        QWindow* pw = (QWindow*)(window());
        pw->installEventFilter(this);
        this->update();
    }
}

bool HexViewItem::sendEventToWidget(QEvent *e)
{
    if(!m_pHexContainer)return false;
    QWindow* wHandle = m_pHexContainer->windowHandle();
    bool res = false;
    if(wHandle)
    {
        res = qApp->sendEvent(wHandle, e);
    }
    return res;
}


void HexViewItem::paint(QPainter *painter)
{
    painter->save();
    if(m_pHexContainer)
    {
        m_pHexContainer->render(painter);
    }
    painter->restore();
}

bool HexViewItem::eventFilter(QObject *obj, QEvent *e)
{
    QWindow* pw = (QWindow*)(window());
    bool res = QQuickPaintedItem::eventFilter(obj, e);
    if(obj == m_pHexContainer)
    {
        switch(e->type())
        {
        case QEvent::Paint:
        {
            QPaintEvent* pe = (QPaintEvent*)e;
            this->update(pe->rect());
        }
            break;
        }
    }
    else if(obj == pw)
    {
        //* 如果是鼠标等(有鼠标坐标信息的事件。)的话我们得计算一下偏移量并修正一下,这里就只处理QMouseEvent和QWheelEvent作为示例
        //* 如果有其他类似的也需要修正,不然可能坐标偏移
        switch(e->type())
        {
        case QEvent::MouseButtonDblClick  :
        case QEvent::MouseButtonPress	  :
        case QEvent::MouseButtonRelease	  :
        case QEvent::MouseMove	          :
        case QEvent::MouseTrackingChange  :
        case QEvent::Move	              :
        {
            QMouseEvent *me = (QMouseEvent*)e;
            QEvent::Type type = me->type();
            QPointF localPosF = me->localPos();
            Qt::MouseButton mouseButton = me->button();
            Qt::MouseButtons mouseButtons = me->buttons();
            Qt::KeyboardModifiers modifiers = me->modifiers();

            //修正一下localpos
            QPointF offsetF = mapToScene(QPoint(0,0));
            QPointF diffPosF = localPosF - offsetF;

            QMouseEvent tme(type, diffPosF, mouseButton, mouseButtons, modifiers);
            sendEventToWidget(&tme);
        }
            break;
        case QEvent::Wheel:
        {
            QWheelEvent *we = (QWheelEvent*)e;
            QPointF localPosF = we->posF();
            QPointF gloabalPosF = we->globalPosF();
            QPoint  pixelDelta = we->pixelDelta();
            QPoint  angleDelta = we->angleDelta();
            int qt4Delta = we->delta();
            Qt::Orientation orientation = we->orientation();
            Qt::MouseButtons mouseButtons = we->buttons();
            Qt::KeyboardModifiers modifiers = we->modifiers();

            //修正一下localpos
            QPointF offsetF = mapToScene(QPoint(0,0));
            QPointF diffPosF = localPosF - offsetF;

            QWheelEvent twe(diffPosF, gloabalPosF, pixelDelta, angleDelta, qt4Delta, orientation, mouseButtons, modifiers);
            sendEventToWidget(&twe);
        }
            break;
        default:
        {
//             sendEventToWidget(e);
        }
            break;
        }
    }

    return res;
}

void HexViewItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry);

    if(m_pHexContainer)
    {
        m_pHexContainer->setGeometry(newGeometry.toRect());
    }
}

bool HexViewItem::event(QEvent *e)
{
    return __super::event(e);
}

关键点,将QQuickItem的窗口注册事件过滤器:

QWindow* pw = (QWindow*)(window());
pw->installEventFilter(this);

eventFilter就是过滤一些需要用到的关键事件进行转发,在paint()中调用Widget的render进行UI刷新。

QHexView源码进行过一些修改,添加了一些接口可供QML中快速设置,如:高亮某段数据、快速定位,头部底部对齐,主题切换,截图保存,切换展示宽度等

Q_INVOKABLE void setFilePath(int index, QString filePath);
Q_INVOKABLE void updateGeo();
Q_INVOKABLE void setSelect(int index,int pos,int len);
Q_INVOKABLE void closeFile(int index);  //关闭文件
Q_INVOKABLE void alignment(bool head,int index = -1);  //头部 尾部对齐
Q_INVOKABLE QStringList renderHexView(QList<int> fileIndexs);
Q_INVOKABLE void setTheme(bool darkTheme);
Q_INVOKABLE void setHexLineWidth(quint8 value);

可在此基础上进行扩展。

整体目录结构:
在这里插入图片描述


本文demo 点击下载


参考文章:
https://blog.csdn.net/r5014/article/details/92642626
https://github.com/Dax89/QHexView

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QML实现文件十六进制数据展示 的相关文章

  • EXCEL 如何制作混合数据透视图柱形图添加折线图

    当我们制作了数据透视图 增长率什么的 需要在柱形图上增加折线图 如何做呢 工具 原料 EXCEL2007 方法 步骤 1 新建一个工作表 而后数据入局 制作一个带增长率的数据透视表 2 选中数据 而后在上方功能区找到插入菜单 在下拉选项了里
  • PM 和 PL 的区别

    工作之前只知道PM是项目经理 PL是 项目负责人 看过几本职场小说 据我理解 PM职能更多是在人事和外部资源调度方面 而PL更多在技术层面去领导下面的开发人员 小组有PL PM各一个 同事对待他们的方式给我的理解就是 PM要比PL大 工作汇
  • linux————zabbix搭建

    目录 一 zabbix的概述 二 构成 一 server 二 web页面 三 数据库 四 proxy 五 agent 三 zabbix监控对象 四 zabbix的常用术语 五 zabbix监控框架 一 zabbix client架构 二 z
  • 视频会议用户洞察白皮书

    导读 白皮书重点通过桌面研究和定量调研的方式 对疫情后视频会议行业发展现状 用户行为及需求偏好和用户付费意愿等内容展开研究 以期加深对视频会议行业及用户的了解 希望能为相关企业与资本市场提供参考意见与运营建议 关注公众号 互联互通社区 回复
  • 蓝桥杯国赛 C/C++ ABC组题解(第四届 ~ 第十二届)

    2020年第十一届蓝桥杯国赛 题号 类型 C A组 C B组 C C组 试题A 结果填空 合数个数 美丽的 2 美丽的 2 试题B 结果填空 含 2 天数 日期处理 扩散 BFS 合数个数 试题C 结果填空 本质上升序列 线性DP 阶乘约数
  • karma使用webpack的代码覆盖率测试

    前言 距离上一次博客有2个月了 倒不是没有可写东西就是提不起劲写 不说这些了这次写下我使用 karma webpack 中遇到的代码覆盖率问题 一 karma的使用 自个去搜吧 感觉讲这个的真的多 我就说一些建议 karma的测试框架改用m
  • LVGL 获取光标坐标位置

    为了方便获取物理按键输入的坐标 在仿真时直接开启打印坐标显示 获取自己想要的坐标 核心代码主要接口 indev proc press 打印光标位置 注意要先使能打印开关 LV LOG WARN pressed at x d y d proc
  • HTTP:断点续传原理图文分析

    起源 以前 用户不能使用现在这种高速的带宽访问互联网 当时 下载一个尺寸稍大的图片或文件就已经很吃力了 如果下载过程中遇到网络中断的情况 那就必须重头开始 一 获取部分内容 在HTTP 1 1中 为了解决上述问题 需要一种可恢复的机制 所谓
  • C++ Web服务器 - 用户登录(三)

    newobj跨平台开发框架 https github com Liuccysdgg newobj 本片着重介绍 MYSQL连接池 HTTP静态文件响应 部分JS等 效果演示 一 MYSQL连接池 如果每次业务请求进来时去创建mysql连接并
  • Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime问题解决

    Node Sass does not yet support your current environment Windows 64 bit with Unsupported runtime问题解决 运行原先vue程序时 npm run d
  • Typescript、VUE3的相关介绍

    一 Typescript 1 TypeScript 的由来 TypeScript 是由微软开发的一款开源的编程语言 TypeScript 是 Javascript 的超集 遵循最新的 ES6 ES5 规范 TypeScript 扩展了 Ja
  • 动态规划问题——最长上升子序列(LIS)(一)

    原文转载自我的博客benym cn 推荐链接 动态规划问题 最长上升子序列 LIS 二 动态规划问题 最长上升子序列 LIS 三 如 求 2 7 1 5 6 4 3 8 9 的最长上升子序列 我们定义d i i 1 n 来表示前i个数以A
  • chatgpt赋能Python-python2_7如何安装

    Python 2 7如何安装 Python 2 7是一个广泛使用的Python版本 其可以在Windows和Linux上安装 本文将介绍Python 2 7如何安装 并提供相关步骤和指南 下载Python 2 7 首先 您需要下载Pytho

随机推荐

  • Python for循环嵌套

    视频版教程 Python3零基础7天入门实战视频教程 在有复杂应用的时候 我们可以通过for循环的嵌套来实现 比如打印二维的行列 这里先学习下range 方法 获取一个数字序列 案例 range stop 返回0到stop 1的数字序列 f
  • SQL 通配符

    在 SQL 中 通配符与 SQL LIKE 操作符一起使用 SQL 通配符用于搜索表中的数据 在 SQL 中 可使用以下通配符 通配符 描述 替代 0 个或多个字符 替代一个字符 charlist 字符列中的任何单一字符 charlist
  • Angular项目配置本地https访问

    Angular项目配置本地https访问 首先 先创建一个项目 d work learn ng new angular https 然后cd到刚生成的项目的根目录 建立一个cert目录 用于存放我们的密钥证书等文件 cd angular h
  • 转载---贪心算法

    转载博主 1 贪心算法简介 1 1 基本定义 在贪婪算法 greedy method 中 我们要逐步构造一个最优解 每一步 我们都在一定的标准下 做出一个最优决策 做出决策所依据的标准称为贪心准则 greedy criterion 贪心算法
  • python语法-类型注解

    python语法 类型注解 类型注解 在代码中涉及数据交互的地方 提供数据类型的注解 显式说明 主要功能 帮助第三方IDE工具 如pycharm 对代码进行类型推断 协助做代码提示 帮助开发者自身对变量进行类型注释 支持 变量的类型注解 函
  • 如何安装wsl以及安装时遇到的一些问题

    首先我安装wsl是参考这篇文章 Windows安装WSL详解 讲得挺具体 如果安装过程一切顺利就可以跳过下面的内容了 wsl在终端安装遇到的问题 当我在终端输入wsl install 返回了一列数据 但显然不是安装成功 于是我输入wsl i
  • document onload和window onload的区别?

    答 Document onload 是在结构和样式加载完成才执行的JS Window onload 不仅仅要在结构和样式加载完 还要执行完所有的样式 图片这些资源文件 完全加载完才会触发Window onload事件
  • Oracle SQL查询之Like使用正则表达式

    select from si0001 temp a where regexp like a xm a z A Z 查询xm字段带有英文的数据
  • 2019年第十届蓝桥杯国赛B组试题G-排列数-next_permutation枚举,模拟

    在一个排列中 一个折点是指排列中的一个元素 它同时小于两边的元素 或者同时大于两边的元素 对于一个 1 n 的排列 如果可以将这个排列中包含 t个折点 则它称为一个 t 1 单调序列 例如 排列 1 4 2 3 是一个 3 单调序列 其中
  • Mapreduce学习基础

    一 Mapreduce的基础 1 1 为什么要学习Mapreduce 1 单机资源受限 比如CPU 磁盘 2 分布式计算的程序的复杂度特别高 难度大 mapreduce就是解决以上问题的 1 利用集群的所有cpu 所有内存 所有磁盘 2 m
  • 【TCP/IP】第四章 IP协议

    4 1 即网际协议 TCP IP的心脏是互联网层 这一层主要是由IP Internet Protocol 和ICMP Internet Control Message Protocol 两个协议组成 IP相当于OSI参考模型的第3层 IP
  • 06-TensorFlow 自制数据集

    1 数据文件介绍 数据集下载 https download csdn net download qq 41865229 85254826 训练集60000张数字图片 测试集10000张图片 都是黑底白字的灰度图 每张图有28行28列个像素点
  • c#下各种数据库操作的封装!(支持ACCESS,SQLSERVER,DB2,ORACLE,MYSQL)

    首先定义数据库操作的标准接口IDBAccess 定义接口的基本功能 通过基本的接口设置 完成数据访问的统一抽象 public interface IDBAccess void Init string strServer string str
  • android编译时报错:Error parsing XML: unbound prefix 的错误原因及解决方案

    原因之一 拼写错误 例如 android写成androd之类 原因之二 xmlns没有添加 有的时候 自定了一些view 且新加了一些自定义的命名 那么需要添加声明到根上 如果忘了添加也会报这个错误 xmlns calendar http
  • javacv 人脸检测_使用JavaCV进行手和手指检测

    javacv 人脸检测 这篇文章是Andrew Davison博士发布的有关自然用户界面 NUI 系列的一部分 内容涉及使用JavaCV从网络摄像头视频提要中检测手 注意 本章的所有源代码都可以从http fivedots coe psu
  • 抖音微信消息推送情侣告白浪漫(简易版)

    抖音微信消息推送情侣告白浪漫 简易版 一 首先去微信公众平台用微信扫码登录 登录后会自动生成属于自己的appId appSecret 二 在上述登录后页面中下拉 用一个手机扫码会生成user id 即微信消息推送的接收方 三 点击下方的新增
  • PBR渲染原理

    PBR渲染原理 Tags computer graphics 基于PBR做渲染 需要涉及到很多物理学 几何学 热辐射学概念 本文将逐一介绍每个关键概念 并给出相关重要公式 微平面 microfacets 理论 微观尺度下的任意一个平面 su
  • bootstrap table 表头排序

    在columns 里面加上 sortable true 如下 columns field width 50 align center title sortable true
  • Calendar类介绍 获取对象方式 和方法

    重点 是一个抽象日历类 Calendar 类是一个抽象类 它为特定瞬间与一组诸如 YEAR MONTH DAY OF MONTH HOUR 等 日历字段之间的转换提供了一些方法 并为操作日历字段 例如获得下星期的日期 提供了一些方法 无法直
  • QML实现文件十六进制数据展示

    前言 将一个二进制文件直接拖放到Qt Creator中可以直接查看到以十六进制显示的数据格式 如 要实现一个这样的效果 还是要花不少时间的 在网上找了挺多示例 其中一个开源代码效果不错 参考这里 但是是在QWidget中实现的 通过继承QA