zoukankan      html  css  js  c++  java
  • C++ GUI Programming with Qt4 笔记 -- chap2 QDialog

    以 finddialog 为例,介绍 QDialog。并对 Qt 的基本概念和技巧做了更进一步(chap1)的介绍。

    1.MOC 扩展与signals–slots 机制

    严格来说,Qt 开发,写的并不是标准 C++。

    Meta-Object System 是 Qt 对 C++ 的一项重要扩展,简称 moc。

    moc  is a mechanism for creating independent software components

    that can be bound together without any component knowing anything about the other components it is connected to

    提供了 2 个关键内容:signals–slots and introspection。

    其中,introspection 是实现 signals–slots 的基础。

    The mechanism works as follows:

    • The Q_OBJECT macro declares some introspection functions that must be implemented in every QObject subclass: metaObject(), tr(), qt_metacall(), and a few more.

    • Qt's moc tool generates implementations for the functions declared by Q_OBJECT and for all the signals.

    • QObject member functions such as connect() and disconnect() use the introspection functions to do their work.

    All of this is handled automatically by qmake, moc, and QObject, so you rarely need to think about it.

    But if you are curious, you can read the QMetaObject class documentation

    and have a look at the C++ source files generated by moc to see how the implementation works.

    2. 技巧与细节

    2.1 class forward declaration

    在头文件中,如果只用到了某个类的指针,不依赖于类的定义与实现。

    可以使用  class ClassName 声明类,取代  #include "ClassName.h" 

    相比于加载头文件,前置声明更简洁,性能更好。

    2.2 国际化:用户可见的文字,使用  tr() 

    2.3 快捷键:使用 & 声明快捷键。

    例如  &Find 声明快捷键为 F, 

    setBuddy(widget)  设置快捷键按下时,focus 到 widget 组件上,而非自身。

    2.4  setDefault  按下 Enter 键时的行为。

    2.5 setLayout 时会重新计算父子关系。

    layout 中的所有组件,都变成 setLayout 对象的子对象。

    2.6 使用 moc 机制(Q_OBJECT)时,类的定义必须在 .h 文件中,否则 moc 不会正常工作。

    // finddialog.h
    #ifndef FINDDIALOG_H
    #define FINDDIALOG_H
    
    #include <QDialog>
    
    class QCheckBox;
    class QLabel;
    class QLineEdit;
    class QPushButton;
    
    class FindDialog : public QDialog
    {
        Q_OBJECT
    public:
        FindDialog(QWidget *parent = 0);
    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
    // finddialog.cpp
    #include <QtGui>
    #include "finddialog.h"
    
    FindDialog::FindDialog(QWidget *parent)
        : QDialog(parent)
    {
        // widgets
        label = new QLabel(tr("Find &what: "));
        lineEdit = new QLineEdit;
        label->setBuddy(lineEdit);
    
        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"));
    
        // connections
        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()));
    
        // layout
        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 <QApplication>
    #include "finddialog.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        FindDialog *dialog = new FindDialog;
        dialog->show();
        return app.exec();
    }
  • 相关阅读:
    ASP.NET MVC 3.0(八): MVC 3.0 传递和保存你的Model
    ASP.NET MVC 3.0(十九): MVC 3.0 实例之使用开源控件实现表格排序和分页
    ASP.NET MVC 3.0(十二): MVC 3.0 使用自定义的Html控件
    ASP.NET MVC 3.0(十七): MVC 3.0 实例之表格中数据的筛选
    ASP.NET MVC 3.0 学习系列
    ASP.NET MVC 3.0(五): 入手Controller/Action
    ASP.NET MVC 3.0(十五): MVC 3.0 实例系列之表格的排序
    ASP.NET MVC 3.0(十): MVC 3.0 使用 Forms身份验证
    ASP.NET MVC 3.0(九): MVC 3.0 验证你的Model
    设计功能与界面的测试
  • 原文地址:https://www.cnblogs.com/misspy/p/3676661.html
Copyright © 2011-2022 走看看