Qt学习之对话框与主窗口的创建
Qt中的信号与槽机制
qt中槽和普通的C++成员函数几乎是一样的--可以是虚函数,可以被重载,可以是共有的,保护的或者私有的。
槽可以和信号连接在一起,在这种情况下,每当发射这个信号的信号,就会自动调用这个槽
connect语句:connect(sende, SIGNAL(signal), receiver, SLOT(slot)
这里的sender和receiver是指向QObject的指针,signal和slot是不带参数的函数名,实际上SIGNAL和SLOT宏会把他们的参数转换成相应的字符串
注意:
一个信号可以连接多个槽
connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int)));
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(updateStatusBarIndicator(int)));
多个信号可以链接同一个槽
connect(lcd, SIGNAL(overflow)), this, SLOT(handleMathError()));
connect(calculator, SIGNAL(divisionByZero)), this, SLOT(handleMathError()));
一个信号可以与另外一个信号相连接
connect(lineEdit, SIGNAL(textChanged(const QString&)), this, SIGNAL(updateRecord(const QString&)));
Qt的元对象系统机制
元对象系统机制工作原理:
1. Q_OBJECT宏声明了在每一个QObject子类必须实现一些内省函数:metaObject(), tr(), qt_metacall(),以及其他一些函数
2. Qt的moc工具生成了用于由Q_OBJECT声明的所有函数和信号的实现
3. 向connect()和disconnect()这样的QObject的成员函数使用这些内省函数来完成他们的工作
用C++代码实现简单对话框
头文件:findDialog.h
#ifndef FINDDIALOG_H #define FINDDIALOG_H
#include <QLabel> #include <QDialog> class QCheckBox; //class QLabel; class QLineEdit; class QPushButton; class FindDialog : public QDialog { Q_OBJECT public: //construct function FindDialog(QWidget *parent = 0); signals: void findNext(const QString &str, Qt::CaseSensitivity cs); void findPrevious(const QString &str, Qt::CaseSensitivity cs); private slots: void findCliked(); void enabledFindButton(const QString &text); private: QLabel *label; QCheckBox *caseCheckBox; QCheckBox *backwardCheckBox; QPushButton *findButton; QPushButton *closeButton; QLineEdit *lineEdit; };实现文件findDialog.cpp
#include <QtGui> #include <QHBoxLayout> #include <QVBoxLayout> #include <QCheckBox> #include <QLineEdit> #include <QPushButton> #include <QMessageBox> #include "finddialog.h" FindDialog::FindDialog(QWidget *parent) :QDialog(parent) { label = new QLabel(tr("Find &what:")); lineEdit = new QLineEdit; label->setBuddy(lineEdit); caseCheckBox = new QCheckBox(tr("Match &case")); backwardCheckBox = new QCheckBox(tr("Search &backword")); findButton = new QPushButton(tr("&Find")); findButton->setDefault(true); findButton->setEnabled(false); closeButton = new QPushButton(tr("&Clase"));
//链接信号与槽 connect(lineEdit, SIGNAL(textChanged(const QString)), this, SLOT(enabledFindButton(const QString&))); connect(findButton, SIGNAL(clicked()), this, SLOT(findCliked())); connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); //set 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); //Adds a stretchable space (a QSpacerItem) with zero minimum size //and stretch factor stretch to the end of this box layout. rightLayout->addStretch(); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addLayout(leftLayout); mainLayout->addLayout(rightLayout); //set the dialog's main layout setLayout(mainLayout); //设置主对话框的布局 setWindowTitle("Find"); //设置对话框的标题 setFixedHeight(sizeHint().height()); } //实现槽 void FindDialog::findCliked() { QMessageBox msgBox; msgBox.setText(tr("find successfully!")); msgBox.exec(); 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::enabledFindButton(const QString &text) { findButton->setEnabled(!text.isEmpty()); }
创建主窗口
主窗口是构建应用程序用户界面的框架,其中包括菜单,工具栏以及应用程序所需的对话框。那么该如何实现这些功能呢?子类化QMainWindow(继承MainWindow)
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: void closeEvent(QCloseEvent *event); private slots: void newFile(); void open(); bool save(); bool saveAs(); void find(); void goToCell(); void sort(); void about(); void openRecentFile(); void updateStatusBar(); void spreadsheetModified();
......
};实现代码
MainWindow::MainWindow() { spreadsheet = new Spreadsheet; setCentralWidget(spreadsheet); createActions(); //创建各个动作 createMenus(); //创建菜单 createContextMenu(); //创建内容菜单 createToolBars(); //创建工具栏 createStatusBar(); //创建状态栏 readSettings(); //读取配置 findDialog = 0; setWindowIcon(QIcon(":/images/icon.png")); setCurrentFile(""); } void MainWindow::closeEvent(QCloseEvent *event) { if (okToContinue()) { writeSettings(); event->accept(); } else { event->ignore(); } }
......
图形用户界面(GUI)应用程序通常会使用图片,在Qt使用图片的方法
1. 把图片保存到文件中,并且在运行时载入他们
2. 把XPM文件包含在源代码中
3. 使用Qt的资源机制 (RESOURCE = app_name.qrc)
app_name.qrc:
<RCC> <qresource> <file>images/icon.png</file> <file>images/new.png</file> <file>images/open.png</file> <file>images/save.png</file> <file>images/cut.png</file> <file>images/copy.png</file> <file>images/paste.png</file> <file>images/find.png</file> <file>images/gotocell.png</file> </qresource> </RCC>
创建菜单和工具栏
Qt通过"动作"的概念简化了有关菜单和工具栏的编程。一个Action可以添加到任意数量的菜单和工具栏上的像。实现步骤:
1. 创建并且设置动作
2. 创建菜单栏并且把动作添加的菜单上
3. 创建工具栏并且把动作添加到工具栏
void MainWindow::createActions() { newAction = new QAction(tr("&New"), this); //实现创建新文件的动作 newAction->setIcon(QIcon(":/images/new.png")); newAction->setShortcut(QKeySequence::New); newAction->setStatusTip(tr("Create a new spreadsheet file")); connect(newAction, SIGNAL(triggered()), this, SLOT(newFile())); openAction = new QAction(tr("&Open..."), this); //实现打开文件的动作 openAction->setIcon(QIcon(":/images/open.png")); openAction->setShortcut(QKeySequence::Open); openAction->setStatusTip(tr("Open an existing spreadsheet file")); connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
.........
创建菜单
void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(newAction); fileMenu->addAction(openAction); fileMenu->addAction(saveAction); fileMenu->addAction(saveAsAction); separatorAction = fileMenu->addSeparator(); for (int i = 0; i < MaxRecentFiles; ++i) fileMenu->addAction(recentFileActions[i]); fileMenu->addSeparator(); fileMenu->addAction(exitAction); editMenu = menuBar()->addMenu(tr("&Edit")); editMenu->addAction(cutAction); editMenu->addAction(copyAction); editMenu->addAction(pasteAction); editMenu->addAction(deleteAction);
.............设置上下文菜单和工具栏
void MainWindow::createContextMenu() { spreadsheet->addAction(cutAction); spreadsheet->addAction(copyAction); spreadsheet->addAction(pasteAction); spreadsheet->setContextMenuPolicy(Qt::ActionsContextMenu); } void MainWindow::createToolBars() { fileToolBar = addToolBar(tr("&File")); fileToolBar->addAction(newAction); fileToolBar->addAction(openAction); fileToolBar->addAction(saveAction); editToolBar = addToolBar(tr("&Edit")); editToolBar->addAction(cutAction); editToolBar->addAction(copyAction); editToolBar->addAction(pasteAction); editToolBar->addSeparator(); editToolBar->addAction(findAction); editToolBar->addAction(goToCellAction); }
设置状态栏
void MainWindow::createStatusBar() { locationLabel = new QLabel(" W999 "); locationLabel->setAlignment(Qt::AlignHCenter); locationLabel->setMinimumSize(locationLabel->sizeHint()); formulaLabel = new QLabel; formulaLabel->setIndent(3); statusBar()->addWidget(locationLabel); statusBar()->addWidget(formulaLabel, 1); connect(spreadsheet, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(updateStatusBar())); connect(spreadsheet, SIGNAL(modified()), this, SLOT(spreadsheetModified())); updateStatusBar(); }
附上以上实现的简单图形界面程序(Spreadsheet)