爱linux,爱qt, 记录学习的每一个脚印!!!
KDE常用网站
4.1. Main Window Classes
4. GUI Applications
4. GUI应用化程序
使用Qt构建现代应用程序简单、快捷,既可以手动编写代码,也可以使用
Qt Desinger--Qt的可视化设计工具。
Qt提供了所有创建现代应用程序所需要的实用的类与函数。Qt既可以用于创建"主窗口式"的应用程序:带有菜单栏,工具栏,和状态栏在窗口的四周,也可以用于创建"对话框式"的应用程序:使用按钮和活动页(tabs)来显示可选的选择项和信息。Qt同样支持SDI(sigle document interface)和MDI(multiple document interface)。Qt也支持拖放(drag and drop)和剪贴板。
工具栏可以在其区域内自由移动,也可以拖到其它区域,也可以像工具面板那样浮动(tool palettes)。这些功能都是内建的,故无需编写多余的代码。当然,如果需要,程序员也可以限制和工具栏的行为。
Qt简化了开发编程。比如,如果有一个菜单项,一个工具按钮,一个键盘加速键都执行同一个动作,那么这个动作的代码仅需要编写一次。
Qt也提供消息框及完整的标准对话框集以方便应用程序方便的向用户提问,让用户选取文件、文件夹、字体、颜色。实际上, 显示一个消息框或标准对话框所要做的仅仅是用一条语句来调用Qt的静态便利功能。
Qt可以做到平台独立的保存应用程序的设置,如用户偏好,最近使用过的文件,窗口与工具栏位置、大小,等。
3.2 Meta Object Compiler
3.1. A Signals and Slots Example
3.1 信号和槽的例程
为了较好的使用信号和槽机制,类必须从QObject或它的一个子类继承派生,并在类定义声明部分包含Q_OBJECT宏。信号在类的signals字段中进行声明,而槽则在类的public slots,protected slots,private slots字段中。
下面给出的是QObject的子类:
class BankAccount : public QObject
{
Q_OBJECT
public:
BankAccount() { curBalance = 0; }
int balance() const { return curBalance; }
public slots:
void setBalance( int newBalance );
signals:
void balanceChanged( int newBalance );
private:
int curBalance;
};
与多数C++类格式一样,BanckAccount类有一个构造函数,一个"get"函数balance()和一个"set"函 数setBalance()。
该类有一个signal函数balanceChanged(),它在账户余额发生变化后发出通告。当一个signal发出后,那么其连接到的slot函数将被执行。
下面给出了槽setBalance()的实现:
void bankAccount::setBalance( int newBalance )
{
if ( newBalance != curBanlance ) {
curBalance = newBanlance;
emit balanceChanged( curBalance );
}
}
其中这条语句:
emit balanceChanged( curBalance );
以当前新的余额为参数调用signal函数balanceChanged(),以便发出该signal。关键字emit,与signals和slots一样,由Qt提供并由Qt的C++预处理器翻译成为标准的C++代码。
下边是如何连接两个BankAccount:
BankAccount x, y;
connect( &x, SIGNAL(balanceChanged(int)), &y, SLOT(setBalance(int)) );
x.setBalance( 2450 );
当x的余额被设为2450后,x将发出balanceChanged() signal。该signal被y的setBanlance() slot收到后,y的余额将被设为2450。
一个对象的signal可以被指定连接到多个不同的slot上,而且多个signal可以被定连接到特定的对象一个slot。只有对应参数类型一致的 signal和slot才能建立这样的连接。而slot的参数表中的参数可以少于signal,那么signal多于的参数将被忽略。
3. Signals and Slots
3. 信号和槽
信号和槽提供对象间通信,易于理解和使用,并得到Qt设计器的完全支持。
GUI 应用程序对用户动作的响应,比如,当一个用户点击菜单项或一个工具条按钮,应用程序便执行一段代码。更普遍的,我们希望任意类型的对象可以相互之间进行通信。开发者则必须将事件与相应的代码关联起来。原有的开发工具包使用的并非类型安全(容易导致崩溃),即不灵活也不是面向对象的。
信号和槽连接概览
Trolltech提出了称为信号和槽的解决方案。信号和槽是一个强大的对象间通信机制,它可以完全取代粗糙的传统开发工具包中的回调机制与消息映射机制。信号和槽使用灵活、完全面向对象,并用C++实现。
在原有的回调机制中,为了关联代码与按钮必须将指向函数的指针赋给按钮。当按钮被单击后,相应的函数将被调用。旧的开发工具包并不保证在调用函数时传递参数的类型的正确性,从而增加了程序崩溃的可能性。使用回调机制的另一个问题就是它将GUI元素紧紧的绑定到具体功能之上,加大了独立的开发实用类的难度。
Qt的信号和槽机制则不同。Qt的部件在事件发生的时候将发出信号。比如当被单击后,按钮将发出"clicked"信号。程序员可以通过调用connect ()函数将已经创建的一个函数(称为一个槽)连接到信号,将信号和槽关联起来。该机制并不要求各个类需要相互了解,得以将开发高度可复用类的工作变得简单容易。它是一个保证类型安全的机制,类型不匹配错误将通过编译时的警告(warnings)提交出来,避免了运行时导致程序崩溃。
例如,如果Quit按钮的clicked() signal被连接到程序的quite() 槽。用户单击Quit按钮将结束并退出程序。代码如下:
connect( button, SIGNAL(clicked()), qApp, SLOT(quit()) );
连接在Qt程序运行时任意的添加和删除。
信号和槽机制的实现,绝好的扩展了C++语法并很好的利用了C++面向对象的功能。信号和槽机制是一种类型安全的机制,可以被重载或重新实现,并可以在类的public,protected或private访问控制字段中使用。
一个信号和槽连接的例子
2.3. Custom Widgets
2.3. 自定义部件
开发者可以通过继承QWidget或其子类来创建自己的对话框或部件。为了说明这个过程,下边给出了数字时钟的完整代码。
这个时钟部件是一个LCD形式先是当前时间并自动更新,冒号分隔符每闪一次,表明时间走过一秒。
在clock.h文件中类Clock定义如下:
#include
class Clock : public QLCDNumber
{
public:
Clock( QWidget *parent = 0, const char *name = 0 );
protected:
void timerEvent( QTimerEvent *event );
private:
void showTime();
bool showingColon;
};
类Clock从类QLCDNumber部件继承了LCD的显示功能,他有一般部件的构造函数,带有可选的父部件和实例名参数(提供实例名将使得测试和调试更容易)。timerEvent()函数是继承自QObject并在初始化是自动调用。
在clock.cpp文件中,在文件clock.h中声明的函数实现如下:
#include
#include "clock.h"
Clock::Clock( QWidget *parent, const char *name )
: QLCDNumber( parent, name ), showingColon( true )
{
showTime();
startTimer( 1000 );
}
void Clock::timerEvent( QTimerEvent * )
{
showTime();
}
void Clock::showTime()
{
QString time = QTime::currentTime().toString().left( 5 );
if ( !showingColon )
time[2] = ' ';
display( time );
showingColon = !showingColon;
}
构造函数调用showTime()并初始化当前时间来初始化时钟,并通知系统每1000毫秒调用timerEvent()函数,以刷新LCD显示。
在showTime()函数中以当前时间调用QLCDNumber::display(),而冒号而每次被空格所替换,以显的冒号在闪烁。
clock.h和clock.cpp完成编译后便完成了clock部件的实现。这个部件可以立即投入使用:
#include <qapplication.h>
#include "clock.h"
int main( int argc, char **argv )
{
QApplication app( argc, argv );
Clock *clock = new Clock;
app.setMainWidget( clock );
clock->show();
return app.exec();
}
这个例程只包含一个部件,并没有子部件,复杂的部件可以通过将多个部件分层次的搭配在一起而构成。
开发者也可从新开发自定义部件。例如,为了创建一个类似的时钟,就必须在代码中画时钟的外形和表针,而不是依靠在一些基础类中已经实现的功能。这些方法在"2D图形"一节。
2.2. Built-in Widgets
2.2. 内建部件
下边的截图是主要的Qt 部件,它们以Windows的风格显示出来。
QLabel和QPushButton放置在QHBox中
QRadioButtons和QCheckBoxes放置在QButtonGroup中(图4)
QDateTimeEdit,QLineEdit,QTextEdit和QComboBox放置在QGroup-Box中
QDial,QProgressBar,QSpinBox,QScrollBar,QLCDNumber和QSlider放置在QGrid中
QIconView,QListView,QListBox和QTable放置在QGrid中
QTabWidget和QToolBox放置在QHBox中
QComboBox, QLineEdit和QSpinBox的输出可以使用QValidator的子类进行强制约束,规则表达式也可用于认证。
通过继承QScrollView生成的部件,可以用于显示大量的数据(如QTable, QListView和QTextEdit),并且可以自动的添加滚动条。
QMainWindow, QMenuBar和QToolBar出现在"GUI应用程序"一节。QMessageBox, QFileDialog, QWizard和其他对话框出现在"对话框"一节。"布局管理"一节涉及到了QSplitter。QCanvas和QGLWidget则出现在"2D和3D图形"一节。
截图所示QRadioButtons和QCheckBoxes(图4),是由下面的代码生成:
parent = new QButtonGroup( 2, Qt::Vertical, "QButtonGroup" );
radio1 = new QRadioButton( "&Radio 1", parent );
radio2 = new QRadioButton( "R&adio 2", parent );
radio1->setChecked( true );
check1 = new QCheckBox( "&Check 1", parent );
check2 = new QCheckBox( "C&heck 2", parent );
check2->setChecked( true );
2.1. A “Hello” Example
2.1. "Hello"实例
这个显示"Hello Qt!"程序的完整代码如下:
#include <qapplication.h>
#include <qlabel.h>
int main( int argc, char **argv )
{
QApplication app( argc, argv );
QLabel *hello = new QLabel( "<font color=blue>Hello <i>Qt!</i>"
"</font>", 0 );
app.setMainWidget( hello );
hello->show();
return app.exec();
}
2. Widgets
2.部件
Qt有一组丰富的部件(按钮,滚动条等)适用于许多位置。Qt的部件是灵活的,
很容易对子类为特殊需要。
Qt提供了完整的部件。部件是可视化的,可组合的创建用户界面,如按钮,菜单,滚动条,消息框和应用程序窗口。Qt的部件不是任意的分为"控件"和"容器";所有的部件都可用作控件或容器。自定义的部件可以很容易的继承现有的Qt部件,或创建新的在需要时。
部件是QWidget或它的一个子类的实例,而自定义部件是通过继承创建。
一个部件可以包含许多子部件。子部件将被显示在父部件内,没有父部件的是一个最高级的部件,它们通常拥有自己的条目显示在桌面环境的任务条中。Qt没有对部件任何限制,任意一个部件都可成为最高级的,也可成为人和部件的子部件。子部件在父部件内的位置可以使用布局管理器或手动形式设置。当父部件被禁止,隐藏,删除时,这些动作也将递归的应用到它的子部件上。
标签,消息框,工具条等,可使用多种的颜色,字体和语言。Qt的文本输入部件可使用HTML的子集显示多种语言的多文本样式。