jjzjj

QT自定义QTextEdit实现大数据的实时刷新显示

疯狂的挖掘机 2024-07-02 原文

文章目录


前言

最近使用QT中的QTextEdit控件,作为实时数据显示的UI,在一次写入超过多少k的时候循环写入则会卡顿,网上也没有什么好的解决方案,左思右想自己实现一个类似的demo。后期封装起来继承QWidget就可以在其他地方应用,直接上图:

主要功能介绍:
1、这里用一个6M多的文件加一个定时器100ms模拟实时数据,可以 自定义保存多少数据,默认是保存10M数据;
2、行号的显示和隐藏;
3、右侧滚动条可以查看保存的数据;
4、支持大数据的保存实时刷新。


一、 思路

QT自带的QTextEdit在一次显示K以上级别的还是可以的,但是一次性读入上M数据基本上就会卡死,如果在实时监测数据,这个控件基本不能使用(少量数据是可以的)。目前的思路是分页显示:

上述自定义的TextEdit其实由1、QTextEdit(作为行号)+2、QTextEdit(主内容)+3、scrollbar组成拼接的一个UI。
1、1和2自动显示的水平和竖直的滚动条,将3滚动条与其信号产生关联(有信号)
2、设置当前显示的区域的最大列数和每一行最大字节数(这样就可以知道显示多少字节数了);
3、设置一个缓存来存储收到的内容,示例用了一个10M的QString来存储数据,每次来数据就去偏移,这个缓存就是为了暂存。
4、显示区域只显示设置的最大列数,实际设置为100列足够占满显示区域每次点击右侧滚动条最上或者最下小倒三角就自动翻页(翻页的大小也是固定的,从缓存找相应的位置)

所以说即使是6M数据,显示的只是最后100行数据,在实时刷新的时候不会卡界面,如果想要查看之前的数据,只需要向上翻页,从缓存读取显示出来,用户体验还是蛮好的。

二、关键部分代码

1.缓存

这个缓存我想了很久,最后直接用一个QString来做

代码如下(示例):

  mwarehouse.fill(QChar(),10*1024*1024);

移位部分代码

void MainWindow::setDataToHouse(QString &str)
{
    int Maxsize = mwarehouse.size();
    if(str.size()>=Maxsize)
    {
        mwarehouse= str;
        return;
    }
    QString test = mwarehouse.mid(str.size(),-1);
    mwarehouse.replace(0,Maxsize-str.size(),mwarehouse.mid(str.size(),-1));
    mwarehouse.replace(Maxsize-str.size(),str.size(),str);
}

2.滚动部分代码

代码如下(示例):

void MainWindow::showScrollContent(bool up)
{
    int Maxsize = mwarehouse.size();
    uint tmpsize = getScrollshowAreaSize();
    uint cursize = mtextedit->toPlainText().size();
    if(up)
    {
        if(cyclesnum<mlinenum){return;}
        mupnum+=tmpsize;
        cyclesnum-=  (mlinenum*2-1);
    }
    else{
        if(mupnum<tmpsize)
        {
           mupnum=0 ;
           return;
        }
        mupnum-=cursize;
    }
    QString allowString = mwarehouse.mid(Maxsize-tmpsize-mupnum,tmpsize);
    showString(allowString);
}

2.根据每一行最大字节数显示数据

void MainWindow::showString(QString mess,bool cyc )
{
        if(cyc)
        {
            uint cycles = (mess.size())/(mlinenumsize);
            qDebug()<<"!!!!!"<<cycles;
            if(cycles>0)
            {
                for (uint i = 0;i<cycles ;++i ) {
                    showAllString(mess.mid(i*mlinenumsize,mlinenumsize));
                }
                mess = mess.mid(cycles*mlinenumsize,mess.size()-cycles*mlinenumsize);
            }
        }
        mtextedit->append(mess);
        ui->tb_linenum->append(QString::number(cyclesnum++));
}

用了一个递归,感觉不是太好。


三、需要优化的地方

1、因为保存的都是为QString,实际过程可能char用的多,这个需要转换,同时显示HEx也需要转换;
2、行号其实是有上限,这个上限就是最大容量除以每一行最大字节数,但是没有设置;
3、需要需要优化的部分翻页功能应该让右侧滑动条到最上或者最下自动去加载数据,可能体验更好;

总结

在实现功能之前,自己试验了好几种方法,包括多线程,后来发现时频繁的加载大数据界面才会卡死,UI交互部分在主线程操作,所以保证数据量在可视的范围就好,无需一次加载太多数据。

QT是个好的ide,目前已经6版本,支持更高级的C++和更好的特性,在应用方面还需要自己更具实际需要好好的揣摩。

有关QT自定义QTextEdit实现大数据的实时刷新显示的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  9. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  10. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

随机推荐