QT(5)Dialog - Addressbook例子3

本文介绍如何在Qt中使用对话框进行联系人查找,并实现文件的二进制及文本格式读写,包括QFileDialog的使用、QDataStream进行数据序列化及文本流操作。

  我们丰富Addressbook的例子,增加一个Find按键,可弹出一个dialog,参考:http://doc.qt.nokia.com/latest/tutorials-addressbook-part5.htmlhttp://doc.qt.nokia.com/latest/tutorials-addressbook-part6.htmlhttp://doc.qt.nokia.com/latest/tutorials-addressbook-part7.html,学习下面的内容:

  1. QDialog的使用方法。
  2. QFileDialog的使用方法
  3. 二进制和文本的文件读写
  4. split,QRegExp,QStringList等相关String的使用方法

  为此,我们增加FindDialg的类,继承QDialog。下图是主Window的界面,以及FindDialog的弹出界面。

  我们增加一个头文件finddialog.h和源文件finddialog.cpp来处理弹框。请注意在*.pro文件中加入相关的文件,通过qmake重新生成Makefile。finddialog.h如下:

按Find按钮后弹框:

#ifndef WEI_FINDDIALOG_H
#define WEI_FINDDIALOG_H

#include <QDialog>

class QLineEdit;
class QPushButton;

class FindDialog : public QDialog
{
    Q_OBJECT

public :
    FindDialog(QWidget * parent = NULL);
    QString getFindText();

public slots:
    void findClicked();

private:
    QPushButton * findButton;
    QLineEdit   * lineEdit;
    QString       findText;
};

#endif

  我们看看finddialog.cpp文件:

#include <QtGui>
#include "finddialog.h"

FindDialog::FindDialog(QWidget *parent): QDialog(parent)
{
    QLabel * findLabel = new QLabel(tr("Enter contact's name: "));
    lineEdit = new QLineEdit;
    findButton = new QPushButton(tr("&Find"));
    findText = "";

    QHBoxLayout * layout = new QHBoxLayout;
    layout->addWidget(findLabel);
    layout->addWidget(lineEdit);
    layout->addWidget(findButton);

    setLayout(layout);
    setWindowTitle(tr("Find Contact"));

    /* 我们在这里作两个test case。方式一:将findButton的clicked()信号连接两个slot函数,先是findClicked()然后是accept()。accept()是QDialog的一个函数,当QDialog hide的时候给出dialog的返回数值QDialog::Accepted。当我们处理了findClicked后,则依次调用accept(),这是dialog将会hide(注意在QT中不是关闭),并且返回一个resultcode:Accepted。这个处理关系如图所示 */
    connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
    connect(findButton, SIGNAL(clicked()), this, SLOT(accept())); //在Test case 2中我们注释此行。
}

void FindDialog::findClicked()
{
    QString text = lineEdit->text();
    if(text.isEmpty()){
        QMessageBox::information(this,tr("Empty Field"), tr("Please enter a name."));

        return; //在这个例子,如果是空的,执行完此,return后,调用accept,窗口会自行关闭
    }else{
        findText = text;
        lineEdit -> clear();

        //accept(); // Test Case2:由于处理findClicked后,没有下一步的accept,通过test2 我们可以比较了解信号依次出发的情况。
    }

}
/*在这里,我们注意到,宁可增加一个public来读取属性, 也不将该属性设置为public,即使目前只提供读的功能,这是一种好的编写风*/
QString FindDialog :: getFindText()
{
    return findText;
}

  现在补充addressbook.h,如下:

... ...
#include "finddialog.h"
... ...
class AddressBook : public QWidget
{
    ... ...
public slots:
    ... ...
    void findContact();

private:
... ...
    FindDialog * dialog;
    QPushButton * findButton;
};
... ...

  补充addressbook.cpp,如下:

... ...
AddressBook :: AddressBook(QWidget * parent) : QWidget(parent)
{
... ...
    findButton = new QPushButton(tr("&Find"));
    findButton->setEnabled(false);
    dialog = new FindDialog();
... ...
    buttonLayout1->addWidget(findButton);
... ...
    connect(findButton, SIGNAL(clicked()),this,SLOT(findContact()));

}

void AddressBook::updateUI(Mode mode){
... ...
    case NavigationMode:
... ...
        findButton -> setEnabled(!contacts.isEmpty());
... ...   

}

void AddressBook::findContact()
{
   dialog->show();
   if(dialog->exec() == QDialog::Accepted){
       QString contactName = dialog->getFindText();
       if(contacts.contains(contactName)){
           nameLine->setText(contactName);
           addressText->setText(contacts.value(contactName));
       }else{
           QMessageBox::information(this,tr("Not Found"), tr("Sorry, %1 is not found").arg(contactName));
       }

   }
}

二进行的文件读写

  我们进一步完善,增加两个button,saveButton和loadButton,将click()信号connect置saveToFile()和loadFromFile(),相关的updateUI修改方式就不在重复,对于一个button,我们还可以采用setToolTip鼠标放在上面,出现提示方式。

loadButton->setToolTip(tr("Load contacts from a file"));
saveButton->setToolTip(tr("Save contacts to a file"));

  我们重点看看save和load,对应写文件和读文件。文件采用QFile,QFile是QIODevice的subclass。通过QFile来open一个文件,如果文件不存在,则创建这个文件。使用 QDataStream来从QIODevice中二进制读写数据。下面是写的例子:

//对于文件类型,假设Address Book类型有两种*.a和*.b,方式为Address Book(*.a *.b),如果多个文件类型,之间使用“;;”来分割
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Address Book"),"",  tr("Address Book(*.abk);;All Files (*)"));
if(fileName.isEmpty())
    return;

QFile file(fileName);
if(file.open(QIODevice::ReadOnly)){
    QDataStream in(&file);
   
contacts.empty();
    in >> contacts; //将in的内容导入contacts。}
}

  下面是读的例子:

    QString fileName = QFileDialog::getSaveFileName(this, tr("Save Address Book"),"", tr("Address Book(*.abk);;All Files (*)"));
    if(fileName.isEmpty())
        return;

    QFile file(fileName);
    if(!file.open(QIODevice::WriteOnly)){
        QMessageBox::information(this,tr("Unable to open file!"), file.errorString());
        return;

    }
    QDataStream out(&file);
    out << contacts;
    file.close();

  在Tutorial的例子中我们发现没有加入close(),close是调用flush后close文件,必须加入的,否则容易出问题。

文本读写方式和String的一些高级用法

  上面是二进制的读写,有时我们需要采用文本text的方式,我们在上面的例子中增加到处vCard格式,并将其保存。我们需要将名字name中区分firstName,llastName。相当于获取一个字符串用空格分隔的第一个字符串和最后一个字符串。

// 其中nameList是QStringList,相当于一个String数组来保存,用split来分开,第二个参数表示如果分割后,entry为空,忽略,例如我们使用;分割,如果有;;,则有一个空的entry,将这个忽略。用户的输入,可能中间隔一个空格,也可能隔两个空格,无论多少个空格我们都作为一个分割符号来处理。这里我们使用了QRegExp来处理。/s表示空格,+表示可以多个。
nameList = name.split(QRegExp("//s+"),QString::SkipEmptyParts);
firstName = nameList.first();  lastName = nameList.last();

  对于文本文件的写,获得有效的QFile file后,如下操作:

    QTextStream out(&file);
    out << "BEGIN:VCARD" << "/n";
    out << "VERSION:2.1" << "/n";
    out << "N:" << lastName <<";" <<firstName <<  "/n"; ... ... //根据vCard格式加,此处略去
    file.close();

  对于close,在我们的实验中,似乎二进制的方式,如果忘记了问题还表示很大,但是文本方式就很有问题。我们编写了一个采用文本方式读文件的函数,如果在write后面(没有close)马上调用之前读函数,读出来为空,如果在write最后有close,则正常。所有我们应该在open之后,加入close。

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

<think> 我们正在讨论的是Qt Material Widgets中的对话框使用方法和相关示例。根据提供的引用,我们可以参考一些Qt中的对话框使用方式,但需要明确这些引用并不直接针对qt-material-widgets,因此我们需要结合qt-material-widgets的特性来回答。 首先,qt-material-widgets是一个基于Qt Widgets的库,它提供了Material Design风格的组件。因此,对话框的使用应该类似于Qt的标准对话框,但具有Material Design的外观。 从引用[2]中,我们看到了一个使用Qt.labs.platform中的FileDialog的示例,但这是在QML中的用法。由于qt-material-widgets是基于Widgets的,因此我们应该使用C++和Qt Widgets的方式来创建对话框。 在Qt Widgets中,常用的对话框有: 1. QFileDialog:用于文件选择 2. QMessageBox:用于显示消息 3. QInputDialog:用于获取用户输入 4. QColorDialog:用于选择颜色 5. QFontDialog:用于选择字体 在qt-material-widgets中,可能会有自定义的Material风格对话框组件,但通常它们会继承自Qt的标准对话框类,并应用特定的样式。 由于qt-material-widgets的文档可能不是非常详尽,我们可以参考其GitHub仓库中的示例。假设我们想使用一个简单的消息对话框,我们可以这样做: ```cpp #include <QApplication> #include <qtmaterialdialogs.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 设置整体样式为Material Design QtMaterialTheme::setColorScheme(QtMaterialColorScheme::Purple); // 例如,设置颜色方案为紫色 // 创建一个消息对话框 QtMaterialMessageDialog dialog; dialog.setText("This is a Material Design styled message dialog."); dialog.setTitle("Message Title"); dialog.addActionButton("OK", QMessageBox::AcceptRole); dialog.addActionButton("Cancel", QMessageBox::RejectRole); dialog.exec(); return a.exec(); } ``` 但是,请注意,qt-material-widgets的具体API可能有所不同,因此最好查阅其文档或示例代码。 另外,根据引用[1]和[2],在QML中使用了FileDialog,但如果我们是在Widgets中使用,应该使用QFileDialog。而在qt-material-widgets中,可能会提供一个Material风格的QFileDialog。我们可以这样使用: ```cpp #include <QFileDialog> #include <qtmaterialtheme.h> // ... QString fileName = QFileDialog::getOpenFileName(this, "Open Image", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "Image Files (*.png *.jpg *.jpeg)"); if (!fileName.isEmpty()) { // 加载图像等操作 } ``` 由于qt-material-widgets通过样式表和应用主题来改变外观,因此标准的QFileDialog也会被应用Material风格,无需特别调用。 如果我们想使用qt-material-widgets中自定义的对话框类,例如`QtMaterialDialog`(具体类名需要查看文档),那么用法可能如下: ```cpp #include <qtmaterialdialog.h> // ... QtMaterialDialog *dialog = new QtMaterialDialog(this); dialog->setWindowTitle("Material Dialog"); dialog->setText("This is a custom material dialog."); // 添加按钮等 dialog->addButton("OK", QtMaterialDialog::AcceptRole); dialog->addButton("Cancel", QtMaterialDialog::RejectRole); connect(dialog, &QtMaterialDialog::acceptButtonClicked, this, &MyClass::onAccept); dialog->exec(); ``` 请注意,以上代码仅为推测,实际使用需要参考qt-material-widgets的文档或示例。 由于用户要求提供使用方法和示例,我们可以假设qt-material-widgets的对话框使用方式与标准Qt对话框类似,但具有不同的样式。 另外,引用[3]提到了示例的manifest文件,我们可以查看qt-material-widgets的示例来获得更具体的用法。通常,在GitHub仓库的examples目录下会有示例代码。 总结: 1. 对于消息对话框,可以使用`QtMaterialMessageDialog`(如果存在)或者使用`QMessageBox`(会自动应用Material样式)。 2. 对于文件对话框,使用`QFileDialog`,它会自动应用样式。 3. 若需要自定义对话框,可以使用`QtMaterialDialog`(如果存在)来构建。 由于没有直接给出qt-material-widgets的对话框文档,建议用户查看其项目中的示例代码。 相关问题: 1. qt-material-widgets提供了哪些自定义对话框组件? 2. 如何为Qt的标准对话框应用Material Design样式? 3. 在qt-material-widgets中如何创建自定义对话框? </think> 基于Qt Material Widgets中Dialog的使用方法和相关示例,结合Qt文档的最佳实践,以下是关键信息总结: ### 一、Dialog的核心使用方法 1. **基础调用** ```cpp #include <QtMaterialWidgets> MaterialMessageBox dialog(parent); dialog.setTitle("提示"); dialog.setText("操作已完成"); dialog.addButton("确认", QMessageBox::AcceptRole); dialog.exec(); ``` 2. **文件对话框示例**(参考引用[2]) ```cpp MaterialFileDialog fileDialog; fileDialog.setTitle("选择图片"); fileDialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); fileDialog.setNameFilter("图片文件 (*.png *.jpg)"); if (fileDialog.exec() == QDialog::Accepted) { QString selectedFile = fileDialog.selectedFile(); // 处理选中的文件 } ``` 3. **对话框响应处理** ```cpp connect(&dialog, &MaterialMessageBox::accepted, []{ qDebug() << "用户确认操作"; }); ``` ### 二、关键特性 1. **独立样式系统** 使用纯Qt Widgets实现,不依赖QtQuick(参考引用[1]),确保跨平台兼容性。 2. **Material Design元素** - 平滑动画过渡 - 自适应阴影效果 - 动态颜色主题(可通过`QtMaterialTheme`配置) ```cpp QtMaterialTheme::setColorScheme(QtMaterialColorScheme::Purple); ``` 3. **对话框类型支持** | 对话框类型 | 类名 | 功能描述 | |--------------------|-----------------------|----------------------| | 基础对话框 | `MaterialDialog` | 自定义布局容器 | | 消息框 | `MaterialMessageBox` | 提示/警告消息 | | 文件对话框 | `MaterialFileDialog` | 文件选择 | | 颜色选择器 | `MaterialColorDialog` | 颜色选择 | ### 三、布局自定义示例 ```cpp MaterialDialog customDialog; QVBoxLayout *layout = new QVBoxLayout; // 添加Material组件 MaterialTextField *textField = new MaterialTextField; MaterialRaisedButton *btn = new MaterialRaisedButton("提交"); layout->addWidget(textField); layout->addWidget(btn); customDialog.setLayout(layout); // 按钮事件绑定 connect(btn, &MaterialRaisedButton::clicked, [&]{ customDialog.accept(); }); customDialog.exec(); ``` ### 四、最佳实践建议 1. **主题统一性** 在`main()`中全局设置Material主题: ```cpp QApplication::setStyle(new MaterialStyle); QApplication::setPalette(MaterialTheme::palette()); ``` 2. **动画优化** 启用窗口动画效果: ```cpp dialog.setAnimate(true); // 默认启用 ``` 3. **响应式设计** 使用`QSizePolicy::Expanding`确保对话框内容自适应: ```cpp dialog.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); ``` > 参考Qt Material Widgets官方示例:`/examples/dialogs`目录包含完整对话框实现(参考引用[3]的manifest文件指引)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值