Qt学习笔记_Chapter1_3窗口部件的布局
Windows7下的程序运行效果图:
这一节主要讲了两点:(1)如何用布局(Layout)来管理窗口中窗口部件的几何形状;(2)如何利用信号和槽来同步窗口部件。
这个应用程序用了三个窗口部件:一个QSpinBox(微调框)、一个QSlider(滑块)和一个QWidget。其中QWidget是这个应用程序的主窗口,也是QSpinBox和QSlider的父对象,QWidget自己没有父对象。QWidget的构造函数以及它的所有子类都会带一个参数QWidget*,以用来说明谁是它们的父窗口部件。
- #include <QApplication>
- #include <QHBoxLayout>
- #include <QSlider>
- #include <QSpinBox>
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- QWidget *windows=new QWidget;
- windows->setWindowTitle("Enter Your Age");
- QSpinBox *spinBox=new QSpinBox;
- QSlider *slider=new QSlider(Qt::Horizontal);
- spinBox->setRange(0,130);
- slider->setRange(0,130);
- QObject::connect(spinBox,SIGNAL(valueChanged(int)),
- slider,SLOT(setValue(int)));
- QObject::connect(slider,SIGNAL(valueChanged(int)),
- spinBox,SLOT(setValue(int)));
- spinBox->setValue(35);
- QHBoxLayout *layout=new QHBoxLayout;
- layout->addWidget(spinBox);
- layout->addWidget(slider);
- windows->setLayout(layout);
- windows->show();
- return app.exec();
- }
Line8,9:创建了Widget对象,使用setWindowTitle()函数来设置显示在窗口标题栏上的文字。
Line10,11:创建了一个QSpinBox和一个QSlider,并分别在第12行和第13行设置了它们的有效范围。本应将这个窗口传递给QSpinBox和QSlider的构造函数,以说明这两个窗口部件的父对象都是这个窗口,但在这里没有这个必要,因为布局系统将会自行得出这一结果并自动把该窗口设置为微调框和滑块的父对象。
Line14-17:调用了两次QObject::connect(),来确保能够让微调框和滑块同步,一旦有一个窗口部件的值发生了改变那么就会发射它的valueChanged(int)信号,而另一个窗口部件就会用这个新值调用它的setValue(int)值。
Line18:将微调框的值设置为35,此时QSpinBox会发射valueChanged(int)信号,其中,int参数的值为35,触发QSlider的setValue(int)槽,避免无限循环的发生,流程如下图所示:
Line19-22:使用了一个布局管理器对微调框和滑块进行布局处理。布局管理器(layout manager)是一个能够对其所负责窗口部件的尺寸大小的位置进行设置的对象。Qt有三个主要的布局管理器类:(1)QHBoxLayout:在水平方向上排列窗口部件,从左到右;(2)QVBoxLayout:在竖起方向上排列窗口部件,由上到下;(3)QGridLayout,把各个窗口部件排列在一个网格中。第22行的QWidget::setLayout()函数调用会在窗口上安装该布局管理器。QSpinBox和QSlider会自动“重定义父对象”,成为这个安装了布局的窗口部件的子对象。因此当创建一个需要放进某个布局中的窗口部件时,就没有必要为其显式的指定父对象了。
Qt学习笔记_Chapter1_2建立连接
Windows7下程序运行效果图:
还记得MFC中,消息循环系统是每一个初学者都要费不少心思学习的东西,Qt中采用了一种完全不同的方式:信号和槽。还是从代码开始:
- #include <QApplication>
- #include <QPushButton>
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- QPushButton *button=new QPushButton("Quit");
- QObject::connect(button,SIGNAL(clicked()),
- &app,SLOT(quit()));
- button->show();
- return app.exec();
- }
这里使用了QPushButton作为应用程序的主窗口部件。
Line7,8:Qt的窗口部件通过发射信号(signal)来表明一个用户动作已经发生了或者是一个状态已经改变了。例如,当用户单击QPushButton时,该按钮就会发射一个clicked()信号。信号可以与函数(在这里称为槽,slot)相连接,以便在发射信号时,槽可以得到自动执行。这里把按钮的clicked信号和QApplication对象的quit()槽连接起来。宏SIGNAL()和SLOT()是Qt语法中的一部分。
BTW:QObject这个类是QT对象模型的核心,绝大部分的QT类都是从这个类继承而来,这个模型的中心特征就是一个叫做信号和槽的机制来实现对象间的通讯。所有的widget都是QT object,因为它们继承自QWidget,而Qwidget正是继承自QObject
Qt学习笔记_Chapter1_1HelloQt
Windows7下程序运行效果图:
学习的每一步总是HelloWorld,Qt4.6直接推出了VS2008的Binary包,大大方便了我的学习,现在可以像写一般的MFC程序一样在VS集成环境中编写Qt程序了,Qt中的HelloWorld程序如下:
- #include <QApplication>
- #include <QLabel>
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- QLabel *label=new QLabel("<h2><i>Hello</i> "
- "<font color=red>Qt!</font></h2>");
- label->show();
- return app.exec();
- }
Line1,2:对于每个Qt类,都有一个与该类同名(且大写)的头文件,在这个头文件中包括了对该类的定义。
Line5:创建了一个Qapplication对象,用来管理整个应用程序所用到的资源。Qt支持它自己的一些命令行参数,所以这里同样有argc,argv作为参数。
Line6:创建了一个QLabel Widget,这里的Widget相当于VC中的控件,Qt十分灵活,任意窗口部件(Widget)都可以作为窗口,这里就使用了一个Qlabel作为窗口。另外可以看到,通过使用一些简单的HTML样式格式,可以轻松地把Qt应用程序的用户接口变得更为丰富多彩。
Line8:使QLabel可见,默认隐藏是为了便于我们先进行设置然后再显示它们,从而避免了窗口部件的闪烁现象。
Line9:将应用程序的控制权传递给Qt。此时,程序会进入事件循环状态,这是一种等待模式,程序会等候用户的动作,例如鼠标单击和按键等操作。
BTW:在这个程序中没有过多关注在main()函数末尾处对QLabel对象的delete操作调用。在如此短小的程序内,这样一点内存泄漏(memory leak)问题无关大局,因为在程序结束时,这部分内存是可以由操作系统重新回收的。
C++Primer学习笔记2_构造函数初始化式
正如Lippman所说,构造函数初始化列表是许多相当有经验的C++程序员都没有掌握的一个特性。虽然在学习MFC的时候,经常看到这种形式的初始化,但是总觉得格式不漂亮,也没有深究为什么Microsoft的程序员们喜欢这样做,直到今天。且看下面这两段代码:
- Sales_item(const std::string &book=""):isbn(book),units_sold(0),revenue(0.0){}
- Sales_item(const std::string &book="")
- {
- isbn=book;
- units_sold=0;
- revenue=0.0;
- }
第一段代码使用了初始化式,执行构造函数时,直接执行初始化,而第二段代码中,虽然没有显式的初始化式,但是在执行构造函数之前,要初始化isbn成员,由默认的string构造函数执行,在执行构造函数的函数体时,isbn成员已经有值了。这两个构造函数虽然执行结果相同,但是不使用初始化式等于在程序执行时多了一步。这种效率上的损失还不是最糟糕的,在以下情况下,甚至必须要使用初始化列表进行初始化:
1.成员是没有默认构造函数的类
2.成员是const对象
3.成员是引用类型的对象
要注意的另外一点是:成员初始化的次序并不是它们出现在初始化列表中的次序,而是定义成员的次序.
C++Primer学习笔记1_类作用域
这一章东西很杂,也很容易混淆。
一、类作用域包括以下内容
1、类定义体
2、在类外定义的成员函数的定义(不包括返回类型)
二、类作用域中的名字查找
1.类成员的声明中用到的名字
(1)检查出现在名字使用之前的类成员的声明。
(2)如果第1步查找不成功,则检查包含类定义的作用域中出现在类定义前的声明。
2.类定义体中的成员函数的函数体中用到的名字
(1)检查成员函数局部作用域中的声明。
(2)检查对所有类成员的声明。
(3)检查在此成员函数定义之前的作用域中出现的声明。
3.定义在外部的成员函数的函数体中用到的名字
在2的基础上,还会寻找在成员函数定义之前出现的全局作用域声明
VS2008环境下编译使用SGI STL(using stlport 5.2.1)
stlport据说是一位俄罗斯高人之作,目的就是为了让我们在多平台下可以使用高效的SGI STL,废话少说,先介绍下它的主页:
下面是下载地址,最新版本是5.2.1:
下载后解压,假设目录为:D:\STLport,接下来就该编译它了:
1.在开始菜单中找到VC 命令行工具,这样可以省去很多事(网上很多教程要做很多热身运动,为啥不让M$代行呢?接下来切换到D:\STLport目录。
2.可以运行configure –help看看编译选项,用MSVC编译器编译的话,输入以下命令:
configure msvc9
3.输入
cd build/lib
4.输入
nmake clean install
稍等几分钟就可以编译好
5.在VS2008 IDE中做收尾工作:
依次选择“工具”->“选项”,在“项目和解决方案”下选择“VC++ 目录”,把D:\STLport\bin目录添加到“可执行文件”,把D:\STLport\include目录添加到“包含文件”(注意要放在最前,这样就可以取代默认的MSVC自己的STL库了),再把D:\STLport\lib目录添加到库目录和引用文件就ok了。
Windows 下C++ 学习平台的选择
对于大多数人来说,计算机只是一个工具,作为一个工科大学生,我不是程序员,但也有很多用得着程序的地方,一个良好的平台,对学习无疑能起到极大的促进作用。
一、为什么选择C++
之所以选择C++,是因为在科研方面,C++有许多已经很成熟的库,也有许多前人的工作可以借鉴,尽管其本身的学习要难些,但资料很多,遇到问题也不难在google上得到答案,而且C++程序的效率比较高。写程序的效率方面,不拘泥于C风格,适应起STL风格的编程,也还是比较高的。
二、IDE
选定了语言,就要选具体的开发平台了,不像国外,国内还是windows当道,机子配置低的可以选择eclipse,还可以的可以选择vs2008(普通双核就很ok了,没有传说中的那么夸张),但是msvc编译器这玩意还是有很大的优化余地的,在这里选择了用SGI STL库取代其自带的库,同时试用了Intel C++编译器11.1版本。原因很简单,SGI STL的效率比自带库高得多了,Intel编译器才颇有独到之处,请看下文。
三、STL库的选择
我借用 C++ Primer测试string和C风格字符串的一段程序作了测试,源代码如下:
#include <ctime>
#include <string>
#include <iostream>
#include <cmath>
using namespace std;
int main(int argc,char *argv[])
{
clock_t StartClock,EndClock;
const int LoopTimes=5000000;
for (int i=0;i<1000;i++)
{
sin(5.0);
}
StartClock=clock();
//C-style code
const char *pc=”a very long literal string”;
const size_t len=strlen(pc);
for (size_t ix=0;ix!=LoopTimes;ix++)
{
char *pc2=new char[len+1];
strcpy(pc2,pc);
if (strcmp(pc2,pc))
{
cout<<”error”<<endl;
}
delete [] pc2;
}
EndClock=clock();
double DurationTime1=static_cast<double>(EndClock-StartClock)/CLOCKS_PER_SEC;
StartClock=clock();
//string-style code
string str(“a very long literal string”);
for (string::size_type ix=0;ix!=LoopTimes;++ix)
{
string str2=str;
if (str2!=str)
{
cout<<”error”<<endl;
}
}
EndClock=clock();
double DurationTime2=static_cast<double>(EndClock-StartClock)/CLOCKS_PER_SEC;
cout<<”C-style: “<<DurationTime1<<” s.”<<endl;
cout<<”String-style: “<<DurationTime2<<” s.”<<endl;
return 0;
}
测试平台:
CPU:Intel Q9550
内存:4G
系统:Windows 7 ultimate x64
测试的结果如下:
|
编译平台 |
C风格 |
string |
|
Intel 11.1 x86(VS STL) |
0.579 |
0.888 |
|
Intel 11.1 x86(SGI STL) |
0.579 |
0.340 |
|
Intel 11.1 x64(VS STL) |
0.399 |
0.530 |
|
Intel 11.1 x64(SGI STL) |
0.422 |
0.073 |
|
MSVC9 x86(VS STL) |
0.578 |
0.967 |
|
MSVC9 x86(SGI STL) |
0.585 |
0.345 |
|
MSVC9 x64(VS STL) |
0.559 |
0.559 |
|
MSVC9 x64(SGI STL) |
0.567 |
0.102 |
|
MinGW with GCC4.4 x86 |
1.573 |
0.208 |
|
MSVC10 x86(VS STL) |
0.521 |
0.554 |
|
MSVC10 x64(VS STL) |
0.550 |
0.430 |
很明显,VS STL没有达到Lipman描述的超过C风格的效率,而SGI STL则可以,测试中32位平台效率最高的是GCC4.4,这也是一个优秀的编译器,不过还是在Linux下用起来比较顺当。另外64位平台明显比32位快,对速度比较敏感的项目可以考虑迁移平台了。
四、boost库
boost库又被称为未来的标准库,其中包括已经纳入tr1甚至即将发布的c++ 0x标准中的库,lambda表达式等新鲜东西不光适合尝鲜,也很有益于开发效率,也是我下一步将要学习的大头之一。
五、Qt
选择它的原因很简单,相比较于MFC,它实在是好学得多了,我不是程序员,我只是想要用一个简单的界面表达我想要达到的功能,也许C#+Windows Form会更简单,但是我真的懒得再多学一门语言,也不擅长混合编程。
六、后记
补遗一下,Visual Studio 2008下有个很好用的工具,就是大名鼎鼎的Visual Assist了,番茄很好吃,也是我偏爱这个IDE的很大原因之一,对我来说,傻瓜又好用才是王道。
下一次该要记录的,就是这个平台的搭建了。
时隔半年,再开博客
半年前,和兔子兴致勃勃的开了博客,技术上没有多少问题,因为我们的要求很简单,现在的技术又很发达,早就有热心的技术人员为我们准备好了wordpress这么好的平台。可惜host2ez中间倒了,虽然数据都有存,不过忙忙碌碌的我意兴阑珊,也就搁下了。中间也想过用商业网站提供的现成平台,可惜mousefire这个名字大半是被注册过了。。无奈,还是得麻烦一下自己,再开一下喽。
刚开出来发现老是出问题,访问速度时快时慢,排除了WordPress插件的问题以后,最后发现是godaddy莫名其妙的加了一条A记录,大概搞得域名解析冲突了吧,早上删除了,到目前为止blog都很正常,再观后效吧,先用起来再说。
最近评论