Qt的MDI中多个子窗口响应一个菜单事件的优雅实现(动态slot)

问题:

用过MFC的人都知道,MDI中,某个菜单或者按钮,在视图中可以添加响应函数,在文档中也可以添加响应函数,在框架中也可以添加它的响应函数,优先级分别是视图、文档、框架,而且MFC自动将消息发给当前激活的视图或者文档。

解决思路:

在Qt中,菜单/按钮的响应是通过信号/槽来实现的,在MDI中,多个视图经常需要响应同一个菜单,且是激活的视图去响应,这有两种处理方法,一 是,由主窗口接收事件再转调用当前激活窗口,二是,通过disconnect/connect动态修改信号槽。第一种方法,当这样的菜单事件比较多时,比 较繁琐;如果多个视图分属不同子类,只要其中一个子类实现了一个处理函数,其他子类都需要添加这样的处理函数(即使啥也不干),另外,在主窗口转调用时, 还需要做类型转换(或者通过虚函数),总而言之,比较复杂。


这里,我按照第二种方法,通过少量代码实现了动态修改信号槽。思路是:

1、自定义一个结构,将connect信息保存起来;

2、当MDI的子窗口焦点切换时,将connect信息中的receiver全部换成当前窗口,并重新connect;


该方法只需要在mainwindow中做这些工作即可,比较简洁优雅。

关键代码粘贴如下

class MainWindow : public QMainWindow
{

    //......

    void dynamic_connect(const QObject * sender, const char * signal, const QObject * receiver, const char * method); void set_dynamic_connect_receiver(const QObject * receiver); //...... struct MdiConnectInfo { MdiConnectInfo(const QObject * sender1, const char * signal1, const QObject * receiver1, const char * method1) { sender = sender1; strcpy(signal,signal1); receiver = receiver1; strcpy(method, method1); } const QObject * sender; char signal[100]; const QObject * receiver; char method[100]; }; std::vector<MdiConnectInfo> m_mdiConnects; }; MainWindow::MainWindow() { //...... connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(onMdiActived())); //...... } void MainWindow::dynamic_connect(const QObject * sender, const char * signal, const QObject * receiver, const char * method) { m_mdiConnects.push_back(MdiConnectInfo(sender, signal, receiver, method)); } void MainWindow::set_dynamic_connect_receiver(const QObject * receiver) { for (int i = 0; i < m_mdiConnects.size(); i++) { MdiConnectInfo item = m_mdiConnects[i]; disconnect(item.sender, item.signal, item.receiver, item.method); } for (int i = 0; i < m_mdiConnects.size(); i++) { MdiConnectInfo item = m_mdiConnects[i]; connect(item.sender, item.signal, receiver, item.method); m_mdiConnects[i].receiver = receiver; } } void MainWindow::onMdiActived() { QWidget* child = activeMdiChild(); if (child) { set_dynamic_connect_receiver(child); } } void MainWindow::createActions() { //......  zoomInAct = new QAction(QIcon(":/images/zoomIn.png"), tr("Zoom In"), this); zoomInAct->setStatusTip(tr("Zoom in view")); dynamic_connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomInView())); zoomOutAct = new QAction(QIcon(":/images/zoomOut.png"), tr("Zoom Out"), this); zoomOutAct->setStatusTip(tr("Zoom out view")); dynamic_connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOutView())); zoomFitAct = new QAction(QIcon(":/images/zoomFit.png"), tr("Zoom Fit"), this); zoomFitAct->setStatusTip(tr("Zoom fit view")); dynamic_connect(zoomFitAct, SIGNAL(triggered()), this, SLOT(zoomFitView())); zoomPanAct = new QAction(QIcon(":/images/zoomPan.png"), tr("Pan Zoom"), this); zoomPanAct->setStatusTip(tr("Pan zoom view")); dynamic_connect(zoomPanAct, SIGNAL(triggered()), this, SLOT(zoomPanView())); //......  }

 

 

作一下解释:

1、通过MdiConnectInfo结构和m_mdiConnects变量,将connect信息保存起来;具体是通过函数dynamic_connect来完成的;

2、当MDI的子窗口焦点切换时,其响应函数onMdiActived()中,将connect信息中的receiver全部换掉,具体是通过 set_dynamic_connect_receiver来完成的;


上述代码运行正常。

 

转载于:https://www.cnblogs.com/zgrpmc/p/5420181.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于Qt应用程序触摸事件的触发问题,可能有几个原因导致触摸事件没有被触发。以下是一些可能的解决方案: 1. 确保触摸设备已正确配置:在某些情况下,触摸设备可能没有正确配置或驱动程序可能需要更新。请确保您的触摸设备已正确安装和配置。 2. 检查事件过滤器:您可能已经在应用程序使用了事件过滤器,并且该过滤器可能会阻止或修改触摸事件的传递。请检查您的代码是否存在这样的过滤器,并确保它们不会影响到触摸事件的传递。 3. 检查触摸事件处理函数:在Qt应用程序,您需要实现相应的事件处理函数来处理触摸事件。例如,在QWidget派生类,您可以实现`void QWidget::touchEvent(QTouchEvent *)`函数来处理触摸事件。请确保您已经正确实现了相应的处理函数。 4. 检查窗口标志:在某些情况下,窗口标志可能会影响到触摸事件的传递。例如,如果窗口标志设置为`Qt::WindowStaysOnTopHint`,则可能会阻止触摸事件传递给下层窗口。请检查您的窗口标志是否可能导致触摸事件无法触发。 5. 检查操作系统和Qt版本:某些操作系统和Qt版本可能存在与触摸事件相关的问题。请确保您使用的操作系统和Qt版本与触摸事件兼容,并查看是否存在已知的问题或修复。 如果以上解决方案不能解决您的问题,我建议您提供更多关于您的应用程序、操作系统和Qt版本的详细信息,以便我可以更好地帮助您解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值