上一小节已经介绍过应用程序主窗口的主要部件。
这次自己做一个菜单
需要新建一个类,它继承自QWidgetAction类,并且在其中重新实现Create Widget函数
下面一个例子实现这样一个菜单项目:
包含一个标签和一个行编辑器,可以在行编辑器中输入字符串,按下回车键就可以自动将字符串输入到中心部件文本编辑器中。
新建一个myaction项目,基类Qt Widget应用,项目名称为myaction,类名默认为QMainWindow不改动
建好后添加一个新c++文件
myaction.h
#ifndef MYACTION_H
#define MYACTION_H
#include
class QLineEdit; // 前置声明
class MyAction : public QWidgetAction
{
Q_OBJECT
public:
explicit MyAction(QObject *parent = 0);
protected:
// 声明函数,该函数是QWidgetAction类中的虚函数
QWidget* createWidget(QWidget *parent);
signals:
// 新建信号,用于在按下回车键时,将行编辑器中的内容发射出去
void getText(const QString &string);
private slots:
// 新建槽,它用来与行编辑器的按下回车键信号关联
void sendText();
private:
// 定义行编辑器对象的指针
QLineEdit *lineEdit;
};
#endif // MYACTION_H
全是定义方法和槽
下面在到myaction.cpp中
先添加头文件包含:
#include "myaction.h"
#include
#include
#include
然后将MyAction类的构造函数修改如下:
MyAction::MyAction(QObject *parent) :
QWidgetAction(parent)
{
// 创建行编辑器
lineEdit = new QLineEdit;
// 将行编辑器的按下回车键信号与我们的发送文本槽关联
connect(lineEdit, &QLineEdit::returnPressed, this, &MyAction::sendText);
}
在添加createWidget()函数的定义:
QWidget * MyAction::createWidget(QWidget *parent) //创建部件
{
// 这里使用inherits()函数判断父部件是否是菜单或者工具栏
// 如果是,则创建该父部件的子部件,并且返回子部件
// 如果不是,则直接返回0
if(parent->inherits("QMenu") || parent->inherits("QToolBar")){
QSplitter *splitter = new QSplitter(parent);
QLabel *label = new QLabel;
label->setText(tr("插入文本:"));
splitter->addWidget(label);
splitter->addWidget(lineEdit);
return splitter;
}
return 0;
}
当使用该类的对象,并将其添加到一个部件上时,就会自动调用createWidget()函数。
这里先判断这个部件是否是一个菜单或者工具栏,如果不是,直接返回0,不处理。
如果是,就以该部件为父窗口创建了一个分裂器,并在其中添加一个标签和行编辑器,
最后将这个分裂器返回。其中使用的inherits()函数在第7章会讲到。
下面是sendText()函数的定义:
void MyAction::sendText()
{
emit getText(lineEdit->text()); // 发射信号,将行编辑器中的内容发射出去
lineEdit->clear(); // 清空行编辑器中的内容
}
过程:
1 在行编辑器中输入文本
2 按下回车键时,就会激发returnPressed()信号
3 这时就会调用sendText()槽。
4 这里发射了自定义的getText()信号,并将行编辑器中的内容清空。
下面:
双击ui文件,拖入一个text Edit,Crtl+G 栅格化布局
到mainwindow.h中添加一个私有槽的声明:
private slots:
void setText(const QString &string); //向编辑器添加文本
然后在mainwindow.cpp 中添加头文件#include“myaction.h”,
并在MainWindow类的构造函数中添加如下代码:
// 添加菜单并且加入我们的action
MyAction *action = new MyAction;
QMenu *editMenu = ui->menuBar->addMenu(tr("编辑(&E)"));
editMenu->addAction(action);
// 将action的getText()信号和这里的setText()槽进行关联
connect(action, SIGNAL(getText(QString)), this, SLOT(setText(QString)));
按下回车 getText(QString) 发送文本 setText(QString)) 输出打印到 lineEdit文本编辑器上
这个例子中设计了自己的信号和槽,整个过程是这样的:
在行编辑器中输入文本,然后按下回车键,这时行编辑就会发射returnPressed()信号,而这时就调用了我们的sendText()槽,在 sendText()槽中又发射了getText()信号,信号中包含了行编辑器中的文本,接着又会调用setText()槽,在setText()槽中将getText()信号发来的文本输人到文本编辑器中。
这样就完成了按下回车键将行编辑器中的文本输入到中心部件的文本编辑器中的操作。
其实,如果所有部件都是在一个类中,则就可以关联行编辑器的returnPressed()信号到我们的槽中,然后进行操作。
但是,这里是在 MyAction和MainWindow两个类之间进行数据传输,所以使用了自定义信号和槽。可以看到,如果能很好地掌握信号和槽的应用,那么实现几个类之间的数据调用是很简单的。