QSignalMapper和原始Sender()

5

我在表格中有许多QComboBox。为了知道哪个被触发,我重新映射信号以编码表格单元格位置(如Selecting QComboBox in QTableWidget所述)。

(为什么Qt不先发送单元格激活信号,这样您就可以使用与任何其他单元格编辑相同的当前行/列机制,我不知道。)

但是,这会删除所有原始发送器小部件的信息。在插槽中调用QComboBox* combo = (QComboBox*)sender()将失败,可能是因为sender()现在是QSignalMapper

我可以使用编码的行/列来查找表格窗口小部件中的QComboBox,但这似乎是错误的。是否有更正确的方法呢?

例如:

// in table creator
_signalMapper = new QSignalMapper(this);

 // for each cell
    QComboBox* combo = new QComboBox();
    connect(combo, SIGNAL(currentIndexChanged(int)), _signalMapper, SLOT(map()));
    _signalMapper->setMapping(combo, row);

   // and finally       
   connect(_signalMapper, SIGNAL(mapped(int)),this, SLOT(changedType(int)));

 // slot
 void myDlg::changedType(int row)
 {      
        QComboBox* combo = (QComboBox* )sender(); // this doesn't work !!
 }

编辑:为了以后的搜索,这里有一本新书《高级Qt编程》由Mark Summerfield撰写,详细解释了如何做这种事情。

2个回答

9
为什么不直接将QComboBox的信号连接到您的槽函数呢?
QComboBox *combo = ...
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(changedType(int)));

然后在您的插槽中,您可以使用sender()方法检索已更改的QComboBox。

void myDlg::changedType(int row)
{
    QComboBox *combo = qobject_cast<QComboBox *> sender();

    if(combo != 0){
        // rest of code
    }
}

或者,您可以使用QSignalMapper方法,只需要更改您的槽以使用您设置的映射:

void myDlg::changedType(int row)
{
    QComboBox *combo = qobject_cast<QComboBox *>(_signalMapper->mapping(row));

    if(combo != 0){
        // rest of code
    }
}        

第二个例子是我推荐的做法。我想象映射函数被包含在QSignalMapper类中,就像这种情况一样。 - Caleb Huitt - cjhuitt
因为这样我就可以得到指向实际下拉框的指针 - 但是我不知道它在哪个表格单元格中,所以我不知道要更改哪条记录。 - Martin Beckett

0

我不确定确切的答案,但也许你应该使用:QComboBox* combo = qobject_cast(sender()) 而不是 QComboBox* combo = (QComboBox* )sender()。像这样:


 QObject* obj = sender();
 QComboBox* combo = qobject_cast<QComboBox*>(obj);
 if(combo)
 {
  doSomethingWithCombo(combo);
 }
 else
 {
  // obj 不是 QComboBox 实例
 }

但也许 QSignalMapper 真正替代了真实的发送者...


如果我没记错,qobject_cast与常规转换执行的操作相同,只是它具有一些内部检查。 - Martin Beckett
2
至少,如果存在类型不匹配(指定类型!=请求类型),此转换将返回0。 - cybevnm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接