zoukankan      html  css  js  c++  java
  • QSignalMapper的使用和使用场景

    QSignalMapper的使用和使用场景

    QSignalMapper类收集了一系列的无参信号,然后使用相对于信号发送者来说的整数、字符串或控件参数来重新发送它们。(一开始没读懂没关系,看完就懂了)

    常见场景

    其实,该类的一个典型的使用场合是,大量控件都要相应槽函数,而这些槽函数的实现又大致相同。这种情况下,最直接的办法就是仍然为每一个控件的相应信号创建一个槽函数。但这会导致代码的大量重复。此时,我们就可以使用QSignalMapper来实现这种需求。

    1. QSignalMapper类支持使用setMapping()函数将一个特定的整数或字符串和一个特定的对象关联起来。

    void QSignalMapper::setMapping

    1. 可以将对象的信号(比如button的clicked)连接到QSignalMapper对象的map()槽函数上,而map()槽函数又会使用与对象相关联的整数或字符串来发送mapped()信号。

    2. 所以,我们只要将我们定义的一个槽函数连接到mapped()信号,即可处理大量相似控件的槽函数。

    我们以一个例子来说明。其界面如下:(例子来自csdn第二篇文章,稍微的补充修改)

    请仔细看补充的注释。将会对应上面写的三条。
    初始化界面的代码如下:

    void Widget::InitUi()
    {
        names << "宋江" << "卢俊义" << "吴用" << "公孙胜"
              << "关胜" << "林冲" << "秦明" << "呼延灼"
              << "花荣" << "柴进" << "李应" << "朱仝"
              << "鲁智深" << "武松" << "董平" << "张清";
        QGridLayout *gridLayout = new QGridLayout;
        for (int i = 0; i < names.size(); ++i)
        {
            QPushButton *button = new QPushButton(names[i]);
            // 使用setMapping()函数将一个特定的整数或字符串或对象(qt doc截图那些)和一个特定的对象关联起来。
            signalMapper->setMapping(button, names[i]);
            // 这就是可以将对象的信号连接到QSignalMapper对象的map()槽函数上
            connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
            gridLayout->addWidget(button, i / 4, i % 4);
        }
        // 将我们定义的槽函数连接到mapped()信号 // 注意看mapped的写法
        connect(signalMapper, SIGNAL(mapped(QString)),this, SLOT(ShowName(QString)));
        setLayout(gridLayout);
    }
    

    其中,names是一个私有的QStringList变量,存储每一个按钮上的文本内容。ShowName()是我们定义的一个槽函数,我们就是让所有按钮的clicked()信号都连接到这个槽函数。在窗口类中声明如下:

    public slots:
        void ShowName(QString name);
     
    private:
        void InitUi();
     
    private:
        Ui::Widget *ui;
        QSignalMapper* signalMapper;
        QStringList names;
    

    ShowName()槽函数的实现如下,简单的弹出一个消息框,显示当前点击的按钮的文本内容:

    void Widget::ShowName(QString name)
    {
        QMessageBox::information(this, "Name", name);
    }
    

    当然,别忘了在构造函数中,调用我们的初始化界面的方法,以及实例化我们的signalMapper对象。如下:

    ui->setupUi(this);
        signalMapper = new QSignalMapper(this);
        InitUi();
    

    下面是参考。可看可不看

    这篇写的不错,搬运为Markdown了 可以看一下

    QSignalMapper类可以看成是信号的翻译和转发器。
    它可以把一个无参的信号翻译成带int参数、QString参数、 QObject* 参数或者QWidget *参数的信号,并将之转发。
    QSignalMapper类的功能核心是要建立一个从原始信号的object到需要的数据的映射(setMapper函数)。 map()作为QSignalMapper的一个槽函数,将根据setMapping规则转发mapped()信号。
    QSignalMapper可将多个有类似处理方式signal用一个slot实现,相当于将N个一对一映射通过集中转换成多对一映射。

    例子:有一堆button,可以把clicked()事件放在一个函数里进行处理,只要给button编个号或者给button起个名字就行,这样就不用给每个button写一个slot函数了,方便很多。

    //mywidget.h
    class MyWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit MyWidget(QWidget *parent = 0);
    
    signals:
    
    public slots:
        //处理最终信号的槽
        void doClicked(const QString &btnName);
    
    private:
        QSignalMapper *signalMapper;
    
    };
    
    
    //mywidget.cpp
    MyWidget::MyWidget(QWidget *parent) :
        QWidget(parent)
    {
        QString buttonText = "btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn10";
        QStringList textList = buttonText.split(",");
        signalMapper = new QSignalMapper(this);
        QGridLayout *gridLayout = new QGridLayout;
    
        for(int i=0; i<textList.size(); ++i)
        {
            //动态创建按钮
            QPushButton *button = new QPushButton(textList[i]);
    
            //原始信号传递给signalMapper
            connect(button,SIGNAL(clicked()),signalMapper,SLOT(map()));
            //设置signalMapper的转发规则,转发为参数为QString类型的信号,并把textList[i]的内容作为实参传递
            signalMapper->setMapping(button, textList[i]);
    
            gridLayout->addWidget(button, i/3, i%3);
        }
    
        //将转发的信号连接到最终的槽函数上
        connect(signalMapper,SIGNAL(mapped(QString)),this,SLOT(doClicked(QString)));
    
        setLayout(gridLayout);
    }
    
    void MyWidget::doClicked(const QString &btnName)
    {
        //显示被按下的button名称
        QMessageBox::information(this,"Clicked",btnName+" is clicked !");
    }
    
    

    例子说明:
    首先把原始不带参数的信号连接到signalMapper的map()槽函数,这样signalMapper能在第一时间接收到原始信号;
    其次调用setMapper方法建立映射关系,告诉signalMapper怎样处理原始信号。这个例子是把原始信号转化为一个带QString参数的信号;
    最后接收转化后的带参数信号,这里把转化后的信号与槽函数连接,在槽函数中获得需要数据

    映射关系可以通过removeMappings()移除;
    setMapping函数的参数只有四种,并且要严格按照格式写入,第一种const QString&,第二种int,第三种QObject*,第四种QWidget *,对于后两种,需要的是他们的子类,则在信号处理的函数里进行类型转化.

    参考

    https://doc.qt.io/qt-5/qsignalmapper.html#details

    https://blog.csdn.net/Amnes1a/article/details/70050788

    https://blog.csdn.net/u011125673/article/details/51218196

    https://blog.csdn.net/Amnes1a/article/details/70050788

  • 相关阅读:
    A2-02-15.DML-MySQL RIGHT JOIN
    A2-02-14.DML- MySQL LEFT JOIN
    A2-02-13.DML- MySQL INNER JOIN
    NHibernate N+1问题实例分析和优化
    怎么创建移动页面应用程序
    .NET开发时让人头痛的SESSION超时
    WCF服务编程——数据契约快速入门
    数据模型类对比,用反射做个快乐的程序员
    javascript常见数据集
    provider:命名管道提供程序,error:40
  • 原文地址:https://www.cnblogs.com/__tudou__/p/11586454.html
Copyright © 2011-2022 走看看