Qt弹出式窗口、Qt::popup闪退问题、设置窗口无焦点问题

需求

根据业务需求,在输入框(QlineEdit)下面做一个模糊查找的弹窗(PopupWidget),当鼠标点击弹窗以外的地方时,这个窗口关闭,当光标在输入框重新输入内容时,再次弹框。

实现方法

方法一
在网上查找到的方法;设置窗口标志位:

setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);

此方法可以达到弹出式窗口的效果,但是出现了一个致命的问题,但我再次show()这个窗口时(popupWidget),程序会闪退,网上找了很久才找到解决办法。
重写popupWidget的closeEvent()函数:


void PopupWidget::closeEvent(QCloseEvent *event)
{
    event->ignore();
    this->hide();
}
 

这里我只是在鼠标点击PopupWidget窗口以外的地方时,把这个窗口隐藏起来。

方法二
安装事件过滤器,捕捉鼠标点击事件,发出信号,在PopupWidget注册该信号,关闭窗口。
这种方法不推荐。虽然可以到达想要的效果,但是比较繁琐,你需要在每个窗口都重写eventFillter()函数或者重写keyPressedEvent()事件,特别是在一个界面比较复杂,子窗口比较多的情况下,会相当繁琐,所以这不是一个明智的选择。

具体实现省略…

方法三
为什么会有方法三呢? 其实在第一个方法已经完全可以实现弹出式窗口的效果了,由于我需要在股票symbol输入框输入内容时,(公司做的是一个股票期货的客户端)弹出模糊查找的结果,但是在弹框出现后,symbol输入框失去焦点,当你再次点击输入框想要重新获得焦点时,弹框又隐藏起来了。
这里想要达成的效果是:弹框出现后,焦点一直都在symbol输入框内,模糊查找返回的弹框也要实现一个弹出式窗口的效果。
在这里插入图片描述这个是富途牛牛的效果。

解决焦点不在symbol输入框的问题:

1、让弹框始终没有焦点

    this->setFocusPolicy(Qt::NoFocus);//方法无效。

另外说一下,要给一个窗口设置焦点前,得先让它是一个活跃窗口

    this->activateWindow();
    this->setFocus(); //单单这句是无效的

设置窗口无焦点:

 this->setAttribute(Qt::WA_ShowWithoutActivating);//Show the widget without making it active.
 this->setAttribute(Qt::WA_X11DoNotAcceptFocus);//对非X11平台不生效

以上方法都试过了,都没有效果。
猜测可能是由于设置了setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);此窗口是一个弹出式窗口,所以无效。

2、去掉setWindowFlags(Qt::Popup),让PopupWidget为一个普通窗口,并设置

this->setAttribute(Qt::WA_ShowWithoutActivating);/

果然,窗口弹出之后,焦点还是在symbol输入框内。

既然PopupWidget是一个普通窗口,那我要怎样实现弹窗的效果呢?

自定义QlineEdit控件,重写焦点事件:

 void focusInEvent(QFocusEvent *event) override;
 void focusOutEvent(QFocusEvent *event) override;
void MySymbolLineEdit::focusInEvent(QFocusEvent *event) 
{
 	QLineEdit::focusInEvent(event);
    emit focusInSignal();
}
void MySymbolLineEdit::focusOutEvent(QFocusEvent *event) 
{
	QLineEdit::focusOutEvent(event);
    emit focuaOutSignal();
}

然后再PopupWidget注册信号槽就可以实现弹框效果了。

  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
当将弹出窗口设置为`Qt::WindowStaysOnTopHint`(始终置顶)时,可能会导致QComboBox无法正常弹出。这是因为`Qt::WindowStaysOnTopHint`属性使得弹出窗口始终位于其他窗口之上,包括QComboBox的下拉菜单。 解决这个问题的一种方法是,在需要使用`Qt::WindowStaysOnTopHint`属性的弹出窗口中,临时禁用该属性,以允许QComboBox的下拉菜单正常弹出。当下拉菜单关闭后,再恢复弹出窗口的`Qt::WindowStaysOnTopHint`属性。 以下是一个示例代码: ```cpp // 创建弹出窗口 QDialog* popupDialog = new QDialog(parent); popupDialog->setWindowFlags(Qt::WindowStaysOnTopHint); // 创建QComboBox QComboBox* comboBox = new QComboBox(parent); // 当下拉菜单要弹出时,禁用弹出窗口Qt::WindowStaysOnTopHint属性 QObject::connect(comboBox, QOverload<int>::of(&QComboBox::activated), [=](int index) { popupDialog->setWindowFlags(popupDialog->windowFlags() & ~Qt::WindowStaysOnTopHint); popupDialog->show(); // 延迟一段时间后恢复弹出窗口Qt::WindowStaysOnTopHint属性 QTimer::singleShot(100, [=]() { popupDialog->setWindowFlags(popupDialog->windowFlags() | Qt::WindowStaysOnTopHint); popupDialog->show(); }); }); // 后续代码... ``` 在上述示例中,我们通过连接QComboBox的`activated`信号,当下拉菜单要弹出时,临时禁用弹出窗口的`Qt::WindowStaysOnTopHint`属性,并在一定延迟后恢复该属性。这样,在用户点击QComboBox以弹出下拉菜单时,弹出窗口将不会遮挡QComboBox的下拉菜单。 请注意,这只是一种解决方案,并不是通用的解决方法。具体实现可能需要根据您的应用程序需求进行调整和修改。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值