关于QLineEdit自定义范围
Qt中有很多种情况比如输入用户名输入名称等功能要用到QLineEdit如果想设置指定的范围比如说关于名称常用的可输入配置为支持中文、英文、数字、特殊符号 - 长度不超过64字符。在我目前的Qt5.9.6版本中无法通过简单的正则和方法直接完成。因为关于特殊符号我无论怎么设置都可以输入 。 、 【 】等这些英文和中文的符号于是我考虑到另一个方法自定义QLineEdit重新实现它的KeyPressEvent事件。代码如下/***************.h文件****************/ #include QLineEdit #include QKeyEvent class MyLineEdit : public QLineEdit { Q_OBJECT public: explicit MyLineEdit(QWidget *parent nullptr) : QLineEdit(parent) {} protected: // 重写键盘按下事件 void keyPressEvent(QKeyEvent *event) override; }; /***************.cpp文件****************/ #include your_header.h // 包含你的头文件 void MyLineEdit::keyPressEvent(QKeyEvent *event) { // 1. 先放行所有的控制键比如退格键删除、CtrlC/V、方向键移动光标等 // 如果不放行这些你的输入框将无法删除内容也无法使用快捷键 if (event-key() Qt::Key_Backspace || event-key() Qt::Key_Delete || event-key() Qt::Key_Left || event-key() Qt::Key_Right || (event-modifiers() Qt::ControlModifier)) { QLineEdit::keyPressEvent(event); return; } // 2. 获取当前按下的文本 QString text event-text(); // 如果文本为空比如按下了 Shift、Alt 等不产生字符的键直接放行 if (text.isEmpty()) { QLineEdit::keyPressEvent(event); return; } // 3. 提取第一个字符进行白名单判断 QChar ch text.at(0); // 白名单规则 // ch.isDigit() - 数字 (0-9) // ch.isLetter() - 英文字母 (a-z, A-Z) // (ch 0x4e00 ch 0x9fa5) - 常用中文字符 Unicode 范围 // ch - - 特殊符号连字符 bool isAllowed ch.isDigit() || ch.isLetter() || (ch 0x4e00 ch 0x9fa5) || ch -; // 4. 如果是允许的字符就交给 QLineEdit 正常处理否则直接拦截不调用父类方法 if (isAllowed) { QLineEdit::keyPressEvent(event); } // 如果不允许比如输入了 这里什么都不做就相当于把这次按键吞掉了 }代码完成后我发现确实英文键盘的情况已经满足我的需求了特殊符号也仅能输入-了但是切到中文输入法后仍然有问题中文的任意符号是可以输入的通过打断点发现在有输入法的时候qt处理不会进入该事件。查阅资料后得知当用输入法打字时按下键盘这个事件并没有直接变成字符塞进QLineEdit而是先被操作系统和Qt的输入法框架(Input Method Framework)给“劫持”了。完整流程如下1. 按下键盘- 产生QKeyEvent(此时进入KeyPressEvent)2. 输入法拦截了这个事件把它转换成拼音或候选词(进入了输入法编辑状态)3. 在输入法里选好了字或符号 比如选中了一个中文逗号4. 输入法框架会生成一个专门的QInputMethodEvent输入法事件直接把最终的字符塞进你的输入框里。所以中文符号和汉字是没有经过KeyPressEvent白名单安检而是走了InputMethodEvent这条通道。所以我们需要再重写一个InputMethodEvent函数用和白名单完全一样的逻辑处理输入法提交的字符。因此在原有类中加入以下代码#include QInputMethodEvent // 在你的 .h 文件中声明 protected: void inputMethodEvent(QInputMethodEvent *event) override* // 在你的 .cpp 文件中实现 void MyLineEdit::inputMethodEvent(QInputMethodEvent *event) { // 获取输入法最终要提交上屏的文本比如你选的中文逗号 QString commitText event-commitString(); // 如果输入法提交了文本我们就进行拦截检查 if (!commitText.isEmpty()) { // 遍历提交的每一个字符防止一次性粘贴或输入多个符号 for (QChar ch : commitText) { bool isDigitOrLetter ch.isDigit() || ch.isLetter(); bool isChineseChar (ch 0x4e00 ch 0x9fa5); bool isHyphen (ch -); // 拦截全角符号中文符号 bool isFullWidthSymbol (ch 0xFF00 ch 0xFFEF); // 只要发现有一个字符不符合白名单或者是全角符号就直接把整个事件忽略掉 if (!((isDigitOrLetter || isChineseChar || isHyphen) !isFullWidthSymbol)) { event-ignore(); // 拒绝这次输入法提交 return; } } } // 如果检查通过或者输入法只是在打出拼音commitString为空就正常放行 QLineEdit::inputMethodEvent(event); }这样就完成了一个专属于名称输入的控件。