748 views
首页 > 技术心得 > 用 VS 2010 玩转 QT

用 VS 2010 玩转 QT

2011年4月27日

工作所需, 用 QT 作为开发环境, 入入门, 简单的介绍一些玩法.

1. 下载 QT 源代码包, 到其官方网站 http://qt.nokia.com/downloads 去找, 目前的版本是 4.7.2, Windows 版本的下载地址是
【Qt libraries 4.7.2 for Windows (VS 2008, 218 MB)】
源代码包的下载地址是
http://get.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.2.zip

2. 将下载下来的源码包解开, 放到一个目录内, 我的是 E:\works\qt-everywhere-opensource-src-4.7.2

3. 编译 QT 源码库, 跟着 http://doc.qt.nokia.com/4.7/install-win.html 页面的导引, 开始编译; 下面是个简介.

(1). 将环境变量 QTDIR 加入系统, 值为 E:\works\qt-everywhere-opensource-src-4.7.2

(2). 将 Path 环境变量追加一个(如果 path 环境变量不存在, 则创建之), 从如

…\WindowsPowerShell\v1.0\

改成如

…\WindowsPowerShell\v1.0\;%QTDIR%\bin;%QTDIR%\lib

注意要加一个分号, 追加的信息和原有信息之间不能有空格.

(3). 运行 VS2010 的命令行 (开始 -> 所有程序 -> Microsoft Visual Studio 2010 -> Visual Studio Tools -> Visual Studio 命令提示(2010) );
在这个 DOS 窗口内运行如下命令

e:
cd E:\works\qt-everywhere-opensource-src-4.7.2
configure -opensource
nmake

对于 configure 命令, 如果带上参数 -static 将会编译出静态版本的 QT 库(但这里还是带有 VC 运行时, 如果要想彻底不带运行时, 必须手工修改 %QTDIR%\mkspecs\win32-msvc2010\qmake.conf 文件, 将 QMAKE_CFLAGS_RELEASEQMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO 标记的 -MD 值改成 -MT, 将 QMAKE_CFLAGS_DEBUG 标记的 -MDd 改成 -MTd ), 但这里没有带, 所以将是 DLL 版本的;

此外, configure 命令执行过程中, 会有一个询问, “Do you accept the terms of the license?”, 当然我们要回答 Y(es) 了, 否则啥也别搞.

最后, nmake 命令的执行要经过漫长的等待, 我这里是大概 4 个小时, 终于编译出了 VS 2010 的 QT 二进制文件, 包括 debug 版本和 release 版本, 均位于 %QTDIR%\lib 文件夹.

这里啰嗦一句, 如果你想重新完全生成编译配置, 先使用命令 nmake distclean 来清除配置, 然后再运行 configure 和 nmake 命令, 这里的 configure 命令可以更精细一些, 如 configure -opensource -platform win32-msvc 等等参数带着.

4. 将 VS 2010 用到的各种 include, lib, bin 路径告诉给 VS 2010, 包括:
(1).包含文件路径:

$(QTDIR)\include

(2).库文件路径:

$(QTDIR)\lib

(3).可执行文件路径:

$(QTDIR)\lib
$(QTDIR)\bin

具体怎么设就不废话了, 看图更直观.




5. 编写验证代码了.
(1) 创建一个新的 win32 的空的工程. 一路图解.


(2) 将以下内容的三个文件 finddlg.h, finddlg.cpp, main.cpp 加入工程.
finddlg.h

#ifndef __FIND_DLG_H__
#define __FIND_DLG_H__	1

#include <QtGui/QDialog>

class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;

class FindDialog : public QDialog
{
	Q_OBJECT

public:
	FindDialog(QWidget * parent = NULL);

signals:
	void findNext(const QString & str, Qt::CaseSensitivity cs);
	void findPrevious(const QString & str, Qt::CaseSensitivity cs);

private slots:
	void findClicked();
	void enableFindButton(const QString & text);

private:
	QLabel * label;
	QLineEdit * lineEdit;
	QCheckBox * caseCheckBox;
	QCheckBox * backwardCheckBox;
	QPushButton * findButton;
	QPushButton * closeButton;

};

#endif	// __FIND_DLG_H__

finddlg.cpp

#include <QtGui/QtGui>

#include "finddlg.h"

FindDialog::FindDialog(QWidget * parent)
	: QDialog(parent)
{
	label = new QLabel(tr("Find &case"));
	lineEdit = new QLineEdit;
	label->setBuddy(lineEdit);

	// 以下的 new 操作符不会导致内存泄露, 原因可以看第六节的 QT 源代码片段.
	caseCheckBox = new QCheckBox(tr("Match &case"));
	backwardCheckBox = new QCheckBox(tr("Search &backward"));

	findButton = new QPushButton(tr("&Find"));
	findButton->setDefault(true);
	findButton->setEnabled(false);

	closeButton = new QPushButton(tr("Close"));

	connect(lineEdit, SIGNAL(textChanged(const QString &)),
		this, SLOT(enableFindButton(const QString &)));
	connect(findButton, SIGNAL(clicked()),
		this, SLOT(findClicked()));
	connect(closeButton, SIGNAL(clicked()),
		this, SLOT(close()));

	QHBoxLayout * topLeftLayout = new QHBoxLayout;
	topLeftLayout->addWidget(label);
	topLeftLayout->addWidget(lineEdit);

	QVBoxLayout * leftLayout = new QVBoxLayout;
	leftLayout->addLayout(topLeftLayout);
	leftLayout->addWidget(caseCheckBox);
	leftLayout->addWidget(backwardCheckBox);

	QVBoxLayout * rightLayout = new QVBoxLayout;
	rightLayout->addWidget(findButton);
	rightLayout->addWidget(closeButton);
	rightLayout->addStretch();

	QHBoxLayout * mainLayout = new QHBoxLayout;
	mainLayout->addLayout(leftLayout);
	mainLayout->addLayout(rightLayout);
	setLayout(mainLayout);

	setWindowTitle(tr("Find"));
	setFixedHeight(sizeHint().height());
}

void FindDialog::findClicked()
{
	QString text = lineEdit->text();
	Qt::CaseSensitivity cs = caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
	if (backwardCheckBox->isChecked()) {
		emit findPrevious(text, cs);
	} else {
		emit findNext(text, cs);
	}
}

void FindDialog::enableFindButton(const QString & text)
{
	findButton->setEnabled(!text.isEmpty());
}

main.cpp

#include <QtGui/QApplication>
#include "finddlg.h"
int main(int argc, char * argv[])
{
	QApplication app(argc, argv);
        // 这里会导致内存泄露, 改成栈变量.
	//FindDialog * dialog = new FindDialog;
	//dialog->show();
        FindDialog dialog;
        dialog.show();
	return app.exec();
}

(3) 将 finddlg.h 文件的属性改成 “自定义生成工具”, 并加入命令行

moc.exe finddlg.h -o moc_finddlg.cpp

将命令的输出填入 moc_finddlg.cpp. 然后编译 finddlg.h 文件, 这将生成 moc_finddlg.cpp 文件, 将 moc_finddlg.cpp 文件加入工程.
一路继续看图解.




(4) 最后, 将 QT 系统的库文件加入链接选项中.

QtCored4.lib
QtGuid4.lib
qtmaind.lib

注意, 这是 debug 版本的库文件, release 版的库文件是 QtCore4.lib;QtGui4.lib;qtmain.lib;

(5) 编译, 运行, 即可得到我们想要的结果, 一个对话框.

6. 解说

void QObjectPrivate::deleteChildren()
{
    const bool reallyWasDeleted = wasDeleted;
    wasDeleted = true;
    // delete children objects
    // don't use qDeleteAll as the destructor of the child might
    // delete siblings
    for (int i = 0; i < children.count(); ++i) {
        currentChildBeingDeleted = children.at(i);
        children[i] = 0;
        delete currentChildBeingDeleted;
    }
    children.clear();
    currentChildBeingDeleted = 0;
    wasDeleted = reallyWasDeleted;
}

用户界面编译命令: uic gotocelldlg.ui -o ui_gotocelldlg.h

例子代码1 ch02-01.zip
例子代码2 gotocell.zip
例子代码3 qtjustgo.zip
多线程例子 qt-multi-thrd.zip qt-thread-01.zip multi-thrd

延伸阅读:
设计 Qt 风格的 C++ API
《QT 学习之路》系列文章
Qt 源码分析之信号和槽机制
从 C++ 到 Qt
用ISO C++实现自己的信号槽(Qt另类学习)
Qt 3.x 参考文档(中文版)
Qt简介以及如何配置Qt使用VS2010进行开发
Static Qt with static CRT (VS 2008)
HeapValidate does not work and C/C++运行期堆栈 and crt-dll.zip and _memory.h
Visual Studio 2010 编译Qt 4.6.3
使用 VS2010 编译 QOAuth 支持微博通用认证 OAuth 实现 SINA 微博登录
Qt 和 Visual Studio 2010 集成使用
风雷云雪电的博客
Android 平台 Qt 开发入门教程
Visual Studio Add-in and Qt Visual Studio Add-in source code
C++ GUI Programming with Qt 4 source code (zip)
QT5 source code

技术心得 ,

  1. 目前还没有任何评论.
  1. 目前还没有任何 trackbacks 和 pingbacks.