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 2.0 的 Master Page(母版页)
    vs2008中文版提供下载(包含中文msdn),包括vs2008序列号和破解方法。
    C# 2.0 :仿MSN提示框or仿迅雷提示框(.Net2.0).rar
    httpanalyzer 结合 HttpWebRequest Post的运用
    xp访问权限问题的解决(绝对有效)
    Request.params、Request、Request.querystring、Request.Form 具体区别!
    C# List<> 泛型中遍历不同类型
    备份与恢复数据库的存储过程
    .Net 生成不重复的随机数
  • 原文地址:https://www.cnblogs.com/misspy/p/3676661.html
Copyright © 2011-2022 走看看