Qt : 信号与槽连接的优化.
程序员文章站
2024-01-02 12:46:58
...
包括我在内,很多的初学者在连接信号与槽的时候,都是使用一个信号对应一个槽函数.像下面这样:
m_firstButton = new QPushButton("first",this);
m_secondButton = new QPushButton("second",this);
connect(m_firstButton, SIGNAL(clicked()), this, SLOT(firstButtonSlot()));
connect(m_secondButton, SIGNAL(clicked()), this, SLOT(secondButtonSlot()));
小练习还好,但是项目一旦稍微大了一点后,发现如果要一一对应的话要写的槽函数不是太多了吗…因为用户的每一个操作,都会触发事件来发出信号.
那么在Qt中是否有什么好办法来减少槽函数的使用呢..至少减少了代码量,看起来篇幅没有那么的夸张.好在QObject中还有着sender()方法来获取发送这个信号的对象.这样就可以获取这个对象,然后进行判断.
m_firstButton = new QPushButton("first",this);
m_secondButton = new QPushButton("second",this);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(m_firstButton);
layout->addWidget(m_secondButton);
connect(m_firstButton, SIGNAL(clicked()), this, SLOT(buttonClickedSlot()));
connect(m_secondButton, SIGNAL(clicked()), this, SLOT(buttonClickedSlot()));
void c::buttonClickedSlot()
{
//获取发出信号的对象.
auto button = qobject_cast<QPushButton*>(this->sender());
//对对象进行判断.
if (button == m_firstButton)
qDebug() << "firstButtonClicked";
else if (button == m_secondButton)
qDebug() << "secondButtonClicked";
}
用上面的方法就可以明确到底是哪个对象发出的信号.但是连接信号与槽的方式除了上述情况外,还有别的方式:比如用信号去连接信号.但如果是这样的话,还可以这样用吗???
经过调试后发现:这样的话是达不到我们原先的目的的,这样无法区分到底是谁发出的信号…因为不管哪个按钮被点击,最后发出信号去调用槽函数的都是m_firstButton这个控件.所以这样是不行的.
//还可以用信号去连接一个信号.
connect(m_firstButton, SIGNAL(clicked()), this, SLOT(buttonClickedSlot()));
connect(m_secondButton, SIGNAL(clicked()), m_firstButton, SIGNAL(clicked()));
void c::buttonClickedSlot()
{
auto button = qobject_cast<QPushButton*>(this->sender());
if (button == m_firstButton)
qDebug() << "firstButtonClicked";
else if (button == m_secondButton)
qDebug() << "secondButtonClicked";
}
除此之外,经常会发生这样的事情…我们怎么样用代码去模拟用户的操作呢?比如说:我们想要用代码去实现用户点击这个按钮的操作.
原来在设计类的时候,就为用户定制好了这样的方法.如QPushButton中:
//这样相当于用户点击和按下了按钮.
m_firstButton->click();
m_firstButton->toggle();
//下面是QPushButton对于手动发出信号的方法.可右键查看头文件中找到.和信号是一一对应的.这样也减少了很多的问题.
public Q_SLOTS:
void setIconSize(const QSize &size);
void animateClick(int msec = 100);
void click();
void toggle();
void setChecked(bool);