天天看点

qt学习四部曲(Console;QByteArray;模态对话框;多线程及事件通信 )

如何在Console中使用cin、cout、cerr;

QByteArray显示中文;

模态对话框和非模态对话框;

多线程及通过事件进行通信

Qt学习系列之一:如何在Console中使用cin、cout、cerr

首先需要包含下列头文件:

     #include <QTextStream>

#include <stdio.h>

然后,在使用cin、cout、cerr之前,创建下列变量:

QTextStream cin(stdin, QIODevice::ReadOnly);

QTextStream cout(stdout, QIODevice::WriteOnly);

QTextStream cerr(stderr, QIODevice::WriteOnly);

其中,QTextStream是个非常好用的字符串处理类,它能够使得字符串或者是基于字符的设备、文件处理变得非常方便。

然后,就可以像正常的C++那样,在QString的环境下使用cin、cout、cerr这些类了。需要注意的一点是,这样的cin、cout、cerr和我们在传统C++遇到的有一点不同,那就是你cout了一个QString之后,默认是不直接输出的,一般需要等到cout的缓冲区满之后,才向终端输出内部的字符串;如果你想在cout之后马上看到输出的内容,可以在输出之后在输出一个endl,或者调用cout的内部方法flush,强制情况缓冲区,例如:

QString str;

str = "Hello world!";

cout<<str;

cout.flush();

cin>>str;

cout<<str<<endl;

Qt学习系列之二:QByteArray显示中文

首先有一个txt的文本文件,内部有中文,一般情况下这样的中文是以GBK标准编码的,除非你在存储的时候显式地存为Unicode。直接通过QFile,然后读取QByteArray,会发现在命令行里面显示出来的是乱码,那是因为Qt默认情况下会以ASCII编码来解释字符串的,这个时侯我们就需要对字符产编码进行转化,QTextCodec类可以很好的帮助我们完成这一任务。

首先包含头文件:

#include <QTextCodec>

然后,可以参考如下代码:

QString str;

QFile file("E:\\a.txt");

if (!file.open(QIODevice::ReadOnly))

{

cerr<<"Open error!"<<endl;

return 1;

}

QTextCodec *tc = QTextCodec::codecForName("GBK");

QByteArray ba = file.readAll();

str = tc->toUnicode(ba);

cout<<str<<endl;

这个时候,就能够正常显示中文了。

Qt学习系列之三:模态对话框和非模态对话框

模态对话框就是指在子对话框弹出时,焦点被强行集中于该子对话框,子对话框不关闭,用户将无法操作其他的窗口。非模态相反,用户仍然可以操作其他的窗口,包括该子对话框的父对话框。 如果从线程角度来讲,模态对话框实际上是线程阻塞的,也就是子对话框是一个线程,但是在创建这个子线程之后,父窗口就阻塞了;模态对话框则不是阻塞型的线程模型,父子线程可以并行运行。 和所有流行的图形类库一样,Qt也提供了创建模态和非模态对话框的机制。 在Qt中创建模态对话框,主要用到了QDialog的exec函数: SonDialog dlg(this); int res = dlg.exec(); if (res == QDialog::Accepted) { QMessageBox::information(this, "INFORMATION", "You clicked OK button!"); } if (res == QDialog::Rejected) { QMessageBox::information(this, "INFORMATION", "You clicked CANCEL button!"); } 正如上面代码所显示的,可以通过exec函数的返回值来判断用户点击了哪个按钮使得模态对话框退出的,这可以使得我们能够根据用户的不同行为在推出退出模态对话框之后采取不同的处理方法。 在Qt中创建非模态对话框,主要用到了QDialog的show函数: SonDialog *dlg; dlg = new SonDialog(this); dlg->show(); 由上面代码,细心的读者可能就会问了,既然new了,如果不delete,那么内存不就存在了泄露的问题了吗?确实如此!所以,我们希望该Qt窗口在退出时自动能够delete掉自己,因此,我们在SonDialog的构造函数里,添加这样的一句代码: setAttribute (Qt::WA_DeleteOnClose); 这样,我们的SonDialog就能够在它退出时自动的delete掉自己了,不会再造成内存泄漏问题。

Qt学习系列之四:多线程及通过事件进行通信

可以通过QThread实现跨平台的多线程开发,Qt库负责在特定平台上的特定多线程实现。要采用QThread进行多线程开发,首先需要包含头文件: #include <QThread> 然后需要从QThread继承一个自己的线程类,暂作MyThread,关键是要实现QThread内的一个虚函数run。在run函数内部,最后一般都调用exec(),使得线程进入事件循环,否则线程主函数run运行结束,线程也就退出了。 class MyThread : public QThread { public: MyThread(); public: Dialog *parent; public: void run(); }; 其中,parent存储的是创建该线程的窗口,也就是该线程的父线程,主要用于该子线程向父线程发送特定事件,以便进行线程间通信。

自定义消息首先需要包含头文件: #include <QEvent> 然后定义自己的事件值: const QEvent::Type MyEvent = (QEvent::Type)1234; 然后在run函数里面(实际上是指在任何你想要和父线程进行通信的地方,我这里简化为就是在run函数内部了)通过: QApplication::postEvent(parent, new QEvent(MyEvent)); 将该事件发送出去。 父线程内通过改写虚函数event,来使得能够捕获消息: bool Dialog::event(QEvent *event) { if (event->type() == MyEvent) { QMessageBox::information(this, "INFORMATION", "This is son sented signal!"); return true; } return QWidget::event(event); } 这样,两个线程就能够同时运行并能够进行线程间通信了。

继续阅读