matplot 多个图片在多个窗口显示

需求 使用 matplot 时,当需要多于 10 个的图表显示,使用单窗口多子图的模式,会太小了,看不清楚。所以需要使用多窗口模式,每个窗口只显示有限的子图即可。 解决 其实很简单,只要保证只有一个 show 即可,把所有的窗口全部设置好之后,在最后使用 show, 就可以多个窗口都显示出来了。 for i in range(0, channel_num): fig = plt.figure(num = i, figsize = (4, 4)) ax1 = fig.add_subplot(311) ax1.plot(lists[i][0]) ax2 = fig.add_subplot(312) ax2.plot(lists[i][1]) ax3 = fig.add_subplot(313) ax3.plot(lists[i][2]) #plt.show() plt.show() 参考 Python 多个图同时在不同窗口显示

<span title='2023-03-21 15:54:00 +0800 CST'>2023-03-21</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;43 words&nbsp;·&nbsp;RamLife

多维列表添加值时,多个位置被同时修改的错误

需求 今天使用 python 编写一个数据处理的脚本时,结果怎么都不对。经过反复调试,问题出现在使用 append 给多维列表添加值的时候,我需要的是只在指定的列表里面添加,结果多维列表的内部多个列表同时被添加值了。 解决 原因 这个错误有点莫名其妙,一开始我以为是我写错了,导致类似于 numpy 里面那样,对多维数组操作时,对高维操作时,会有多个地方被修改。 但是在自己检查之后发现,并不是这种情况。后来经过反复的调试和搜索后,终于确定原因所在。 原因其实还是在新建多维列表的地方,如下是我开始时候的写法: c1 = [] c2 = [] t = [] for i in range(0, 12): l = [c1, c2, t] out_data.append(l) 上面的写法看起来却是是新建了 12 * 3 的多维列表,但是隐藏的问题是,这样添加,其实添加的是 c1, c2, t 的引用,所以导致只要有一个变化了,其他的都会跟着变。 解决 只要修改创建多维列表的方法就可以了,比如这样: out_data = [ [ [] for j in range(3) ] for i in range(channel_num) ] 参考 Python 创建多维空列表 python初始化二维列表:{}.append({}) 与 {{}} * n python 二维列表(数组)赋值问题 python二维列表List修改其中一个数值,所有项数值都改变的问题。

<span title='2023-03-21 14:14:00 +0800 CST'>2023-03-21</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;70 words&nbsp;·&nbsp;RamLife

QT Text 相关 widget 追加文本不换行

需求 正常在 QTextEdit QTextBrowser 中使用 append 添加新内容,都是自动换行的,如果不希望自动换行怎么办? 解决 其实很简单,使用 insertPlainText 这个方法即可。 textBrowser->insertPlainText("hello "); textBrowser->insertPlainText("world"); insertPlainText接口是在当前光标插入文本(光标一般默认在末尾),不自动换行,所以会打印: hello world 参考 QTextEdit QTextBrowser追加文本不换行

<span title='2023-03-10 16:00:00 +0800 CST'>2023-03-10</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;20 words&nbsp;·&nbsp;RamLife

命令行调试串口

需求 在编程使用串口之前,希望先确定串口硬件和系统层面是否正常。 解决 可以使用 stty 来调试串口功能。 查询当前串口配置 sudo stty -aF /dev/ttyS0 上面这个命令可以打印出当前串口的所有配置,有些配置选项前面有 -, 这个表示关闭此选项,或者额外意义,具体可以参考手册 man stty. 需要注意这几个配置: speed, -parenb, cs8, -cstopb, -ixon, -ixoff, -echo. 表示: 波特率,关闭校验,8位,1位停止,无流控,无回显. 保存,读取当前配置 在进行串口配置之前,应该先保存现在配置,便于以后的恢复。 # 保存 sudo stty -gF /dev/ttyS0 > save_stty # 读取 sudo stty -F /dev/ttyS0 $(cat save_stty) 脚本中可以这样写: save_stty="$(stty -g)" ... stty $save_stty 配置串口 sudo stty -F /dev/ttyS0 speed 115200 cs8 -parenb -cstopb -ixon -echo 上面这条命令立即生效,即使已经使用 cat 读取串口数据。 读取数据 sudo cat /dev/ttyS0 *注意: *...

<span title='2023-03-09 11:55:00 +0800 CST'>2023-03-09</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;106 words&nbsp;·&nbsp;RamLife

使用智能指针替代裸指针

需求 希望使用智能指针,能够尽量减少内存泄漏 解决 智能指针比较适合在局部变量领域,在生命周期结束时,会自动释放。 定义 std::unique_ptr<QSerialPort> port_ = nullptr; std::unique_ptr<int[]> buf_ = nullptr; std::shared_ptr<int> data_ = nullptr; std::weak_ptr<int> weak_ = nullptr; 赋值 port_ = make_unique<QSerialPort>(); // 未初始化 buf_ = make_unique<int[]>(new int[10]); // 初始化为 0 buf_ = make_unique<int[]>(new int[10]()); buf_ = make_unique<int[]>(new int[10]{}); // shared data_ = make_shared<int>(); // weak 必须绑定 shared weak_ = data_; 使用 -> 这个是调用指针指向的对象的相关操作 . 这个是智能指针自身的一些操作 直接使用 shared_ptr 指针有可能会产生循环引用的问题,导致死锁,无法释放。建议使用 weak_ptr 来配合 shared_ptr. 注意 weak_ptr 无法单独存在并使用。 weak_ptr 在使用的时候,需要通过 lock 来获取 shared_ptr 对象,如果相应的内存已经释放,那么会返回 nullptr, 可以通过这个判断内存是否有效。 weak_ptr 本身不会增加 shared_ptr 的引用次数。 释放 释放有好几种方法,最简单的就是第一种。...

<span title='2023-03-06 17:03:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;119 words&nbsp;·&nbsp;RamLife

调试信息宏 FILE LINE FUNCTION

需求 调试时,希望打印信息能够包含文件名,行号,函数名等 解决 编译器有提供相应的宏,可以如下使用,注意,行号是数值。 printf("error in %s %d %s\n", __FILE__, __LINE__, __FUNCTION__); 除了这些以外,还有其他的一些可用的宏,比如说: __DATE__ : 当前系统日期 Apr 19 2019 __TIME__ : 当前系统时间 例如 15:39:58 __TIMESTAMP__ : 当前时间日期 例如: printf(_TIMESTAMP_); 打印结果 Fri Apr 19 16:24:31 2019 参考 C/C++中的_FUNCTION_,__FILE__和__LINE__ 系统常用宏定义__TIME__ DATE __LINE__等 C/C++ 宏定义 FILE__、_LINE_、_func_、__TIME 等

<span title='2023-03-06 16:32:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;44 words&nbsp;·&nbsp;RamLife

连接字符串的宏

需求 需要宏来生成字符串,降低人工输入和防止出错 解决 可以使用 #, 让相应的参数作为字符串进行填充。 #define OUT(s) fprintf(stderr, "out: " #s "/n"); OUT(div == 0); // fprintf(stderr, "out: " "div == 0" "/n"); ## 可以用来连接多个参数,减少代码生成。用法简单: #define NAME(n) name##n int NAME(a); NAME(a) = 123; printf("%d\n", NAME(a)); 参考 C语言中如何使用宏连接多个字符串(#和##的用法) C++ 宏字符串拼接、宏参数拼接成符号、宏嵌套、宏变长参数 C语言宏定义##连接符和#符的使用

<span title='2023-03-06 16:26:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;41 words&nbsp;·&nbsp;RamLife

QT 警告: QObject: Cannot create children for a parent that is in a different thread

需求 在运行 qt 程序时,出了相应的警告: QObject: Cannot create children for a parent that is in a different thread. (Parent is QThread(0xb95feffd70), parent's thread is QThread(0x1d3729aef20), current thread is QThread(0xb95feffd70) 解决 这个其实就是在子线程中,使用了主线程的对象,并创建子对象,所以出的警告。解决的方法也有几种: 子线程创建子对象 简单说,就是在子线程中先获取主线程的相应参数,然后创建出需要的对象,这样的话,在需要创建子对象的时候,也是在同一个线程。这种方法最简单,就是代码上可能啰嗦一点。 不指定父对象 对象创建时,不指定父对象,也就是不使用 this 来指定,留空即可。如果碰到一些调用的库函数内部创建对象,这种方法就不好使了。 使用 moveToThread 绑定相应的线程 调用 QObject 的成员函数 moveToThread, 绑定到对应的线程上去。下面是几个例子: ThreadTest2 thread2; thread2.moveToThread(&thread2); thread2.start(); 上面这个例子,thread2 把自己从主线程绑定到子线程,这样在 ThreadTest2 这个类内部创建的对象也就转移到子线程上去了。 class Controller : public QObject { Q_OBJECT ... private: QThread thread; }; Controller::Controller(QObject* parent) : QObject(parent) { Worker *worker = new Worker(); worker->moveToThread(&thread); ....

<span title='2023-03-06 16:00:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;105 words&nbsp;·&nbsp;RamLife

[转] C++ 或 QT 判断当前模式是Debug还是Release模式

需求 在构建版本的时候,需要在 debug 和 release 版本中有不一样的地方,这时候就需要使用宏来自动识别并展开对应的语句。 解决 C++ #ifdef DEBUG cout << "Debug!" << endl; #else cout << "Release!" << endl; #endif Qt #ifdef QT_DEBUG cout << "Debug!" << endl; #else cout << "Release!" << endl; #endif 参考 C++ 或 QT 判断当前模式是Debug还是Release模式

<span title='2023-03-06 15:13:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;42 words&nbsp;·&nbsp;RamLife

QMutex 和 QWaitCondition 配合用于多线程

需求 多线程同步时,需要线程能够被外部唤醒,从而按照一定的顺序来执行。 解决 同步可以使用 QWaitCondition 先让线程睡眠,然后在必要的时候从外面唤醒 线程即可。但是 QWaitCondition 所在的线程必须先使用 QMutex 上锁才行, QWaitCondition 会先阻塞线程,然后把锁释放,再等待唤醒,唤醒可以对 QWaitCondition 的对象使用 wakeAll() 或者 wakeOne() , 唤醒后,锁会自动回来,所以别忘了最后的解锁. QMutex 除了直接的 lock, 还可以使用 QMutexLocker 自动上锁,并在生命周期结束后自动解锁。 m_mutex.lock(); m_cond.wait(&m_mutex); ... m_mutex.unlock(); const QMutexLocker locker(&m_mutex); ... m_cond.wakeOne(); 参考 Qt互斥锁(QMutex)、条件变量(QWaitCondition)理解+QMutex实现多线程循环输出ABC(含源码+注释) QT线程QMutex和 QWaitCondition 结合使用的例子

<span title='2023-02-27 19:13:00 +0800 CST'>2023-02-27</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;40 words&nbsp;·&nbsp;RamLife