QT 虚拟键盘问题解决,dialog,模态窗口,无感知

这篇具有很好参考价值的文章主要介绍了QT 虚拟键盘问题解决,dialog,模态窗口,无感知。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目前各个帖子都没有完美解决QT下模态窗口的键盘无响应问题,此帖已解决此问题。

问题原因:原因主要是模态窗口卡住了虚拟键盘的事件响应,导致两者冲突,出现界面假死现象

目前主要解决方案是设置Dialog为非模态窗口,此法属于绕过虚拟键盘问题,模态窗口的作用就没有了,也就没有这个帖子的意义了。

那要怎么解决这个事件无响应,并且不能修改模态窗口的属性呢?

我思索了很久,偶然想起来模态窗口的子控件是完全可以响应事件的,那我们可以在创建虚拟键盘时将模态窗口设置为虚拟键盘的父对象,不就可以了吗?

//如果当前焦点控件的父控件存在模态窗口就将键盘窗口设置为模态窗口的子类

    if(!m_keyboard){
        if(b){
            m_keyboard = new KeyBoard(testParent);
        }else{
            m_keyboard = new KeyBoard();
        }
    }

那么现在又存在两个问题了

一、怎么知道当前控件的上层父控件是模态窗口呢?

二、一个控件的父对象可以一直向上有多个,怎么一直查找呢?

第一个解决方案很简单,通过 QWidget中的windowModality()方法获取窗口模式,判断是否为模态窗口。

第二个我们可以通过递归查找方式来判断,代码如下。

bool isDialogParent(QWidget* _widget)
{
    if(_widget == nullptr){
        return false;
    }
    if(_widget->windowModality() & Qt::ApplicationModal){
        testParent = _widget;
        return true;
    }
    if(_widget->parent() != nullptr){
        auto wid = qobject_cast<QWidget*>(_widget->parent());
        if(wid){
            return isDialogParent(wid);
        }
    }
    return false;
}

经过测试,目前这个没有任何问题。

详细代码如下:

键盘布局文件:

KeyBoard.h

#ifndef KEYBOARD_H
#define KEYBOARD_H

#include <QWidget>
#include <QPushButton>

class KeyBoard : public QWidget
{
    Q_OBJECT

public:
    explicit KeyBoard(QWidget *parent = nullptr);
    ~KeyBoard();
signals:
    void sendKeyToFocusItem(const QString &keytext);
    void _move(int x,int y);
    int _show(bool b);
    void _setInputType(int type);
private:
    QPushButton * btn1 = nullptr;
    QPushButton * btn2 = nullptr;
    QPushButton * btn3 = nullptr;
    QPushButton * btn4 = nullptr;
    QPushButton * btn5 = nullptr;
    QPushButton * btn6 = nullptr;
    QPushButton * btn7 = nullptr;
    QPushButton * btn8 = nullptr;
    QPushButton * btn9 = nullptr;
    QPushButton * btnA = nullptr;
    QPushButton * btnB = nullptr;
    QPushButton * btnC = nullptr;
    QPushButton * btnD = nullptr;
    QPushButton * btnE = nullptr;
    QPushButton * btnF = nullptr;
    QPushButton * btn0 = nullptr;
    QPushButton * btnDel = nullptr;
    QPushButton * btnPoint = nullptr;
};

#endif // KEYBOARD_H

KeyBoard.cpp

#include "KeyBoard.h"
#include <QtDebug>
#include <QGridLayout>

#define BTN_SIZE 60

KeyBoard::KeyBoard(QWidget *parent) :
    QWidget(parent)
{
    //设置主窗体样式
    //this->setAttribute(Qt::WA_TranslucentBackground);
    this->setWindowFlags(Qt::Tool | \
                         Qt::FramelessWindowHint | \
                         Qt::WindowStaysOnTopHint | \
                         Qt::WindowDoesNotAcceptFocus);
    //this->setFixedSize(150,200);
    this->setStyleSheet("QWidget{"
                        "background-color:rgb(25,25,25);"
                        "}"
                        "QPushButton{"
                        "     font:25px;"
                        "     background-color:rgb(49,49,49);"
                        "     color:white;"
                        "     border:2px solid rgb(25,25,25);"
                        "     border-radius:5px;"
                        " }"
                        "QPushButton:hover{"
                        "     background-color:rgb(36,177,213);"
                        "     color:white;"
                        "}"
                        "QPushButton:pressed{"
                        "     color:blue;"
                        "}");
    btn1 = new QPushButton("1",this);btn1->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn2 = new QPushButton("2",this);btn2->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn3 = new QPushButton("3",this);btn3->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn4 = new QPushButton("4",this);btn4->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn5 = new QPushButton("5",this);btn5->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn6 = new QPushButton("6",this);btn6->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn7 = new QPushButton("7",this);btn7->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn8 = new QPushButton("8",this);btn8->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn9 = new QPushButton("9",this);btn9->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnA = new QPushButton("A",this);btn7->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnB = new QPushButton("B",this);btn8->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnC = new QPushButton("C",this);btn9->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnD = new QPushButton("D",this);btn7->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnE = new QPushButton("E",this);btn8->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnF = new QPushButton("F",this);btn9->setFixedSize(BTN_SIZE,BTN_SIZE);
    btn0 = new QPushButton("0",this);btn0->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnDel = new QPushButton(u8"←",this);btnDel->setFixedSize(BTN_SIZE,BTN_SIZE);
    btnPoint = new QPushButton(".",this);btnPoint->setFixedSize(BTN_SIZE,BTN_SIZE);

    auto layout = new QGridLayout(this);
    layout->setSpacing(3);
    layout->setMargin(3);

    layout->addWidget(btn1,0,1);
    layout->addWidget(btn2,0,2);
    layout->addWidget(btn3,0,3);

    layout->addWidget(btn4,1,1);
    layout->addWidget(btn5,1,2);
    layout->addWidget(btn6,1,3);

    layout->addWidget(btn7,2,1);
    layout->addWidget(btn8,2,2);
    layout->addWidget(btn9,2,3);

    layout->addWidget(btnA,3,1);
    layout->addWidget(btnB,3,2);
    layout->addWidget(btnC,3,3);

    layout->addWidget(btnD,4,1);
    layout->addWidget(btnE,4,2);
    layout->addWidget(btnF,4,3);

    layout->addWidget(btnPoint,5,1);
    layout->addWidget(btn0,5,2);
    layout->addWidget(btnDel,5,3);

    connect(btn1,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("1");});
    connect(btn2,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("2");});
    connect(btn3,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("3");});
    connect(btn4,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("4");});
    connect(btn5,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("5");});
    connect(btn6,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("6");});
    connect(btn7,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("7");});
    connect(btn8,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("8");});
    connect(btn9,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("9");});
    connect(btnA,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("A");});
    connect(btnB,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("B");});
    connect(btnC,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("C");});
    connect(btnD,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("D");});
    connect(btnE,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("E");});
    connect(btnF,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("F");});
    connect(btn0,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("0");});
    connect(btnPoint,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem(".");});
    connect(btnDel,&QPushButton::clicked,this,[&](){emit sendKeyToFocusItem("\x7F");});

    connect(this,&KeyBoard::_move,this,[&](int x,int y){
        this->move(x,y);
    });
    connect(this,&KeyBoard::_show,this,[&](bool b){
        if(b){
            this->show();
        }else{
            this->hide();
        }
    });
    //在这里扩展用户输入类型
    connect(this,&KeyBoard::_setInputType,this,[&](int type){
        if(type == 0){
            btnA->setVisible(false);
            btnB->setVisible(false);
            btnC->setVisible(false);
            btnD->setVisible(false);
            btnE->setVisible(false);
            btnF->setVisible(false);
        }else{
            btnA->setVisible(true);
            btnB->setVisible(true);
            btnC->setVisible(true);
            btnD->setVisible(true);
            btnE->setVisible(true);
            btnF->setVisible(true);
        }
    });
}


KeyBoard::~KeyBoard()
{

}

虚拟键盘实现接口文件:

GZH_VirtualKeyBoard.h

#ifndef GZH_VIRTUALKEYBOARD_H
#define GZH_VIRTUALKEYBOARD_H
#include <qpa/qplatforminputcontext.h>
#include "KeyBoard.h"
#include <QThread>

class GZH_VirtualKeyBoard : public QPlatformInputContext
{
    Q_OBJECT
public:
    GZH_VirtualKeyBoard();
    ~GZH_VirtualKeyBoard();

    bool isValid() const Q_DECL_OVERRIDE;
    void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
    void showInputPanel() Q_DECL_OVERRIDE;
    void hideInputPanel() Q_DECL_OVERRIDE;
    bool isInputPanelVisible() const Q_DECL_OVERRIDE;

private:
    void sendKeyToFocusItem(const QString &keytext);

    KeyBoard * m_keyboard = nullptr;
    QObject * m_focusitem = nullptr;
    QWidget * testParent = nullptr;
    bool isDialogParent(QWidget*);
};

#endif // GZH_VIRTUALKEYBOARD_H

GZH_VirtualKeyBoard.cpp

#include "GZH_VirtualKeyBoard.h"
#include <QCoreApplication>
#include <QKeyEvent>
#include <QApplication>
#include <QDesktopWidget>
#include "KeyBoard.h"
#include <QtDebug>


GZH_VirtualKeyBoard::GZH_VirtualKeyBoard()
{

}

GZH_VirtualKeyBoard::~GZH_VirtualKeyBoard()
{
    disconnect(m_keyboard, &KeyBoard::sendKeyToFocusItem, this, &GZH_VirtualKeyBoard::sendKeyToFocusItem);
    if(m_keyboard) delete m_keyboard;
}

void GZH_VirtualKeyBoard::sendKeyToFocusItem(const QString &keytext)
{
    if(!m_focusitem)return;
    
    if(keytext == QString("\x7F"))
    {
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier));
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier));
    }else
    {
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, keytext));
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyRelease, 0, Qt::NoModifier, keytext));
    }
}

bool GZH_VirtualKeyBoard::isValid() const
{
    return true;
}

void GZH_VirtualKeyBoard::setFocusObject(QObject *object)
{
    m_focusitem = object;
}

void GZH_VirtualKeyBoard::showInputPanel()
{
//如果当前焦点控件的父控件存在模态窗口就将键盘窗口设置为模态窗口的子类
    bool b = isDialogParent(qobject_cast<QWidget*>(m_focusitem));
    if(!m_keyboard){
        if(b){
            m_keyboard = new KeyBoard(testParent);
        }else{
            m_keyboard = new KeyBoard();
        }
        connect(m_keyboard, &KeyBoard::sendKeyToFocusItem, this, &GZH_VirtualKeyBoard::sendKeyToFocusItem);
    }
    if(m_keyboard->isHidden())emit m_keyboard->_show(true);
    QWidget *widgetTmp = qobject_cast<QWidget*>(m_focusitem);

    if(widgetTmp){
        QPoint widgetGlobalPos = widgetTmp->mapToGlobal(QPoint(0, 0));
        if(widgetGlobalPos.x() < 0){
            widgetGlobalPos.setX(0);
        }
        if(widgetGlobalPos.y() < 0){
            widgetGlobalPos.setY(0);
        }
        if(qApp->desktop()->width() - widgetGlobalPos.x() < m_keyboard->width()){
            widgetGlobalPos.setX(qApp->desktop()->width() - m_keyboard->width());
        }
        if(qApp->desktop()->height() - widgetGlobalPos.y() - 30 < m_keyboard->height()){
            widgetGlobalPos.setY(widgetGlobalPos.y() - m_keyboard->height() - 10);
        }
        else{
            widgetGlobalPos = widgetGlobalPos + QPoint(0,30);
        }
        emit m_keyboard->_setInputType(widgetTmp->property("bdtype").toInt());
        emit m_keyboard->_move(widgetGlobalPos.x(),widgetGlobalPos.y());
    }
}

void GZH_VirtualKeyBoard::hideInputPanel()
{
    if(!m_keyboard){
        return;
    }
    delete m_keyboard;
    m_keyboard = nullptr;
}

bool GZH_VirtualKeyBoard::isInputPanelVisible() const
{
    return m_keyboard->isVisible();
}
//核心方法,查找当前焦点所在窗口是否为dialog窗口
bool GZH_VirtualKeyBoard::isDialogParent(QWidget* _widget)
{
    if(_widget == nullptr){
        return false;
    }
    if(_widget->windowModality() & Qt::ApplicationModal){
        testParent = _widget;
        return true;
    }
    if(_widget->parent() != nullptr){
        auto wid = qobject_cast<QWidget*>(_widget->parent());
        if(wid){
            return isDialogParent(wid);
        }
    }
    return false;
}

新手使用指导帖子:QT 虚拟键盘使用问题_悟情道长的博客-CSDN博客

完整项目地址:

https://download.csdn.net/download/qq_32854345/87173147?spm=1001.2014.3001.5501

如需要积分,可以联系球球654320149发送文章来源地址https://www.toymoban.com/news/detail-485136.html

到了这里,关于QT 虚拟键盘问题解决,dialog,模态窗口,无感知的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt透明窗口鼠标穿透问题及解决办法

    最近写了个项目,需要播放视频并在视频上做标记框去完成一些功能 因为视频播放使用了 VLC-qt 的库,封装好的窗口控件 没办法直接在该视频窗口上绘图(也许可以?) 出于不想动别人写好的库的想法,想着在视频窗口上加一个透明蒙版-即一个透明窗口,在透明窗口上进行

    2024年02月04日
    浏览(32)
  • [QDialog]qt虚拟键盘的实现以及qdateedit实现打开虚拟键盘

    首先,实现虚拟键盘的拖动功能就需要对QDialog的鼠标事件进行重写,所以就需要自己写一个继承于QDialog的子类。  这里代码参考qt实现窗口拖动的两种思路_肩上风骋的博客-CSDN博客_qt 拖动窗口 这里除了构造函数以外,还需要初始化、读取字符、添加字符、删除字符四个函数

    2024年02月09日
    浏览(44)
  • QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

    一、本自制虚拟键盘特点 1.键盘界面保持在所有界面最上方。 2.点击键盘按钮不会改变底层文本输入框焦点。 3.通过模拟键盘点击事件完成键盘输入文本信息。 4.包含各种键盘自带符号输入。 5.长按按键可以持续重复输入键盘内容。 6.支持win7、win10、Linux等各个系统。 7.界面

    2024年02月09日
    浏览(39)
  • Qt使用星空图作为窗口背景,点击键盘的WASD控制小飞机在上面移动。

    事件函数的使用依托于Qt的事件机制,一个来自于外部事件的传递机制模型如下所示 信号槽虽然好用,但是无法包含所有的情况,事件函数可以起到对信号槽无法覆盖的一些时机进行补充,事件函数的使用无需连接。 常用的事件函数如下所示。 // 绘制事件 void QWidget :: pain

    2024年02月11日
    浏览(31)
  • 在ARM板上实现qt虚拟键盘 Qwidget实现 官方虚拟键盘、第三方虚拟键盘qtvirtualkeyboard //Qwidget最简单但效果不是最好

    在使用qt的虚拟键盘以前,我的开发板qt环境中并没有安装虚拟键盘库,所以这里还会顺便介绍如何在开发板上已安装qt环境的前提下,继续更新qt的组件。 开发板qt版本:5.15.2 在这里,我默认你已经有自己动手交叉编译过qt源码了,否则你将缺少部分细节和前置知识。首先在

    2024年04月09日
    浏览(220)
  • 论文笔记:相似感知的多模态假新闻检测

    论文地址:SAFE   在此之前,对利用新闻文章中文本信息和视觉信息之间的关系(相似性)的关注较少。这种相似性有助于识别虚假新闻,例如,虚假新闻也许会试图使用不相关的图片来吸引读者的注意力。本文提出了一种相似感知的新闻检测方法(SAFE),该方法研究新闻文章的

    2024年02月19日
    浏览(32)
  • 使用van-dialog二次封装微信小程序模态框

    由于微信小程序的wx.showModal不支持富文本内容,无法实现更灵活的展示效果,故需要进行二次封装 实现思路:使用van-dialog以及微信小程序的rich-text实现 代码如下: 使用方法 本文仅提供一种思路,可能不是最优写法,欢迎大家讨论留言

    2024年02月07日
    浏览(34)
  • Android解决Dialog触碰外面不能自动关闭问题

    Android解决Dialog触碰外面不能自动关闭问题,其实也就是解决dialog.setCanceledOnTouchOutside(true) 不生效问题 为什么设置了dialog.setCanceledOnTouchOutside(true) 会不生效呢? 问题根源在styles文件中定义android:windowIsFloating=false导致: android:windowIsFloating 表示Dialog是否浮现在activity之上, 当将

    2024年02月11日
    浏览(24)
  • Qt Windows 去掉标题栏后 最大化窗口时任务栏被窗口遮住问题

    在写Qt窗口时,假如对窗口设置了 Qt::FramelessWindowHint 或者 Qt::CustomizeWindowHint 标志,会发现窗口在副屏上最大化会遮住任务栏。 假如自己实现最大化来解决这个问题,虽然能够解决,但窗口状态就需要自己维护 在Windows中通过拦截窗口消息的方式可以更优雅的解决这个问题 在

    2024年02月05日
    浏览(28)
  • 神经网络入门①多层感知器如何解决异或问题?

    人工智能是最近非常热的一个话题,它的发展将对人类的生产活动产生革命性的影响。 机器学习是实现人工智能的有效手段,深度学习作为机器学习领域中最有潜力的方向,引起了广泛的关注。 感知机(perceptron)早在20世纪50年代就提出来了 1 ,但直到近几年深度学习的崛起

    2024年02月10日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包