QT自定义软键盘

效果图:

项目中需要用到软键盘, 最初的时候,打算使用QT自带的软键盘, 但苦于不会QML, 再加上, 项目中的二级界面都是用的模态窗, QT自带软键盘不能输入。

不得已, 打算自己写一个。 好在项目不需要太复杂的输入, 主要是参数这些

先是找到了一个例子

https://blog.csdn.net/wzs250969969/article/details/78418725

大概是这样的

但这个例子我运行的时候, 关闭按钮关不掉, 并且按钮这些都是手写的, 所以没法直观的进行修改, 因此参考了他的核心代码, 写了一个简单的软键盘出来, 并且用到了一些图片, 使得软键盘好看了点

在使用的时候, 只需要在主函数中创建一个对象即可

MyKeyBoard keybord;

MyKeyBoard.h

#ifndef MYKEYBOARD_H
#define MYKEYBOARD_H

#include <QDialog>
#include <QLineEdit>
#include <QMouseEvent>


namespace Ui {
class MyKeyBoard;
}

class MyKeyBoard : public QDialog
{
    Q_OBJECT

public:
    explicit MyKeyBoard(QWidget *parent = nullptr);
    ~MyKeyBoard();

private slots:
    void btn_click(); //按钮被点击事件
    bool eventFilter(QObject *obj, QEvent *e);
private:
    Ui::MyKeyBoard *ui;

    void init(); //初始化, 进行所有按钮的事件绑定

private:
    QLineEdit *currentLineEdit;     //当前焦点的文本框
    QString currentType;            //当前输入法类型
    bool mousePressed;                //是否按下


    int deskWidth; //屏幕宽度高度, 以及自身宽度高度
    int deskHeight;
    int frmWidth;
    int frmHeight;
    int _cur_pos;  //编辑框中, 当前光标的位置
    bool is_exit; //是否要退出 如果是true则表示要退出;
    /*窗口移动*/
protected:
    void mousePressEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
private:
    bool _is_down;
    QPoint _point;
};

#endif // MYKEYBOARD_H

 

MyKeyBoard.cpp

#include "mykeyboard.h"
#include "ui_mykeyboard.h"
#include <QDesktopWidget>
#include <QApplication>
#include <QDebug>
#include <QComboBox>
#include <QKeyEvent>
#include <QFile>
#include <QMouseEvent>


MyKeyBoard::MyKeyBoard(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MyKeyBoard)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); //Qt::WindowStaysOnTopHint |
    ui->btn_move->setAttribute( Qt::WA_TransparentForMouseEvents, true );

    ui->btn_close->setIcon( QIcon(":/image/icon/close.png") );
    ui->btn_move->setIcon( QIcon(":/image/icon/move.png") );
    ui->btn_del->setIcon( QIcon(":/image/icon/backspace.png") );
    ui->btn_enter->setIcon( QIcon(":/image/icon/enter.png") );
    ui->btn_space->setIcon( QIcon(":/image/icon/space.png") );
    ui->btn_clear->setIcon( QIcon(":/image/icon/clear.png") );


    deskWidth =  QApplication::desktop()->width();
    deskHeight = QApplication::desktop()->height();
    frmWidth = this->width();
    frmHeight = this->height();

    is_exit = false;
    init();



}

MyKeyBoard::~MyKeyBoard()
{
    delete ui;
}


/*实现窗口移动*/
void MyKeyBoard::mousePressEvent(QMouseEvent *e)
{
    if(e->button() != Qt::LeftButton)
        return;
    int x = ui->btn_move->x();
    int y = ui->btn_move->y();
    int rx = ui->btn_move->width();
    int ry = ui->btn_move->height();
    int cur_x = e->pos().x();
    int cur_y = e->pos().y();
    if(cur_x>x && cur_y>y && cur_x<rx+x && cur_y<ry+y)
    {
        _is_down = true;
        _point = e->globalPos();
    }

}
void MyKeyBoard::mouseMoveEvent(QMouseEvent *e)
{
    if(_point.isNull())
        return;

    if(_is_down)
    {
        QPoint n_pos = e->globalPos();
        QPoint update_pos = mapToParent(n_pos - _point);
        move(update_pos);
        _point = n_pos;
    }

}
void MyKeyBoard::mouseReleaseEvent(QMouseEvent *)
{
    _is_down = false;
}
/***********/



void MyKeyBoard::btn_click()
{
        QPushButton *btn = (QPushButton *)sender();
        QString objectName = btn->objectName();

        if (objectName == "btn_del")
        {
            if (currentLineEdit != nullptr) //点击删除
            {
                ui->_key_board_input_lineedit->backspace();
                currentLineEdit->setText( ui->_key_board_input_lineedit->text() );  //这里是因为, 点击删除的时候, 有可能是删除了选中的多个文本, 如果也用backspace的话, 会导致2个编辑框文本不一致
            }
        }
        else if (objectName == "btn_close") //点击关闭窗口
        {
            is_exit = true;
            currentLineEdit->setText( ui->_key_board_input_lineedit->text() );
            currentLineEdit->setFocusPolicy(Qt::ClickFocus);
            this->close();
        }
        else if(objectName == "btn_enter") //点击回车
        {
            currentLineEdit->setText( ui->_key_board_input_lineedit->text() );
            QKeyEvent enterkey(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
            QCoreApplication::sendEvent( currentLineEdit, &enterkey );
            this->close();
        }
        else if(objectName == "btn_space")  //按下空格
        {
            if (currentLineEdit != nullptr)
            {
                currentLineEdit->insert(" ");
                ui->_key_board_input_lineedit->insert( " " );
            }
        }
        else if(objectName == "btn_clear") //按下清空
        {
            if (currentLineEdit != nullptr)
            {
                currentLineEdit->setText("");
                ui->_key_board_input_lineedit->setText("");
            }
        }
        else
        {
            QString value = btn->text();
            //当前的焦点是编辑框, 那么就插入一个字符
            if (currentLineEdit != nullptr)
            {
                ui->_key_board_input_lineedit->insert(value);
                currentLineEdit->setText( ui->_key_board_input_lineedit->text() );
                if(ui->_key_board_input_lineedit != nullptr)
                {
                    currentLineEdit->setCursorPosition( ui->_key_board_input_lineedit->cursorPosition() );
                }
            }
        }
}


//这个被放弃了, 现在使用事件过滤器的方式
void MyKeyBoard::focus_changed(QWidget *, QWidget *nowWidget)
{

    if (nowWidget != 0 && !this->isAncestorOf(nowWidget))
    {
        if (nowWidget->inherits("QLineEdit"))
        {
            currentLineEdit = (QLineEdit *)nowWidget;
            QPoint movePoint;

            // 鼠标点击位置坐标
            if (QCursor::pos().y() > deskHeight / 2)
            {
                // 靠上居中显示
                movePoint = QPoint(deskWidth/2 - frmWidth/2, 0);
            }
            else
            {
                // 靠下居中显示
                movePoint = QPoint(deskWidth/2 - frmWidth/2, deskHeight - frmHeight);
            }
            this->move(movePoint);
            this->repaint();

            if(!is_exit)
            {
                this->exec();
            }
            else {
                is_exit = false;
                this->close();
            }
        }
        else if(nowWidget->inherits("QComboBox"))
        {
            currentLineEdit = static_cast<QComboBox *>(nowWidget)->lineEdit() ;

            if(!is_exit)
            {
                is_exit = true;
                this->exec();
            }
            else {
                is_exit = false;
                this->close();
            }
        }
        else
        {
            currentLineEdit = nullptr;
            this->close();

        }
    }


}

bool MyKeyBoard::eventFilter(QObject *obj, QEvent *e)
{

   if(obj->metaObject()->className() == QStringLiteral("QLineEdit"))
   {
       QLineEdit *tmp_edit = static_cast< QLineEdit* >(obj); //第一步判断
       if(tmp_edit->objectName() == "_key_board_input_lineedit") //如果点击的是自己自带的编辑框的话, 那就是要修改光标位置了
       {
           QMouseEvent *mEvent = static_cast< QMouseEvent* >(e);
           if(mEvent->button() == Qt::LeftButton)
           {
                if(tmp_edit != nullptr)
                {
                    _cur_pos = ui->_key_board_input_lineedit->cursorPosition();
                    currentLineEdit->setCursorPosition( _cur_pos );
                }
           }
           return false;
       }


       QLineEdit *edit = static_cast< QLineEdit* >(obj);
       if(e->type() == QEvent::MouseButtonPress && edit->isEnabled())
       {
           currentLineEdit = (QLineEdit *)obj;
           ui->_key_board_input_lineedit->setText( currentLineEdit->text() );
           ui->_key_board_input_lineedit->setCursorPosition( currentLineEdit->cursorPosition() );
           QPoint movePoint = QCursor::pos();
           this->move( movePoint.x(), movePoint.y()+edit->height() );
           this->repaint();
           this->exec();
       }
   }


}

void MyKeyBoard::init()
{
    currentLineEdit = 0;
    mousePressed = false;
    currentType = "min";

    QList<QPushButton *> btn = this->findChildren<QPushButton *>();
    foreach (QPushButton * b, btn) {
        connect(b, SIGNAL(clicked()), this, SLOT(btn_click()));
    }

    qApp->installEventFilter(this);

}

很多代码都是用的上边的参考例子, 修改了布局, 以及模态输入, 和实现逻辑。使用还是很方便的。

这套软键盘的配色也很简单, 只需要几行css即可

#_key_board_input_lineedit{
    border: 1px solid rgb(155,155,155);
    background:rgb(28,29,30);
    border-radius:2px;
    font-size:20px;
    color:rgb(230,230,230);
}
/*软键盘的CSS*/
#MyKeyBoard{
background:rgb(28,29,30);
}


.MyKeyBoard QPushButton{
    border-radius:1px;
    text-align:center;
    background:rgb(48,50,50);
    margin:1px;
    font-size:22px;
    color:rgb(255,255,255);
}
.MyKeyBoard QPushButton:enabled:hover{
    background:rgb(48,50,50);
}
.MyKeyBoard QPushButton:enabled:pressed{
    background:rgb(60,60,60);
}

主要代码全在这里了。 ui文件可以自己对应着拖一个好看的出来

 

 

 

  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 要将自定义软键盘与第三方应用结合起来,您需要实现一个 Input Method(输入法)模块,并在系统中注册。以下是一些一般性的步骤: 1. 实现 Input Method 模块:您需要编写一个 Qt 插件,实现 QInputMethod 接口,并在其中实现自定义键盘的逻辑。 2. 注册 Input Method 模块:将编写的 Input Method 模块注册到系统中。对于 Windows 平台,您可以使用注册表进行注册;对于 Linux 平台,您需要在 /usr/share/ibus/component/ 或 /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/ 中创建相应的文件。 3. 测试 Input Method 模块:在第三方应用程序中测试输入法是否能够正常工作。您可以使用 Qt 提供的输入法测试工具,在命令行中输入 `qinputmethodtest` 启动,然后选择测试应用程序,并测试您的自定义软键盘是否正常工作。 4. 集成 Input Method 模块:在第三方应用程序中启用您的输入法。您可以在应用程序中使用 Qt 提供的输入法接口来管理输入法,例如 `QInputMethod::setEnabled(true)` 来启用输入法,或 `QInputMethod::queryFocusObject()` 来获取当前输入焦点所在的对象。 请注意,对于某些特定的第三方应用程序,您可能需要进行额外的定制化工作,以使您的输入法与其更好地集成。 ### 回答2: QT是一个跨平台的应用程序开发框架,提供了丰富的组件和工具来创建用户界面。在QT中,可以通过自定义软键盘来增强用户输入体验,并且可以与第三方应用结合。 首先,我们可以在QT中创建一个自定义软键盘的窗口,使用QT提供的按钮组件和布局管理器等组件来构建软键盘的界面。可以根据需要自定义按钮的样式和功能,例如数字、字母、符号等。 其次,在第三方应用中,我们可以通过QT提供的槽和信号机制来实现与自定义软键盘的交互。可以在第三方应用的输入框中绑定一个槽函数,用于接收软键盘按钮的点击事件。 然后,在自定义软键盘中,可以通过发送信号的方式将被点击的按钮信息发送到第三方应用中。可以使用QT提供的信号和槽机制,将软键盘按钮的点击事件连接到第三方应用中的槽函数,从而实现与第三方应用的交互。 最后,可以在第三方应用中的槽函数中获取到软键盘按钮的信息,并根据需求将其插入到当前焦点位置的输入框中,从而实现与自定义软键盘的结合。 总之,通过在QT中创建自定义软键盘的界面,并利用QT的信号和槽机制与第三方应用进行交互,可以实现自定义软键盘和第三方应用的结合。这样,用户可以在第三方应用中使用自定义软键盘,提高输入体验和便捷性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值