Git Product home page Git Product logo

Comments (18)

pezy avatar pezy commented on June 6, 2024

首先的思路应该是搭出一个这个坐标轴能够运用的框架(平台),最直接的办法就是先把问题中的这个截图实现了。这个窗口应该是一个 widget ,其次,想要在 widget 中画图, 必然要自定义 widget ,并且重写 paintEvent() 函数,我们的自定义画图就在该函数里面进行。以上应该是最基本的思路,这一部分知识可以参考《C++ GUI Qt4编程》85页的内容。

然后我们可能会思考,如何把握坐标轴上的尺度?一个格子应该多大?怎么才能显示不疏不密,正正好好呢?很重要的一点在于我们需要知道标尺下面的字一般多大,横轴要看宽度,纵轴要看长度。问题得到了第一步分解,如何计算字体长度 #2

from qtlab.

pezy avatar pezy commented on June 6, 2024

第二步就应该是做出一个静态的坐标轴示意,来给我们一个总体的感觉,也就是粗略的搭建起一个Demo。

于是我们写了这些代码

示意图如下:
qq 20140929191451

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

如果没理解错的话。。我能想到的是这样的:
1、加入响应鼠标滚轮的signal
2、加入对应此signalslot
3、把必要的部分从void Widget::paintEvent(QPaintEvent *event)考出来,建立一个新函数比如dynamic_draw()
实现实时绘图。

至于画得不会过于稀疏,不会过于稠密,能想到的有两个办法:
其一:
1、把要用到的实时绘图数据打包成一个类,比如叫DrawData
2、提前演算好所有需要的数值,存入DrawData的对象,再把这些对象塞进容器比如std::vectorqvector
3、dynamic_draw()修改为dynamic_draw(int pos)pos代表鼠标滚轮的当前位置。
4、dynamic_draw()里面定义这个容器,比如:
std::vector<DrawData> vec = init()
init()函数返回一个装好已静态编译的实时绘图数值的容器。
5、dynamic_draw(int pos)里根据signal传来的实时pos值 ,取出数据vec[pos]。用这个数据进行实时绘图。由于这个数据是静态编译好的,肯定能做到的不会过于稀疏,不会过于稠密。估计要反复做实验,反复调才能把数据调好。

优点:实时性好,实现难度低。
缺点:空间开销大,要做不少实验。。

其二:
大思路和上面一样,就是把静态编译的数据换成实时计算。找到pos i和每个数据之间的数学函数关系,实时计算。

优点是:实验量小,空间开销小。
缺点是:实现难度大。可能需要一定的复杂度分析,有一定的制造瓶颈的风险。

我都是纸上谈兵。。感冒很难受,睡觉了。。

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

上述思路有个边界条件可以优化。
鼠标的最高响应频率可以做到1000hz。逻辑上,上述思路会导致1ms就重新绘图一次。
客户端没必要这么高频,10ms以下人眼基本分辨不出来,无为的增加系统负担。可以搞个计时器,把pos值的采集频率降低到100-200hz,实时性应该会更好一些。

哈哈,这个更纸上谈兵了,需要实验验证。

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

降频率这个思路可能要单开一个线程,专门计时用。

from qtlab.

pezy avatar pezy commented on June 6, 2024

dynamic_draw(int pos)里根据signal传来的实时pos值 ,取出数据vec[pos]。用这个数据进行实时绘图。由于这个数据是静态编译好的,肯定能做到的不会过于稀疏,不会过于稠密。估计要反复做实验,反复调才能把数据调好。

思路很好, 我将抽空试试你这个方案! 感冒多休息, 别太辛苦!

抽空调整了一下界面,力求与目标相仿:(代码)

qq 20141008095111

from qtlab.

pezy avatar pezy commented on June 6, 2024

dynamic_draw()修改为dynamic_draw(int pos),pos代表鼠标滚轮的当前位置。

在添加了滚轮事件(wheelEvent)之后,又有一个问题困扰我们, 即如何获取鼠标滚轮当前的位置,滚轮滚一个角度,我们如何获取,与刻度缩放的比例如何把握?我们很快找到QWheelEvent:delta这个方法。
参见:#4 ,其中numSteps就是@Mooophy 所说的参数pos .

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

看了下#4。。。
我当时就头脑风暴,信口诌一下。。没想到还和QWheelEvent::delta ()挺接近的。。

from qtlab.

pezy avatar pezy commented on June 6, 2024

我当时就头脑风暴,信口诌一下。。

你是天才!

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

。。

from qtlab.

pezy avatar pezy commented on June 6, 2024

模仿QChart的API, 简略的改造了目前的结构, 并补充了直方图颜色的提示. 17c4098

效果如下:
qq 20141009003544

简要叙述下目前的思路:

  1. QChart 是商业作品,我们看不到实现,但可以看到API/ABI。这正好给了我这样的新手一个机会,那就是动手实现这些接口。(当然这道题还是为了解决坐标轴缩放的问题,那是难点,我的这部分工作都是铺路。)我们没有必要面面俱到,既然给了Example,就要从这段代码中透露出的接口入手。
  2. @Mooophy 的思路相同,数据提供者应该作为一个类,也就是这里的 QBarSet,它应该包含数据集的名称示意颜色数据,由于这里的数据应该是无序且应被高效查找的,所以我采用了QList,从官网例子来看,<<赋值的方式,也像是QList而非QVector。 在此数据结构之上,还应该有一个集合来容纳这些数据,也就是这里的 QBarSeries,这个用简单的数组即可,从官网例子看,采用append而非<<赋值,也说明用的是QVector而非QList。由于在这里 QBarSeries并没有太多别的属性, 我连继承都懒得用了,直接用的typedef。
  3. 为了和真正的QChart 搞点小区别,在外观上将原有漂亮的网格去掉。仅保留坐标刻度。

接下来的困难:

现在数据有了,但数据表示的值与实际绘制的直方长度还存在一个对应关系,我们需要计算并管理这个关系,以供滚轮事件捕获的长度做后续的对应。

from qtlab.

pezy avatar pezy commented on June 6, 2024

把必要的部分从void Widget::paintEvent(QPaintEvent *event)考出来

这部分工作本以为很容易,没想到竟然还挺麻烦,也许是我脑子太笨了。将结构分离开竟然花了不少时间。

我将坐标轴单独抽了出来,作为一个 QSelfAdjustingAxis 类,这样就方便了之后更加灵活的处理缩放计算。这个类还提供了从数据值屏幕长度的转换。valueToTick

借助这个类的方法,我们轻松的将直方图绘制出来:

qq 20141009205738

这部分代码请见 437317a

真的就差最后一步了呢,心有点颤。

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

干嘛老说自己笨啊。。赞下心颤!

from qtlab.

pezy avatar pezy commented on June 6, 2024

不会过于稀疏

怎么界定?我觉得目前 Y 轴有5个刻度,已经是极限,再稀一点就很难看了。

不会过于稠密

怎么界定?我觉得起码的要求间距不能小于一个刻度的高度,否则相邻的刻度就重叠在一起了。

那么,我们得出两个结论,或者说两个变量:

  1. _deltaYMin记录最小间隔,等于字体的高度( #2 )。
  2. _defaultFactor记录默认分割因子,等于4 (分成4份,即5个刻度)

好了,基于上述两点,我们基本可以写出 adjustautoCalculateYTick方法的大致结构了。还有什么要注意的地方?

可以无限缩小吗?

默认状态下,最高刻度对应着数据中的最大值,那么在这个状态下缩小,直方图显然会超出最大刻度,跑到图的外面去。我们应该避免这种情况。所以又要引入一个变量:_actualMax来记录数据实际的最大值。无论如何缩小,都不能让直方图冲出这个最大值。

OK,最终的实现,比我想象的简单,还没有昨天重整结构麻烦。效果图如下 (代码):

result

😄 这个问题终于有了一个合理的解答。

from qtlab.

Mooophy avatar Mooophy commented on June 6, 2024

Working now?
👍
I'm gonna try it later~

from qtlab.

VeaLang avatar VeaLang commented on June 6, 2024

很有毅力和探索性,加油。

from qtlab.

pezy avatar pezy commented on June 6, 2024

I'm gonna try it later

Thanks, looking forward to receiving your comments or ideas about this code. 😃

from qtlab.

pezy avatar pezy commented on June 6, 2024

很有毅力和探索性,加油。

谢谢,一起学Qt,共同进步。

from qtlab.

Related Issues (12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.