当前位置:嗨网首页>书籍在线阅读

14-利用信号与槽实现交互操作

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

6.2.5 利用信号与槽实现交互操作

前面设计的QWDialogLocate对话框与主窗口之间的交互采用互相引用的方式,实现起来比较复杂。另外一种实现方式就是利用Qt的信号与槽机制,设计相应的信号和槽,将信号与槽关联起来,在进行某个操作时发射信号,槽函数自动响应。

对MainWindow和QWDialogLocate稍作修改,采用信号与槽机制实现交互操作。

下面是MainWindow类定义中与此相关的定义,包括两个槽函数和一个信号。

class MainWindow : public QMainWindow
{
public slots:
   void   setACellText(int row, int column, QString &text);//设置单元格内容
   void   setActLocateEnable(bool enable);//设置actTab_Locate的enabled属性
signals:
   void   cellIndexChanged(int rowNo, int colNo);//当前单元格发生变化
};

两个槽函数是对话框操作主窗口时,主窗口作出的响应。信号是主窗口上tableView的当前单元格发生变化时发射的一个信号,以便对话框作出响应。

下面是两个槽函数的实现,以及tableView的clicked()信号的槽函数里发射自定义信号的代码,代码中都无须引用对话框对象。

void MainWindow::setACellText(int row, int column, QString &text)
{//定位到单元格,并设置字符串
   QModelIndex index=theModel->index(row,column);//获取模型索引
   theSelection->clearSelection();
   theSelection->setCurrentIndex(index,QItemSelectionModel::Select); 
   theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
}
void MainWindow::setActLocateEnable(bool enable)
{ //设置actTab_Locate的enabled属性
   ui->actTab_Locate->setEnabled(enable);
}
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{//单击单元格时发射信号,传递单元格的行号、列号
   emit cellIndexChanged(index.row(),index.column());
}

在主窗口上,“定位单元格”按钮的响应代码与前面有较大的差别。

void MainWindow::on_actTab_Locate_triggered()
{//创建 StayOnTop的对话框,对话框关闭时自动删除
   QWDialogLocate *dlgLocate = new QWDialogLocate(this); 
   dlgLocate->setAttribute(Qt::WA_DeleteOnClose); 
   Qt::WindowFlags   flags=dlgLocate->windowFlags(); 
   dlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); 
   dlgLocate->setSpinRange(theModel->rowCount(),theModel->columnCount());
   QModelIndex curIndex=theSelection->currentIndex();
   if (curIndex.isValid())
      dlgLocate->setSpinValue(curIndex.row(),curIndex.column());
//对话框发射信号,设置单元格文字
   connect(dlgLocate,SIGNAL(changeCellText(int,int,QString&)),
                 this,SLOT(setACellText(int,int,QString&)));
//对话框发射信号,设置actTab_Locate的属性
   connect(dlgLocate,SIGNAL(changeActionEnable(bool)),
                 this,SLOT(setActLocateEnable(bool)));
//主窗口发射信号,修改对话框上的spinBox的值   
   connect(this,SIGNAL(cellIndexChanged(int,int)),
                 dlgLocate,SLOT(setSpinValue(int,int)));
   dlgLocate->show(); //非模态显示对话框
}

在这里,对话框变量声明为了局部变量,不再需要在主窗口类里保存对话框的指针。这段代码的关键是设置了3对信号与槽的关联。

在QWDialogLocate类定义中,与信号和槽相关的定义如下。

class QWDialogLocate : public QDialog
{
private:
   void   closeEvent(QCloseEvent *event);
   void   showEvent(QShowEvent *event);
private slots:
   void   on_btnSetText_clicked();
public slots:
   void   setSpinValue(int rowNo, int colNo); 
signals:
   void   changeCellText(int row, int column, QString &text);
   void   changeActionEnable(bool en); 
};

QWDialogLocate自定义了一个槽函数和两个信号,还增加了showEvent()事件的处理,用于对话框显示时发射信号使主窗口的actTab_Locate失效。这些槽函数,以及发射信号的实现代码如下,代码中没有出现对主窗口的引用。

void QWDialogLocate::closeEvent(QCloseEvent *event)
{ //窗口关闭事件, 发射信号使 actTab_Locate 能用
   emit changeActionEnable(true);
}
void QWDialogLocate::showEvent(QShowEvent *event)
{//窗口显示事件, 发射信号使 actTab_Locate 不能用
   emit changeActionEnable(false);
}
void QWDialogLocate::setSpinValue(int rowNo, int colNo)
{//响应主窗口信号,更新spinBox的值
   ui->spinBoxRow->setValue(rowNo);
   ui->spinBoxColumn->setValue(colNo);
}
void QWDialogLocate::on_btnSetText_clicked()
{//发射信号,定位到单元格并设置字符串
   int row=ui->spinBoxRow->value(); //行号
   int col=ui->spinBoxColumn->value();//列号
   QString text=ui->edtCaption->text();//文字
   emit changeCellText(row,col,text);//发射信号
   if (ui->chkBoxRow->isChecked()) //行增
      ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());
   if (ui->chkBoxColumn->isChecked()) //列增
      ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
}

经过这样修改后的程序,能实现与前面的实例完全相同的主窗口与对话框交互的功能,但是与前面互相引用的方式不同,这里使用Qt的信号与槽的机制,无须获取对方的指针,程序结构上更简单一些。