今天学习Qt中控件相互传值的方法。其中参考了一些网上的意见。今天学习了两种方法。其中一种是利用全局变量;另一种是利用了Qt中的信号和槽机制。当学习signals和slot机制的时候,有一些疑问,在介绍利用signals和slot进行值传递的时候,再说。
练习是这样子,如下两图所示。
第一幅图是主窗体,在画笔宽度文本框和画笔颜色文本框中可以填入宽度和样色值,决定画笔宽度和颜色,然后选择右边的画椭圆,画矩形,画多边形按钮可以画相应的图形,其中画图中,大部分功能是直接在函数中赋值好的,可以创建固定大小的图形。
但是,练习中实现了一个功能,可以改变其中的一个坐标,通过文本框来改变。
也可以单击坐标点按钮,会弹出一个子窗体对话框,如第二个图所示,练习中只实现了X文本框向父窗体传值,其他三个没有实现,以后吧。当在X文本框填入X值后,单击确定按钮,它的值将传向父窗体中未命名的四个文本框的左上角那个,同时显示出来,这时再按画椭圆,画矩形按钮,其中一个坐标将改变,图形也会改变,练习中是改变的宽度值。
下面是主要代码:
首先建立一个工程,创建父窗体,结果如上“简单图形绘制”,然后给坐标点按钮和其他三个按钮添加槽函数,下面是代码,利用全局变量和signals/slot来进行传值。测试的时候可以注释掉其中一种,看看两种是不是都可以。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots://槽函数
void on_CreateEllipse_clicked();//画椭圆
void on_createRect_clicked();//画矩形
void on_createPloygen_clicked();//画多边形
void on_pushButton_clicked();//坐标点槽函数
void receivedata(QString mx);//接收数据槽
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include"ellipse.h"
extern QString sx;//声明的全局变量
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//Ellipse *els = new Ellipse;
//connect(els,SIGNAL(senddata(QString )),this,SLOT(receivedata(QString )));
//connect(els,els->senddata,this,this->receivedata);
//els->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_CreateEllipse_clicked()//画椭圆
{
QString pw;
QString pc;
pw = ui->penWidth->text();//画笔宽度字符串
pc = ui->penColor->text();//画笔颜色字符串
int w;
int c;
w = pw.toInt();//画笔宽度转为整型
c = pc.toInt();//画笔颜色转为整型
QString esx;
esx = sx;
int e;
e = esx.toInt();//从子窗体中接收到的控件变量有QString转为Int
QPen pen;//画笔
pen.setStyle(Qt::DashDotLine);
pen.setWidth(w);//设置画笔宽度
if(c == 7)//颜色可以参考16色值,这里文本框中为7 颜色为红,不填默认为黑,测试而已
{
pen.setBrush(Qt::red);//画笔设为红色
}
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
QGraphicsScene *scene = new QGraphicsScene;
scene->addEllipse(150,150,e,200,pen);//画椭圆,这里动态传人了宽度值,为e,是从子窗体中接收的
ui->graphicsView->setScene(scene);
}
void MainWindow::on_createRect_clicked()//画矩形
{
QString pw;
QString pc;
pw = ui->penWidth->text();
pc = ui->penColor->text();
int w;
int c;
w = pw.toInt();
c = pc.toInt();
QPen pen;
pen.setStyle(Qt::DashDotLine);
pen.setWidth(w);
if(c == 7)
{
pen.setBrush(Qt::red);
}
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
int rc;
rc = ui->x->text().toInt();
QGraphicsScene *scene = new QGraphicsScene;
scene->addRect(100,200,rc,120,pen);//画矩形,这里也动态的传人了宽度值,为e,接收自子窗体。
ui->graphicsView->setScene(scene);
}
void MainWindow::on_createPloygen_clicked()//画多边形
{
QString pw;
QString pc;
pw = ui->penWidth->text();
pc = ui->penColor->text();
int w;
int c;
w = pw.toInt();
c = pc.toInt();
QPen pen;
pen.setStyle(Qt::DashDotLine);
pen.setWidth(w);
if(c == 7)
{
pen.setBrush(Qt::red);
}
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
QGraphicsScene *scene = new QGraphicsScene;
QPolygon polygon;
polygon << QPoint(20, 20);
polygon << QPoint(122, 25);
polygon << QPoint(130, 120);
polygon << QPoint(140, 150);
polygon << QPoint(20, 110);
polygon << QPoint(0, 50);
scene->addPolygon(polygon,pen);//画多边形
ui->graphicsView->setScene(scene);
}
void MainWindow::on_pushButton_clicked()//坐标点按钮槽,单击显示选择坐标对话框
{
Ellipse *els = new Ellipse(this);//构建Ellipse对话框对象
// Ellipse *els = new Ellipse;
connect(els,SIGNAL(senddata(QString )),this,SLOT(receivedata(QString )));//信号链接
els->show();//显示对话框
}
void MainWindow::receivedata(QString )//接收槽
{
ui->x->setText(sx);//显示出接收的值
}
子窗体代码和头文件:
ellipse.h
#ifndef ELLIPSE_H
#define ELLIPSE_H
#include
#include
namespace Ui {
class Ellipse;
}
class Ellipse : public QMainWindow
{
Q_OBJECT
public:
explicit Ellipse(QWidget *parent = 0);
~Ellipse();
signals:
void senddata(QString );//信号,用来向父窗体传值
private slots:
void on_pushButton_clicked();//确定按钮槽
private:
Ui::Ellipse *ui;
};
#endif // ELLIPSE_H
ellipse.cpp
#include "ellipse.h"
#include "ui_ellipse.h"
QString sx;//全局变量,这是利用全局变量进行传值
Ellipse::Ellipse(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Ellipse)
{
ui->setupUi(this);
}
Ellipse::~Ellipse()
{
delete ui;
}
void Ellipse::on_pushButton_clicked()//确定按钮槽
{
emit senddata(ui->Xedit->text());//发送信号
sx = ui->Xedit->text();//全局变量值
qDebug()<<"danji"<//这个是测试用的,可以去掉
}
觉得利用全局变量进行传值还是好理解,也是比较好实现的,只要在两个类中分别声明全局变量就可以了。
先在父窗体中声明一个全局变量: QString extern sx;
然后再在子窗体Ellipse中声明全局变量 QString sx;这样子在子窗体中对全局变量sx的改变就会反应到父窗体中了。
重点说一下利用signals/slot进行值传递实现和个人一些疑问。
把需要的代码重新复制过来了。
1.
#ifndef ELLIPSE_H
#define ELLIPSE_H
#include
#include
namespace Ui {
class Ellipse;
}
class Ellipse : public QMainWindow
{
Q_OBJECT
public:
explicit Ellipse(QWidget *parent = 0);
~Ellipse();
signals:
void senddata(QString );//信号,用来向父窗体传值
private slots:
void on_pushButton_clicked();//确定按钮槽
private:
Ui::Ellipse *ui;
};
#endif // ELLIPSE_H
上面注释的地方,分别声明了信号和槽。信号和槽是关联的,就是说,当确定按钮单击以后,就会发送信号senddata(QString);这个信号是向父窗体传值的,把X文本框中字符串传给父窗体。这里还好理解。
2.
void Ellipse::on_pushButton_clicked()//确定按钮槽
{
emit senddata(ui->Xedit->text());//发送信号
sx = ui->Xedit->text();//全局变量值
qDebug()<<"danji"<<sx;//这个是测试用的,可以去掉
}
如注释,这个简单,就是一单击按钮,发送一个信号,信号的接收者在父窗体中,个人的主要疑问也在父窗体中。
下面是父窗体的解释和自己的疑问.
3.
void receivedata(QString mx);//接收数据槽
上面是一个简单的接收子窗体传过来的值得槽函数。
4.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//Ellipse *els = new Ellipse; ---------@1
//connect(els,SIGNAL(senddata(QString )),this,SLOT(receivedata(QString )));-----@2
//els->show();----@3
}
这里问题是如果我想向平时练习一样只写上@2 一句,想实现信号接收,结果是根本没有反应,如果加上@1 @2 @3,就又构造另一个对话框,也可以实现信号接收,但是单击坐标点弹出来的那个一样的对话框却不行。如果只在这里写上@1 一句为什么弹出的对话框不能接收。
5.
void MainWindow::on_pushButton_clicked()//坐标点按钮槽,单击显示选择坐标对话框
{
Ellipse *els = new Ellipse(this);//构建Ellipse对话框对象------@4
// Ellipse *els = new Ellipse;-------@5
connect(els,SIGNAL(senddata(QString )),this,SLOT(receivedata(QString )));//信号链接-@6
els->show();//显示对话框--------@7
}
接着上面的问题,@4和@5 有什么区别么?如果把上面的@1,@2,@3都去掉,就完全可以实现想要的功能。
如果把这里的@6注释掉,在上一步中只保留@2,信号是一样的,可是不行。不知道为什么?