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

这篇具有很好参考价值的文章主要介绍了QML实现文件十六进制数据展示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

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

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

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

先来看效果:
QML实现文件十六进制数据展示,QML十六进制数据,hexview,十六进制,二进制文件
这是在QML项目中实现的,中间的数据展示部分是使用QHexView代码Widget实现的。


本文demo 点击下载


正文

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

上面说到,QML中要自定义在paint中绘制,需要继承QQuickPaintedItem,然后重写paint函数,而QML Scene Graph场景图绘制是在两个不同的线程中,这个在Qt帮助文档中有说明:
QML实现文件十六进制数据展示,QML十六进制数据,hexview,十六进制,二进制文件
也就是说,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);

可在此基础上进行扩展。

整体目录结构:
QML实现文件十六进制数据展示,QML十六进制数据,hexview,十六进制,二进制文件


本文demo 点击下载


参考文章:
https://blog.csdn.net/r5014/article/details/92642626
https://github.com/Dax89/QHexView文章来源地址https://www.toymoban.com/news/detail-701534.html

到了这里,关于QML实现文件十六进制数据展示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【FPGA仿真】Matlab生成二进制、十六进制的txt数据以及Vivado读取二进制、十六进制数据并将结果以txt格式保存

    在使用Vivado软件进行Verilog程序仿真时可能需要对模块输入仿真的数据,因此我们需要一个产生数据的方法(二进制或者十六进制的数据),Matlab软件是一个很好的工具,当然你也可以使用VS等工具。 以下分别给出了使用Matlab模拟产生二进制和十六进制数据的例子,例子仅供参

    2024年02月01日
    浏览(38)
  • Ubuntu vim 以十六进制的形式显示文件内容

    Vim(Vi IMproved)是一款开源的文本编辑器,是 Unix 系统中经典的 vi 编辑器的改进版本。它具有强大的功能和高度可定制性,被广泛应用于程序开发、系统管理和文本编辑等领域。 以下是 Vim 的一些主要特点和功能: 模态编辑:Vim 包含多种编辑模式,包括普通模式、插入模式

    2024年02月13日
    浏览(31)
  • 十六进制数如何转十进制 C/C++实现

    一.问题分析 我们输入一个真正意义上的十六进制数,0x开头,返回一个十进制数。 二.思路生成 输入一个十六进制的数,依次取出它的每一位,然后根据权值累加,得到10进制值。 三.问题解决及代码 以C++为例 1.如何输入一个16进制数,使用标志符hex,cinhex\\\"变量名\\\" 如果指定

    2024年02月04日
    浏览(38)
  • MATLAB输出串口发送所需十六进制数据

      可以用一个文件来测试其是否符合我们的要求,将一个二进制向量转化为十六进制向量,每个十六进制数表示1byte(不足1byte前面补0),并且写入txt文件中,每byte之间用空格隔开。   打开存储路径下的txt文件,可见符合预期需求。   使用串口助手载入txt文件,可见

    2024年02月16日
    浏览(36)
  • rk3566通过stty向串口发送十六进制数据

    在Unix或Linux系统中,stty命令可以用于设置和控制终端的参数。要发送十六进制数据给串口,需要使用stty命令设置终端为raw模式,这样终端就不会将输入或输出数据进行任何处理。然后,可以使用echo命令将十六进制数据写入串口。 以下是在Linux系统中发送十六进制数据的步骤

    2023年04月10日
    浏览(34)
  • sm3加密(32位哈希,64位十六进制数据)

    https://blog.csdn.net/nicai_hualuo/article/details/121555000 中介绍了sm3的算法并给出了可用代码,我只是将其拷贝过来,测试、去掉多余的输出,并进行了简单封装,以方便项目中使用。 修正了十六进制转字符串和十进制的方法支持小写的十六进制字符串。 用法见main函数。

    2024年02月11日
    浏览(34)
  • Qt自定义窗口部件/控件(实现一个十六进制微调框SpinBox)

    在某些情况下,我们发现Qt窗口控件需要更多的自定义定制,这些定制可能要比它在Qt设计师里可设置的属性或者对它调用的那些函数更多一些。一个简单而直接的解决方法就是对相关的窗口部件类进行子类化并且使它能够满足我们的需要。 本文主要是通过实现一个十六进制微调

    2024年02月11日
    浏览(32)
  • Linux C/C++ 分析网络流量(十六进制TCP数据包分析)

    在分析TCP数据包时,理解TCP协议的工作原理和报文格式是关键。TCP是一种面向连接的、提供可靠的、端到端的字节流传输服务。其头部结构包括源端口、目标端口、序列号、确认应答号等字段。序列号是在建立连接时由计算机生成的随机数作为初始值,每发送一次数据,就累

    2024年02月03日
    浏览(29)
  • 【FPGA】Verilog:实现十六进制七段数码管显示 | 7-Segment Display

    写在前面: 本章主要内容为理解七点数码管显示的概念,并使用 Verilog 实现。生成输入信号后通过仿真确认各门的动作,通过 FPGA 检查在 Verilog 中实现的电路的操作。 七段数码管是利用多重输出功能的非常有用的元件。该元件用于字符化,如十进制、十六进制数等。适当配

    2024年02月02日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包