Feb 20, 2015 - Qt5 With Log4qt

layout: post title: “Qt5 中使用 log4qt 输出日志” description: “” category: project tags: [C++, QT] —

最近在写一个 QT 的程序,需要打印日志。搜索了一下,选定了 Log4Qt。不过,原项目已经长期不更新了,而 DevBean 维护了一个 Qt5 的版本。所以,我执行了 git submodule add https://github.com/devbean/log4qt.git 而在此同时,另一个团队也在孜孜不倦地 维护着 Log4qt。感兴趣的朋友不妨也测试一下。

官方提供了一个比较详细的使用介绍,但也隐藏了几个小坑,整理如下:

Step 1

将这句话加入 .pro 文件即可 include(<unpackdir>/src/log4qt/log4qt.pri)

Step 2

在预编译头文件里加入

#include "log4qt/consoleappender.h"
#include "log4qt/logger.h"
//我添加的内容
#include "log4qt/logmanager.h"
#include "log4qt/patternlayout.h"
//被我移除的头文件
//#include "log4qt/ttcclayout.h"

Step 3

初始化 Log4Qt,我是在 QApplication::exec() 之前执行的这段代码 为了能灵活地处理 Layout,我小幅修改了原有的代码。

//Configure a logger to generate output. The example uses the root logger
//Create a layout
Log4Qt::LogManager::rootLogger();

//TTCCLayout *p_layout = new TTCCLayout();
//使用 PatternLayout,自定义输出格式
p_layout = new Log4Qt::PatternLayout("%-5p [%c] %m%n");
p_layout->setName(QLatin1String("My Layout"));
p_layout->activateOptions();

// Create an appender
ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET);
p_appender->setName(QLatin1String("My Appender"));
p_appender->activateOptions();
// Set appender on root logger
Log4Qt::Logger::rootLogger()->setAppender(p_appender);

关于 Layout 的详细内容,可以参考 Log4j 的一篇文档,使用方法与 C 的格式化字符串是一样的。

Step 4

然后,就可以直接输出 log 了,例如官方示例
Log4Qt::Logger::logger(QLatin1String("My Logger"))->info("Hello World!");

为了简化代码,我在预编译头文件里又加入了这段内容

#define INITIATE_LOG4QT(ClassName) LOG4QT_DECLARE_STATIC_LOGGER(LOG4QT_LOGGER, ClassName)

#define ERROR(s) LOG4QT_LOGGER()->error(QString(s))
#define WARN(s) LOG4QT_LOGGER()->warn(QString(s))
#define INFO(s) LOG4QT_LOGGER()->info(QString(s))

而在定义类的头文件里,只要初始化一下

class MyClass
{
private:
    INITIATE_LOG4QT(MyClass);

public:
    MyClass();
    ~MyClass();
};

就可以直接在类的成员函数里用 ERROR() 这样的宏了。

Step 5

Log4Qt 的功能非常强大。例如,四个 Level 用于输出不同的信息,可以在启动时动态确定输出哪些信息。同样,也可以使用条件编译,在 Release 里将 INFO 编译成 (void)0 来减少性能损失。不过,Log4Qt 的性能没有测试,希望了解的朋友贴出自己的经验 :-)

Last

从我学 Qt 的第一天起就没少看 DevBeans 的博客,也在这里推荐一下他的书籍 《Qt 5编程入门》

Feb 7, 2014 - 如何教人编程

这学期头脑发热,辅导了两个人编程(第一个 Python,第二个 C++),真的是很难忘的经历。
学习编程是一件有挑战的事情。相比之下,教一个人编程更加困难。第一个障碍,就是思维方式的改变(针对大学生而言)。

有了高中的经历,学习者很希望能得到一个 “知识体系”,一个树状的知识结构图,就像这样 biology
(原链接 http://zxshw.jyjy.net.cn/Article/UploadFiles/200511/20051102160138116.gif)

问题是,编程并不是要回答原有的问题。我喜欢将编程比作乐高积木:给定若干规则,你要按照你的想法想起组合在一起。来 搭建 你所需要的东西。如果不能让他们掌握新的思维方式,那你就可以打 GG 然后 Alt + Q 了。

回头想想,有几点建议,还是留给自己吧:

指出错误要直接

我并不时说我们要像 Linus Torvalds 那样 “直白”,但对于学习者的错误,要果断的指出。如果发现对概念有错误的理解,一定要第一时间指出。如果因为他们看上去很努力,就给了不客观的鼓励,那会是非常不负责任的行为。

####避免使用自然语言 need description

大家应该很熟悉这幅漫画吧。一个团队内的成员,尚且会相互误解,更何况在一个半斤八两的教授者,和一个一片空白的学习者间呢?
相比于含糊的自然语言,流程图是一种更可靠的交流方式。而且,还能帮助他们形成正确的思路。

####不要相信“我听懂了” 很多时候,“懂了”的意思,是“我知道了”(参见图一)。学习者经验少,不自觉地自欺欺人,如果你也被忽悠了,那结果将会是悲惨的。

####不要在练习上吝啬时间 《我编程,我快乐》 一书中,作者将编程与音乐做了类比。虽然两者间的区别很大(比方说没有维也纳新年编程会),但个人愚见,有一点是共同的:需要大量的练习。贸然跳过一些自认为“简单”的练习,很可能埋下某些“定时炸弹”。今天坑挖的越深,明天掉进去的时候摔的就会越痛。

不要轻易挖坑

但趁着年轻,多做一些有挑战性的事情吧

Jan 30, 2014 - CentOS 使用 ELRepo 安装最新的 Linux Kernel

回家给台式机装上了 CentOS 6.5,发现很多软件包都太旧,尤其是 kernel,还停留在 2.6 的时代。找了一些介绍,多数说要自己编译 kernel,实在太麻烦。不过,有一篇文章介绍了用 ELRepo 安装新内核的方法,我只想说:

太伟大了!

具体的步骤很简单:

  1. 添加源
    rpm -Uvh http://www.elrepo.org/elrepo-release-6-5.el6.elrepo.noarch.rpm
  2. 安装kernel
    yum --enablerepo=elrepo-kernel install kernel-ml
    (解释一下,ml 是指 MainLine, kernel-lt 就是 Long-Term)
  3. 编辑 grub 的默认启动项
    这里我就懒了,直接 编辑的 /boot/grub/menu.lst,好孩子们不要学我啊