`
javasogo
  • 浏览: 1844704 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

QT(4)信号、SLOT和QMap - Addressbook例子2

阅读更多

  在之前的MeeGo开发者(五):QT(3)对象和继承小例子 基础上,我们增加三个button,参考http://doc.qt.nokia.com/latest/tutorials-addressbook-part2.htmlhttp://doc.qt.nokia.com/latest/tutorials-addressbook-part3.html http://doc.qt.nokia.com/latest/tutorials-addressbook-part4.html ,学习下面三个内容:

  1. 这三个button放置在layout上,然后摆放在GuidLayout。
  2. 当按这些button的时候,释放signal,这些信号将触发某些slot的函数。这是本次学习的重点。
  3. 学习QMap的使用方法。

  最后的UI如图所示。我们在GuidLayou的(1,2)上摆放一个layout,layout上有三个button,按Add这进入增加新的联系人,按submit表示确定增加该联系人,按Cancel表示取消增加该联系人。在图的右边我们还看到一种三个button的摆放方式,我们会在程序中进行说明。

  用户的信息存放在QMap中,QMap适合存放带索引的数据,在这个例子中,以name为索引,address为该人名对应的信息。QMap是不使用外置数据库的情况下存储数据库的很好的方式。

  当button click后,释放一个signal,我们需要将这个signal和某个函数,在QT上称为slot函数。 在这个例子中,我们需要建立三个对应关心,如图所示。方式为:connect (addButton /*发出信号的对象*/ , SIGNAL(clicked())/*捕抓的信号*/ , this, SLOT (addContact())/*监测到信号后触发的slot函数*/ );

  main.cpp无需修改,addressbook.h如下所示:

#ifndef COM_WEI_ADDRESSBOOK_H
#define COM_WEI_ADDRESSBOOK_H

#include <QWidget>
#include <QMap>

class QLineEdit;
class QLabel;
class QTextEdit;

class QPushButton;

class AddressBook : public QWidget
{

Q_OBJECT

public:
AddressBook(QWidget * parent = NULL);

/* A slot is a function that responds to a particular signal. */
public slots:
void addContact();
void submitContact();
void cancel();

private:
QPushButton * addButton, * submitButton, * cancelButton;
QLineEdit * nameLine;
QTextEdit * addressText;

/* contacts用于存储联系人信息,是QMap对象,是存储key-value:这里联系人名字作为key,联系人地址作为value. */
QMap contacts;
QString oldName,oldAddress;
};

#endif

addressbook.cpp如下所示

/* addressbook.cpp - the implementation file for the AddressBook class */

#include <QtGuid>
#include "addressbook.h"

AddressBook :: AddressBook(QWidget * parent) : QWidget(parent)
{
QLabel * nameLabel = new QLabel(tr("Name:"));
nameLine = new QLineEdit();

nameLine->setReadOnly (true); // not editable

QLabel * addressLabel = new QLabel(tr("Address:"));
addressText = new QTextEdit();

addressText->setReadOnly(true);

addButton = new QPushButton("&Add");
addButton->show();
submitButton = new QPushButton("&Submit");

submitButton->hide ();
cancelButton = new QPushButton("&Cancel");
cancelButton->hide();

QVBoxLayout * buttonLayout1 = new QVBoxLayout;
buttonLayout1->addWidget(addButton,Qt::AlignTop);
buttonLayout1->addWidget(submitButton);
buttonLayout1->addWidget(cancelButton);

buttonLayout1->addStretch (); //紧凑排列,否则按三等分布局,即上面UI图中的右图。

connect(addButton, SIGNAL(clicked() ),this,SLOT(addContact() ));
connect(submitButton, SIGNAL(clicked() ),this,SLOT(submitContact() ));
connect(cancelButton, SIGNAL(clicked() ),this,SLOT(cancel() ));

QGridLayout * mainLayout = new QGridLayout();
mainLayout->addWidget(nameLabel,0,0);
mainLayout->addWidget(nameLine,0,1);
mainLayout->addWidget(addressLabel,1,0,Qt::AlignTop);
mainLayout->addWidget(addressText,1,1);

mainLayout->addLayout (buttonLayout1,1,2);

setLayout(mainLayout);
setWindowTitle(tr("Simple Address Book"));

}

void AddressBook::addContact()
{
printf("Line %d: %s\n",__LINE__,__FUNCTION__);
oldName = nameLine->text();
oldAddress = addressText->toPlainText();

nameLine->clear();
addressText->clear();

nameLine->setReadOnly(false);
nameLine->setFocus(Qt::OtherFocusReason);
addressText->setReadOnly(false);

addButton->setEnabled(false);
submitButton->show();
cancelButton->show();

}

void AddressBook::submitContact()
{
printf("Line %d: %s\n",__LINE__,__FUNCTION__);
QString name = nameLine->text();
QString address = addressText->toPlainText();
if(name.isEmpty() || address.isEmpty()){

QMessageBox::information (this,tr("Empty Field"), tr("Please enter a name and address"));
return;
}

if(contacts.contains(name)){
QMessageBox::information(this,tr("Add Unsuccessful!"), tr("Sorry,\"%1\" is already in your address book").arg(name));
return;
}

contacts.insert (name, address); //QMap的用法
QMessageBox::information (this, tr("Add Successful!"),
tr ("<%1,%2 > has been added to your address book.").arg(name,address) ); //%1,%2表示arg中的参数顺序,图见下

nameLine -> setReadOnly(true);
addressText -> setReadOnly(true);
addButton -> setEnabled(true);
submitButton->hide();
cancelButton->hide();

}

void AddressBook::cancel()
{
printf("Line %d: %s\n",__LINE__,__FUNCTION__);
nameLine->setText(oldName);
nameLine->setReadOnly(true);
addressText->setText(oldAddress);
addressText->setReadOnly(true);

addButton->setEnabled(true);
submitButton->hide();
cancelButton->hide();

}

  QMessageBox的截图如下

  我们在这个基础上做进一步处理。我们增加一个两个button,用于向前查看或者向后查看,再次实践布局,并且学习一个QMap这个存储。QMap 是的entry是<key,value>,key的排列具体是否安hash值不清楚,但是在试验中,我们可以看到如果我们一次读取QMap的元素,将是按顺序(字母大小顺序)进行读出。begin是第一个元素,但是end不是最后一个元素,end可能是NULL,因此end-1才是最后一个有效元素。QMap的元素iterator 是可以简单进行++和--操作的。

  数据的基础操作是增/删/改/查,我们增加删/改两个功能,其中submit和cancel按键通用,在不同的功能要求下各组建的editabled/disenditabled,enabled/disenable,show/hide的显示要求不一样,我们采用一个函数updateUI来统计进行处理,利用一个enum区分不同的模式。将UI独立与功能也是开发的原则之一。

  对于addressbook.h,我们增加相关的button定义和SLOT函数。

... ...
class AddressBook : public QWidget
{
... ...
public:
... ...
enum Mode {NavigationMode,AddingMode, EditingMode}; //设置枚举方式

public slots:
... ...
void next();
void previous();
void editContact();
void removeContact();

private:
... ...
QPushButton * nextButton, * previousButton;
QPushButton * editButton, * removeButton;
Mode currentMode;
void updateUI(Mode mode); //用于专门处理UI的函数
};
... ...

  对于addressbook.cpp文件,我们修改如下,并让程序看起来更为优雅:

... ...
AddressBook :: AddressBook(QWidget * parent) : QWidget(parent)
{
... ...

editButton = new QPushButton(tr("&Edit"));
editButton->setEnabled(false);
removeButton = new QPushButton(tr("&Remove"));
removeButton->setEnabled(false);

... ...
buttonLayout1->addWidget(editButton); //将edit和remove两个button放置在sumbit和calcel前面
buttonLayout1->addWidget(removeButton);
buttonLayout1->addWidget(submitButton);
buttonLayout1->addWidget(cancelButton);

... ...
connect(editButton, SIGNAL(clicked()),this,SLOT(editContact()));
connect(removeButton, SIGNAL(clicked()),this,SLOT(removeContact()));
... ...
nextButton = new QPushButton(tr("&Next"));
nextButton->setEnabled(false);
previousButton = new QPushButton(tr("&Previous"));
previousButton->setEnabled(false);
connect(nextButton,SIGNAL(clicked()),this,SLOT(next()));
connect(previousButton,SIGNAL(clicked()),this,SLOT(previous()));
QHBoxLayout * buttonLayout2 = new QHBoxLayout;
buttonLayout2->addWidget(nextButton);
buttonLayout2->addWidget(previousButton);
... ...
mainLayout->addLayout(buttonLayout1,1,2);
mainLayout->addLayout(buttonLayout2,2,1);

... ...
}


void AddressBook::updateUI(Mode mode){
currentMode = mode;
switch(mode){
case AddingMode:
case EditingMode:

if(mode == AddingMode)
editButton->hide();
else if(mode == EditingMode)
addButton->hide();
removeButton->hide();

nameLine->setReadOnly(false);
nameLine->setFocus (Qt::OtherFocusReason);
addressText -> setReadOnly(false);

addButton->setEnabled(false);
editButton->setEnabled(false);
removeButton->setEnabled(false);
nextButton->setEnabled(false);
previousButton->setEnabled(false);

submitButton->show();
cancelButton->show();
break;
case NavigationMode: //浏览模式:任何功能完成后都进入浏览模式,如果有一个元素,则next和previous有效,并在此模式下可以进入功能操作
nameLine->setReadOnly(true);
addressText -> setReadOnly(true);
if(contacts.isEmpty()){
nameLine->clear();
addressText->clear();
}
addButton->setEnabled(true);
editButton->setEnabled(!contacts.isEmpty());
removeButton -> setEnabled(!contacts.isEmpty());
nextButton -> setEnabled(!contacts.isEmpty());
previousButton -> setEnabled(!contacts.isEmpty());
addButton->show();
editButton->show();
removeButton->show();
submitButton->hide();
cancelButton->hide();
break;
default:
break;

}
}


void AddressBook::addContact()
{
oldName = nameLine->text();
oldAddress = addressText->toPlainText();
nameLine->clear();
addressText->clear();
updateUI(AddingMode);

}

void AddressBook::editContact(){
oldName = nameLine->text();
oldAddress = addressText->toPlainText();
updateUI(EditingMode);

}

void AddressBook::removeContact(){
QString name = nameLine->text();
QString address = addressText->toPlainText();

if(contacts.contains(name)){
if(QMessageBox::question (this,tr("Confirm Remove"), tr("Are you sure you want to remove %1").arg(name),
QMessageBox ::Yes | QMessageBox :: No) == QMessageBox :: Yes){

previous();
contacts.remove (name); //QMap操作
if(contacts.isEmpty()){
nameLine->clear();
addressText->clear();
}
QMessageBox::information(this,tr("Remove successful!"),
tr("\"%1\" is already removed from your address book").arg(name));

}
}
updateUI(NavigationMode);

}

void AddressBook::submitContact()
{
QString name = nameLine->text();
QString address = addressText->toPlainText();

if(name.isEmpty() || address.isEmpty()){
QMessageBox::information(this,tr("Empty Field"),
tr("Please enter a name and address"));
return;
}

switch(currentMode){
case AddingMode:

if(contacts.contains(name)){
QMessageBox::information(this,tr("Add Unsuccessful!"), tr("Sorry,\"%1\" is already in your address book").arg(name));
return;
}else{
contacts.insert (name, address);
//QMap的使 用:增加
QMessageBox::information(this, tr("Add Successful!"), tr("<%1,%2> has been added.").arg(name,address));
}
break;
case EditingMode:
if(oldName != name){
if(!contacts.contains(name)){
QMessageBox::information(this, tr("Edit successful!"), tr("Sorry,<%1> has been edited.").arg(name));
contacts.remove (oldName); //QMap使用:删除
contacts.insert (name,address); //QMap的使用:增加

}else{
QMessageBox::information(this, tr("Edit Unsuccessful!"), tr("Sorry,<%1> already in your addressbook.").arg(name));
cancel();
}
} else if(oldAddress != address){
QMessageBox::information(this, tr("Edit successful!"), tr("Sorry,<%1> has been edited.").arg(name));
contacts[name] = address; //可以采用类似数组的方法对QMap[key]进行赋值
cancel();
}break;
default:
break;
}
updateUI(NavigationMode);

}

void AddressBook::cancel()
{
nameLine->setText(oldName);
addressText->setText(oldAddress);
updateUI(NavigationMode);

}

void AddressBook::next()
{
QString name = nameLine->text();
QMap<QString,QString>::iterator i = contacts.find (name); //QMap的查找和interator

i ++; //可通过i++,将元素移到下一个元素

if(i == contacts.end()) //由于最后一个元素为NULL,并不实际存在,需要设为第一个元素
i = contacts.begin();

nameLine->setText(i.key()); //获取key的值
addressText->setText(i.value()); //获取value的值
}

void AddressBook::previous()
{
QString name = nameLine->text();
QMap<QString,QString>::iterator i = contacts.find(name);

if(i == contacts.begin()){ //如果是第一元素,需要移为实际的最后一个元素,即end-1
i = contacts.end()-1;
}else{
i --;
}

nameLine->setText(i.key());
addressText->setText(i.value());

}

相关链接:我的MeeGo/Moblin相关文章

分享到:
评论

相关推荐

    Python库 | jkq.qmap-1.2.1.tar.gz

    在`jkq.qmap-1.2.1.tar.gz`这个压缩包中,包含了库的所有源代码和其他相关文件,为开发者提供了完整的开发环境。解压后,我们可以看到`jkq.qmap-1.2.1`目录,其中包含了`setup.py`文件,这是Python项目标准的安装...

    qt-vsaddin-msvc2017-2.3.0 +Visualizer.rar

    2. Qt工程模板:提供多种Qt项目模板,如Qt Console Application,Qt Widgets Application等。 3. 智能感知:支持Qt类和函数的代码补全,提高编码速度。 4. 调试支持:增强的调试器集成,可以查看Qt对象的状态,如...

    Python库 | jkq.qmap-1.5.1-cp37-cp37m-win_amd64.whl

    python库。 资源全名:jkq.qmap-1.5.1-cp37-cp37m-win_amd64.whl

    Python库 | jkq.qmap-1.2.1-cp37-cp37m-macosx_10_9_x86_64.whl

    《Python库:深入理解jkq.qmap-1.2.1》 在Python的世界里,库扮演着至关重要的角色,它们极大地扩展了Python的功能,使得开发者可以高效地完成各种任务。今天,我们要聚焦的是名为"jkq.qmap"的一个Python库,版本为...

    Qt学习之路---尤其适用Qt初学者

    通过发射信号和连接槽函数,开发者可以轻松实现复杂的功能逻辑。 2. **布局管理**:Qt提供了多种布局管理器(如QHBoxLayout、QVBoxLayout),这些布局管理器能够自动调整组件大小和位置,使得界面更加美观和适应...

    Qt5.12.4产物-银河麒麟-ARM64

    Qt5.12.4产物_银河麒麟_ARM64

    Qt之QMap的使用分析

    5.保证无毒 1.简单,方便,实用 3.实例可以自行改用 1.如有非法,本人无法律责任! 8.更多作品,查找标签...4.如需联系我请看左边数字!1.如不知代表何物,那就放弃计算机吧! 0.还不懂?CSDN老板不让我上传联系方式。

    qmap:QMAP-用C ++编写的用于量子电路映射的JKQ工具

    QMAP-用C ++编写的用于量子电路映射的JKQ工具 基于 , 提出的方法,提供了一种用于量子电路映射的工具。 A. Zulehner,A。Paler和R. Wille。 “将量子电路映射到IBM QX体系结构的有效方法” 。 IEEE集成电路和系统...

    Qmap 与map 的用法

    4. 功能需求:`QMap`提供了Qt特有的功能,如信号和槽;`std::map`则遵循STL接口,易于与其他STL容器配合。 理解并熟练运用`QMap`和`std::map`能帮助开发者在C++项目中更好地管理键值对数据,提高代码效率和可维护性...

    Qt中QMap和QMultimap使用

    QMap 是Qt的通用容器类之一。它存储(键,值) 对,并提供与键相关联的值的快速查找。其实就是一个键值对的集合,经常使用的。具体更详细还得看看帮助文档 QMap/QMultiMap属于关联式容器,其底层结构是通过二叉树实现...

    Qt容器类(QList,QMap)遍历器的使用

    QList和QMap是两种常用的Qt容器类,它们提供了多种操作数据的方法,包括插入、删除、查找以及遍历等。本篇文章将深入探讨Qt容器类中的QList和QMap,以及如何使用遍历器进行数据操作。 首先,QList是一种动态数组,...

    Qt使用内存共享例子

    一个简单的Qt使用内存共享方法,进程间通信的例子。使用了Windows 函数进行内存共享。注释部分代码也有qt函数进行内存共享的例子;

    Qt5开发及实例-CH204.rar,Qt5在QMap中的插入、遍历和修改的代码

    实例CH204,在QMap中的插入、遍历和修改。 (a) for(;i.hasNext();)、qDebug()()().value():完成对QMap的遍历输出。在输出QMap的键和值时,调用的函数是不同的。因为在输出键的时候,不需要使迭代点移动到下一个位置...

    qt4白皮书(中文版)

    Qt 最具特色之处在于其独特的“信号和槽”(Signals and Slots)机制,这是一种对象间通信的方式,能够简化事件驱动编程的复杂度。 #### 2. 窗体设计 - **内建窗体**:Qt 提供了一系列预定义的窗体类型,如 `...

    C++模式设计-基于QT4开源跨平台开发框架与源代码

    QT4的信号与槽机制使得对象间的通信更加便捷,是实现设计模式中的事件驱动和观察者模式的良好工具。 4. 泛型编程(Generic Programming):通过使用模板,C++允许开发者编写不依赖特定数据类型的代码,从而提高了...

    qt6开发实践(第6版)PPT.zip

    - Qt的设计理念,如模型-视图-控制器(MVC)架构和信号与槽机制。 - Qt的组件体系,包括QWidgets、Qt Quick(QML)以及Qt 3D等模块。 - 安装Qt开发环境,配置编译器和构建系统。 2. **第2章:Qt模板库、工具类及...

    C++模式设计-基于QT4开源跨平台开发框架源代码

    2. **mixed-types.cpp**:这个文件可能涉及了不同类型数据的处理,可能是Qt4中的模板类如QList、QMap等,这些容器可以容纳不同类型的元素,展示了C++模板的威力。 3. **ansicast**:可能是一个关于ASCII字符编码和...

    Qt4 Json 解析和编码类,支持中文 2012.11.05

    在Qt4中,JSON(JavaScript Object Notation)解析和编码是一个常见的需求,特别是在与服务器进行数据交换时。JSON因其简洁、易读的格式,成为网络通信中数据交换的标准格式之一。在Qt4中,虽然没有内置的JSON支持,...

Global site tag (gtag.js) - Google Analytics