Qt学习
.VS2013使用Qt
1.下载安装Qt
去Qt官网下载qt-opensource-windows-x86-msvc2013-5.8.0.exe,安装到目录(此处安装在D盘)
2.打开VS2013新建控制台应用程序
新建main.cpp
3.配置属性
属性->C/C++->常规->附加包含目录:D:\Qt\Qt5.8.0\5.8\msvc2013\include
->连接器 ->常规->附加库目录:D:\Qt\Qt5.8.0\5.8\msvc2013\lib
->连接器 ->输入->附加依赖项: Qt5Core.lib;Qt5Widgets.lib;
#include "QtWidgets/QApplication"
#include "QtWidgets/QDialog"
#include "QtWidgets/QPushButton"
#include "QtWidgets/QSlider"
#include "QtWidgets/QSpinBox"
#include "QtWidgets/QBoxLayout"
#include "QtWidgets/QGridLayout"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QDialog dlg;
dlg.setWindowTitle("QDialog");
QPushButton btn("Ok", &dlg);
QSlider slider(Qt::Horizontal, &dlg);
slider.setRange(0, 120);
slider.setPageStep(10);
slider.setValue(30);
QSpinBox spin(&dlg);
spin.setRange(0, 120);
spin.setValue(30);
QHBoxLayout layoutH;
layoutH.addWidget(&slider);
layoutH.addWidget(&spin);
layoutH.addWidget(&btn);
dlg.setLayout(&layoutH);
// 滑动滑条改变spin的值
QWidget::connect(&slider, SIGNAL(valueChanged(int)),
&spin, SLOT(setValue(int)));
// 改变spin的值移动滑条
QWidget::connect(&spin, SIGNAL(valueChanged(int)),
&slider, SLOT(setValue(int)));
// 点击"Ok"关闭Dialog
QWidget::connect(&btn, SIGNAL(clicked()),
&dlg, SLOT(close()));
dlg.show();
return app.exec();
}
4.编译运行
运行时需要到D:\Qt\Qt5.8.0\5.8\msvc2013\bin下,把libEGL.dll与libGLESv2.dll放到拷贝到可执行文件目录。
5.继承Qt类
如实现加法计算器的Dialog
CalculatorDialog.h
#ifndef _CALCULATOR_DIALOG_H #define _CALCULATOR_DIALOG_H #include "QtWidgets/QDialog" QT_BEGIN_NAMESPACE class QLineEdit; class QPushButton; class CalculatorDialog : public QDialog { // MOC编译器把不符合标准的语法编程标准的C++语法 Q_OBJECT public: CalculatorDialog(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~CalculatorDialog(); private slots: void enableCalcButton(void); void calcClicked(void); private: QLineEdit* m_editX; QLineEdit* m_editY; QLineEdit* m_editZ; QPushButton* m_btnCalc; }; QT_END_NAMESPACE #endif
CalculatorDialog.cpp
#include "CalculatorDialog.h" #include "QtCore/QTextCodec" #include "QtWidgets/QLineEdit" #include "QtWidgets/QLabel" #include "QtWidgets/QPushButton" #include "QtWidgets/QBoxLayout" CalculatorDialog::CalculatorDialog(QWidget *parent /* = Q_NULLPTR */, Qt::WindowFlags f /* = Qt::WindowFlags() */) : QDialog(parent, f) { QTextCodec* codec = QTextCodec::codecForName("GBK"); setWindowTitle(codec->toUnicode("加法计算器")); m_editX = new QLineEdit(this); m_editY = new QLineEdit(this); m_editZ = new QLineEdit(this); m_btnCalc = new QPushButton("=", this); QHBoxLayout* layout = new QHBoxLayout(); layout->addWidget(m_editX); layout->addWidget(new QLabel("+", this)); layout->addWidget(m_editY); layout->addWidget(m_btnCalc); layout->addWidget(m_editZ); setLayout(layout); connect(m_editX, SIGNAL(textChanged(const QString&)), this, SLOT(enableCalcButton())); connect(m_editY, SIGNAL(textChanged(const QString&)), this, SLOT(enableCalcButton())); connect(m_btnCalc, SIGNAL(clicked()), this, SLOT(calcClicked())); } CalculatorDialog::~CalculatorDialog() { } void CalculatorDialog::enableCalcButton(void) { bool bXOk, bYOk; m_editX->text().toDouble(&bXOk); m_editY->text().toDouble(&bYOk); m_btnCalc->setEnabled((bXOk && bYOk)); } void CalculatorDialog::calcClicked(void) { double res = m_editX->text().toDouble() + m_editY->text().toDouble(); QString str = QString::number(res, 'g', 15); m_editZ->setText(str); }
main.cpp
#include "QtWidgets/QApplication" #include "CalculatorDialog.h" int main(int argc, char* argv[]) { QApplication app(argc, argv); CalculatorDialog dlg; dlg.show(); return app.exec(); }
这样的三个文件编译时会出现如下问题:
1>CalculatorDialog.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall CalculatorDialog::metaObject(void)const " (?metaObject@CalculatorDialog@@UBEPBUQMetaObject@@XZ) 1>CalculatorDialog.obj : error LNK2001: 无法解析的外部符号 "public: virtual void * __thiscall CalculatorDialog::qt_metacast(char const *)" (?qt_metacast@CalculatorDialog@@UAEPAXPBD@Z) 1>CalculatorDialog.obj : error LNK2001: 无法解析的外部符号 "public: virtual int __thiscall CalculatorDialog::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@CalculatorDialog@@UAEHW4Call@QMetaObject@@HPAPAX@Z) 1>..\..\bin\Calculator.exe : fatal error LNK1120: 3 个无法解析的外部命令 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
解决方法:
打开Qt 5.8 32-bit for Desktop(MSVC 2013)命令窗口
cd /d E:\workspace\qt\Calculator
moc CalculatorDialog.h -o moc_CalculatorDialog.cpp
此时会生成moc_CalculatorDialgo.cpp文件,然后把该文件添加到工程,即可编译通过。
注:若CalculatorDialg.h文件发生了修改,则需要重新编译生成moc_CalculatorDialog.cpp文件。
6.使用QtDesigner绘制界面并实现加法计算器
在QtDesigner绘制出如下样式的界面后,保存到Calculator工程下,得到CalculatorDialgo.ui文件
在Qt 5.8 32-bit for Desktop(MSVC 2013)命令窗口中执行下面的命令
uic CalculatorDialog.ui -o ui_CalculatorDialog.h
得到ui_CalculatorDialg.h的文件,内容如下:
/******************************************************************************** ** Form generated from reading UI file 'CalculatorDialog.ui' ** ** Created by: Qt User Interface Compiler version 5.8.0 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_CALCULATORDIALOG_H #define UI_CALCULATORDIALOG_H #include <QtCore/QVariant> #include <QtWidgets/QAction> #include <QtWidgets/QApplication> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QDialog> #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QHeaderView> #include <QtWidgets/QLabel> #include <QtWidgets/QLineEdit> #include <QtWidgets/QPushButton> QT_BEGIN_NAMESPACE class Ui_Dialog { public: QHBoxLayout *horizontalLayout; QLineEdit *m_editX; QLabel *label; QLineEdit *m_editY; QPushButton *m_btnCalc; QLineEdit *m_editZ; void setupUi(QDialog *Dialog) { if (Dialog->objectName().isEmpty()) Dialog->setObjectName(QStringLiteral("Dialog")); Dialog->resize(463, 50); horizontalLayout = new QHBoxLayout(Dialog); horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); m_editX = new QLineEdit(Dialog); m_editX->setObjectName(QStringLiteral("m_editX")); m_editX->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); horizontalLayout->addWidget(m_editX); label = new QLabel(Dialog); label->setObjectName(QStringLiteral("label")); label->setLineWidth(10); label->setTextFormat(Qt::AutoText); label->setWordWrap(true); horizontalLayout->addWidget(label); m_editY = new QLineEdit(Dialog); m_editY->setObjectName(QStringLiteral("m_editY")); m_editY->setAlignment(Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing); horizontalLayout->addWidget(m_editY); m_btnCalc = new QPushButton(Dialog); m_btnCalc->setObjectName(QStringLiteral("m_btnCalc")); m_btnCalc->setEnabled(false); horizontalLayout->addWidget(m_btnCalc); m_editZ = new QLineEdit(Dialog); m_editZ->setObjectName(QStringLiteral("m_editZ")); m_editZ->setReadOnly(true); horizontalLayout->addWidget(m_editZ); retranslateUi(Dialog); QMetaObject::connectSlotsByName(Dialog); } // setupUi void retranslateUi(QDialog *Dialog) { Dialog->setWindowTitle(QApplication::translate("Dialog", "Calculator", Q_NULLPTR)); label->setText(QApplication::translate("Dialog", "+", Q_NULLPTR)); m_btnCalc->setText(QApplication::translate("Dialog", "=", Q_NULLPTR)); } // retranslateUi }; namespace Ui { class Dialog: public Ui_Dialog {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_CALCULATORDIALOG_H
新建一个DesignCalculatorDlg类,源码如下:
DesignCalculatorDlg.h
#pragma once #include "ui_CalculatorDialog.h" class DesignerCalculatorDlg : public QDialog, Ui_Dialog { Q_OBJECT public: DesignerCalculatorDlg(QWidget* parent = NULL); ~DesignerCalculatorDlg(); private slots: void enableCalcButton(void); void calcClicked(void); };
DesignCalulatorDlg.cpp
#include "DesignerCalculatorDlg.h" DesignerCalculatorDlg::DesignerCalculatorDlg(QWidget* parent) :QDialog(parent) { setupUi(this); m_editX->setValidator(new QDoubleValidator(this)); m_editY->setValidator(new QDoubleValidator(this)); connect(m_editX, SIGNAL(textChanged(const QString&)), this, SLOT(enableCalcButton())); connect(m_editY, SIGNAL(textChanged(const QString&)), this, SLOT(enableCalcButton())); connect(m_btnCalc, SIGNAL(clicked()), this, SLOT(calcClicked())); } DesignerCalculatorDlg::~DesignerCalculatorDlg() { } void DesignerCalculatorDlg::enableCalcButton(void) { bool bXOk, bYOk; m_editX->text().toDouble(&bXOk); m_editY->text().toDouble(&bYOk); m_btnCalc->setEnabled((bXOk && bYOk)); } void DesignerCalculatorDlg::calcClicked(void) { double res = m_editX->text().toDouble() + m_editY->text().toDouble(); QString str = QString::number(res, 'g', 15); m_editZ->setText(str); }
随后利用moc生成moc_DesignCalculatorDlg.cpp文件,并加入到工程。
属性->连接器 ->输入->附加依赖项,追加Qt5Gui.lib
这样DesignCalculatorDlg与前面的CalulatorDialog就有相同的功能了。
main.cpp
#include "QtWidgets/QApplication" #include "CalculatorDialog.h" #include "DesignerCalculatorDlg.h" int main(int argc, char* argv[]) { QApplication app(argc, argv); CalculatorDialog dlg; dlg.show(); DesignerCalculatorDlg designedDlg; designedDlg.show(); return app.exec(); }
.字符编码
QTextCodec
eg:显示中文不乱码
QTextCodec* codec = QTextCodec::codecForName("GBK"); QLabel label(codec->toUnicode("中文")); label.show();
.容器
1.QWidgets
绝大多数图形相关的组件都是它的子类
2.QMainWindow
3.QDialog
.布局
1.QLayout
2.QBoxLayout/QHBoxLayout/QVBoxLayout
3.QGrigLayout
.信号与槽
使用说明:
1.一般情况信号和草参数纯虚类型要相同
eg:
QObject::connect(A, SIGNAL(sigFunc(int, string)), B, SLOT(slotFunc(int, string))); // ok QObject::connect(A, SIGNAL(sigFunc(string, int)), B, SLOT(slotFunc(int, string))); // no
2.可以带有缺省参数
eg:
QObject::connect(A, SIGNAL(sigFunc(int)), B, SLOT(slotFunc(int, string=""))); // ok
3.信号函数参数可以多于槽函数参数,多余的参数将被忽略
eg:
QObject::connect(A, SIGNAL(sigFunc(int, string)), B, SLOT(slotFunc(int))); // ok
4.一个信号可以被连接到多个槽函数
eg:
QObject::connect(A, SIGNAL(sigFunc(int)), B1, SLOT(slotFunc(int))); // ok QObject::connect(A, SIGNAL(sigFunc(int)), B2, SLOT(slotFunc(int))); // ok
注:当A发出信号时,B1/B2的槽函数都会被执行,执行顺序不确定
5.多个信号可以连接到同一个槽函数
eg:
QObject::connect(A1, SIGNAL(sigFunc(int)), B, SLOT(slotFunc(int))); // ok QObject::connect(A2, SIGNAL(sigFunc(int)), B, SLOT(slotFunc(int))); // ok
注:无论A1还是A2发出信号,B的槽函数都会被执行