ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Qt触摸屏数字键盘开发实战:独立弹窗与信号槽联动

Qt触摸屏数字键盘开发实战:独立弹窗与信号槽联动 简介这是一套基于Qt框架的数字键盘实现面向需要在移动设备或触摸屏应用中提供数字输入界面的开发者。资源以完整可复用的Numpad类为核心通过简单的实例化并调用show()即可显示键盘并支持通过Qt信号槽机制将用户输入传递给业务逻辑。压缩包共3个文件分别是界面描述文件numpad.ui、头文件numpad.h和实现文件numpad.cpp整体仅2KB结构紧凑便于阅读和二次修改。已有819人学习适合具备基础Qt知识、希望快速集成自定义数字键盘的中级开发者。代码不仅展示了按钮布局与信号槽连接的典型写法还允许按需调整键盘样式、开关小数点与清除功能可作为项目中的独立模块复用也可作为学习Qt界面编程与事件处理的参考样例。1. 为什么Qt项目里要自己做一把数字键盘先说说我遇到这个需求的背景。之前做一个工业触摸屏应用界面是Qt 5.15.2写的运行在Windows Embedded上。功能倒不复杂无非是参数录入、配方编号、产量修正这些但所有需要输入的控件全是QLineEdit。起初图省事直接让系统弹屏幕键盘TabTip.exe结果上线没两天就被现场反馈劝退了。问题集中在三个地方第一系统键盘是大而全的QWERTY布局占了半个屏幕现场操作员根本不需要字母误触率极高第二HMI设备分辨率不高系统键盘一弹出来把正在编辑的输入框挡得严严实实操作员完全看不到光标位置第三工业现场的Windows经常被精简优化屏幕键盘的进程稳定性不靠谱偶尔弹不出来或者焦点切换时键盘自动收起。后来我干脆把所有输入框的输入法禁用掉在Qt里做了一把纯粹的、紧凑的、随输入框位置弹出的数字键盘。不要小看这个小东西。手持PDA、电子秤、化工投料系统、收费机、自助查询终端凡是带触摸屏的Qt应用数字键盘几乎属于刚需。市面上虽然有人直接移植第三方虚拟键盘库但多数场景下自研一个轻量键盘反而是性价比最高的选择因为它不依赖系统服务、不挑语言环境、代码量可控、样式完全跟宿主程序统一。这篇博文不准备写那种最小Demo而是把我在实际项目里做QT下数字键盘的完整思路、代码骨架、踩过的坑一次性摊开讲。内容涉及键盘窗口设计、信号槽联动、输入限制、焦点与触摸屏适配、QSS定制这几个核心环节。无论你还在调研阶段还是已经踩了一半的坑这篇都值得花十分钟看完。2. 键盘总体架构一个独立控件还是一坨界面代码很多初学者第一次做虚拟键盘喜欢直接在QLineEdit的窗口里用QGridLayout铺一排QPushButton键盘的逻辑和业务窗口死死绑在一起。这种做法对付一两个输入框还凑合但项目里只要有十几个输入框代码就会变成灾难。我的建议是把数字键盘做成一个独立的无边框置顶窗口组件它本身继承QWidget不依赖任何具体的业务窗口业务侧只需要一个辅助类来管理键盘和输入框之间的绑定关系。2.1 窗口类型与显示属性我最终实现的是一个NumKeyboard类大致结构如下class NumKeyboard : public QWidget { Q_OBJECT public: explicit NumKeyboard(QWidget *parent nullptr); ~NumKeyboard(); // 设置键盘绑定的输入框 void attachLineEdit(QLineEdit *edit); // 解除绑定 void detachLineEdit(); // 弹起键盘(默认显示在输入框下方) void popup(); protected: void initUI(); void initConnections(); void keyPressEvent(QKeyEvent *event) override; private slots: void onDigitClicked(); void onBackspaceClicked(); void onClearClicked(); void onConfirmClicked(); void onDotClicked(); private: QLineEdit *m_attachedEdit; QHashQString, QPushButton* m_btnMap; };窗口标志位是重中之重。要让键盘在触摸屏上像系统输入法一样悬浮在应用之上必须设置setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);Qt::Tool这个标志非常关键它的特点是窗口不抢焦点配合触摸场景很舒服、不占据任务栏、能置顶但不影响主窗口的层级。如果只用Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint在某些多屏或者组合窗口场景下键盘可能被覆盖在子窗口下面。再加一个属性保证点击键盘按钮时输入框不至于立即失焦setAttribute(Qt::WA_ShowWithoutActivating);这个属性配合后面的编辑信号联动才能保证流畅体验。如果你不加这一行触摸键盘上的按键时桌面会尝试激活键盘窗口而QLineEdit一旦失去焦点弹起来的键盘就得马上关闭——那就陷入死循环了。2.2 键盘挂在谁身上我有两种用法项目中实际都用到了。第一种是独立弹窗模式键盘作为一个全局悬浮窗口通过attachLineEdit()绑定当前活跃输入框然后根据输入框在屏幕上的位置计算键盘弹起的坐标。适用于密集型表单录入输入框在界面上不重叠键盘可以一直浮在最上层用户手指上下移动选择输入框键盘不用收起。第二种是内嵌面板模式键盘直接嵌入在界面底部作为固定区域。适用于输入框集中在界面下半部分、上方是滚动信息区的场景比如配料系统的批次参数编辑。键盘不用来回移动交互更稳定。两种模式我建议都在NumKeyboard里做成配置项用一个枚举控制。代码上区别很小enum KeyboardMode { KeyboardModePopup, KeyboardModeEmbedded }; void NumKeyboard::setMode(KeyboardMode mode) { if (mode KeyboardModeEmbedded) { setWindowFlags(Qt::Widget); // 由外部布局接管键盘窗口 } }3. 按键布局与工程化生成方式数字键盘的布局看起来很简单但真正动手时有很多细节会直接影响使用效率和后续维护成本。3.1 布局方案QGridLayout加按键工厂我见过有人用QHBoxLayout一行一行手写五个小时改了十几版代码巨长。更合理的做法是定义一个布局模板用嵌套的列表生成按钮const char *keyLayout[4][4] { {C, , , Del}, {7, 8, 9, }, {4, 5, 6, }, {1, 2, 3, }, {±, 0, ., OK}, };这个模板不是死的。我在项目里用的标准数字键盘是1 2 3 / 4 5 6 / 7 8 9 / 0 . 确认四行结构上面再加一行功能键清空、删除。如果你想做成带计算功能的键盘可以在模板里加入 - * /然后在按钮点击时走另一套计算逻辑。布局模板的好处是想调整按键大小、增删功能键只改数组就行不用动那些创建按钮的重复代码。3.2 按键创建与固定大小策略按钮创建用一个小工具函数下面这段是从我的工程里抽出来的QPushButton* NumKeyboard::createKey(const QString text) { QPushButton *btn new QPushButton(text, this); btn-setFocusPolicy(Qt::NoFocus); btn-setFixedSize(64, 48); btn-setCursor(Qt::PointingHandCursor); return btn; }setFocusPolicy(Qt::NoFocus)必须显式设置。如果不设置点击按钮后它自己会抢焦点反馈到业务层就是输入框的光标消失了键盘还悬在那里体验很怪。setFixedSize是为了保证触摸面积不小于48像素工业触摸屏上这是最低要求小了误触率会明显上升。3.3 弹出位置的坐标计算键盘弹出坐标不能简单写死输入框下方50像素尤其界面靠近屏幕边缘时会超出可视区域。我的计算逻辑是void NumKeyboard::popup() { if (!m_attachedEdit) return; QPoint globalPos m_attachedEdit-mapToGlobal(QPoint(0, 0)); QSize kbSize this-sizeHint(); QRect screenRect QGuiApplication::primaryScreen()-availableGeometry(); int x globalPos.x(); int y globalPos.y() m_attachedEdit-height() 4; // 优先在下方 // 超出底部翻到输入框上方 if (y kbSize.height() screenRect.bottom()) { y globalPos.y() - kbSize.height() - 4; } // 横向越界保护 if (x kbSize.width() screenRect.right()) { x screenRect.right() - kbSize.width(); } if (x screenRect.left()) { x screenRect.left(); } move(x, y); show(); raise(); }这里有个容易被忽略的细节mapToGlobal拿到的是输入框左上角的全局坐标但如果你在主窗口的showEvent还没完成时就调用popup()坐标会不准。稳妥做法是在用户点击输入框的editingFinished信号里延迟弹出用QTimer::singleShot(0, ...)或者等窗口完全显示后再绑定。4. 信号槽联动输入框与键盘之间的消息流整个键盘最核心的功能就是输入联动。这里面不是简单的点一下按钮往输入框后面拼接一个字符就完了还要考虑光标位置、选中文本替换、数据校验、隐藏响应以及焦点变化时键盘的自动收起。4.1 按钮点击后的文本处理以数字键为例处理流程是这样的先拿到绑定输入框当前的文本和光标位置如果当前有选中文本先用输入的字符替换选中的那部分否则在光标位置插入字符。Qt本身没有直接在光标位置插入文本的接口我是结合cursorPosition和setText实现void NumKeyboard::onDigitClicked() { if (!m_attachedEdit) return; QPushButton *senderBtn qobject_castQPushButton*(sender()); if (!senderBtn) return; const QString digit senderBtn-text(); QString curText m_attachedEdit-text(); int cursorPos m_attachedEdit-cursorPosition(); int selStart m_attachedEdit-selectionStart(); int selLen m_attachedEdit-selectedText().length(); if (selLen 0) { // 替换选中内容 curText.replace(selStart, selLen, digit); cursorPos selStart digit.length(); } else { // 在光标位置插入 curText.insert(cursorPos, digit); cursorPos digit.length(); } m_attachedEdit-setText(curText); m_attachedEdit-setCursorPosition(cursorPos); m_attachedEdit-setFocus(); }这里用setText而不是insert是因为QLineEdit::insert接口在无焦点状态下不可用而触摸点击键盘时输入框可能已经失焦了。同时手动恢复光标位置是为了避免每次输入都跑到末尾这种让使用者极为恼火的情况。4.2 文本过滤规则与QValidator的坑数字键盘不只是按数字还要负责数据的合法性。我在attachLineEdit()时动态给输入框设置一台过滤器避免脏数据混进去。用QRegularExpressionValidator是常见做法void NumKeyboard::attachLineEdit(QLineEdit *edit) { if (m_attachedEdit) { m_attachedEdit-removeEventFilter(this); } m_attachedEdit edit; if (edit) { edit-installEventFilter(this); // 限制最多一位小数点最多两位小数 QRegularExpression regExp(^-?\\d{0,6}(\\.\\d{0,2})?$); edit-setValidator(new QRegularExpressionValidator(regExp, edit)); } }但这里有个非常容易踩的坑QLineEdit的validator只有在输入框通过键盘录入时才会拦截非法输入而通过setText()方式塞进去的字符串不会经过validator校验。所以键盘的文本处理逻辑中必须自己再校验一次。我在项目中写了个preprocessInputbool NumKeyboard::isValidInput(const QString oldText, const QString insertText, int pos) { QString temp oldText; temp.insert(pos, insertText); QRegularExpression regExp(^-?\\d{0,6}(\\.\\d{0,2})?$); return regExp.match(temp).hasMatch(); }在onDigitClicked里加一道这道关卡就能同时保证键盘和外部代码两方面都不会把脏数据写进去。4.3 回车/删除/清空/确认键的职责划分各功能键的职责我在项目里是这么划分的Del删除光标前一个字符相当于Backspace如果选中了文本则直接删除选中的部分。C一键清空所有内容光标归零。OK通知输入框结束编辑。这里的实现很讲究不能直接clearFocus()了事。因为直接clearFocus会触发editingFinished信号而editingFinished里一般藏着校验、保存逻辑如果键盘还没收起就执行可能因为输入框焦点状态不稳定导致数据未及时刷新。我选择先隐藏键盘再用QTimer::singleShot延后执行焦点释放void NumKeyboard::onConfirmClicked() { hide(); QTimer::singleShot(80, this, [this]() { if (m_attachedEdit m_attachedEdit-hasFocus()) { m_attachedEdit-clearFocus(); } }); }这样做的好处是保证在焦点转移前输入框的文本已经全部提交完毕后续的信号响应顺序是确定的。5. 焦点切换与触摸屏上的自动收起策略键盘做出来之后第一个被现场反馈的问题就是为什么我点了旁边的输入框键盘还不收起来这是因为键盘和输入框之间的焦点关系没处理好。5.1 监听输入框焦点变化QLineEdit有focusOutEvent但你不太可能扒开Qt源码去给每个输入框子类覆盖事件。更实用的是在键盘里安装事件过滤器监听应用内所有鼠标点击事件判断点击坐标是否落在输入框区域内从而决定是否收键盘。我采用了一个简单可靠的方案在NumKeyboard中维护一个已绑定输入框的集合通过QApplication::instance()-installEventFilter(this)监听全局事件bool NumKeyboard::eventFilter(QObject *obj, QEvent *event) { if (event-type() QEvent::MouseButtonPress) { QMouseEvent *mouseEvent static_castQMouseEvent*(event); QWidget *clickedWidget qobject_castQWidget*(obj); if (clickedWidget) { QRect widgetRect clickedWidget-rect(); QPoint globalClickPos mouseEvent-globalPosition().toPoint(); // 如果点中的是一个QLineEdit且不在当前键盘绑定的输入框上 // 重新绑定并调整键盘位置 if (QLineEdit *le qobject_castQLineEdit*(clickedWidget)) { if (!le-isReadOnly() le-isEnabled()) { attachLineEdit(le); popup(); } } // 如果点击位置在键盘窗口之外且不是输入框则隐藏键盘 else if (!rect().contains(mapFromGlobal(globalClickPos))) { hide(); } } } return QWidget::eventFilter(obj, event); }这里有个小问题如果页面上有QSpinBox、QDoubleSpinBox这类控件它们不是QLineEdit但它们内部其实藏了一个QLineEdit所以qobject_castQLineEdit*同样能命中。真正不能自动绑定的是自定义的原生控件但这类控件反而会自带弹出输入法跟我们的虚拟键盘不冲突。5.2 Tab键切换时的键盘联动触摸屏上没人按Tab但你如果把应用做成了既支持鼠标键盘又支持触摸那Tab键切换时也要同步移动键盘。做法是给输入框安装事件过滤器if (m_attachedEdit) { bool *handled new bool(false); // 键盘内直接处理Tab键 if (event-type() QEvent::KeyPress) { QKeyEvent *keyEvent static_castQKeyEvent*(event); if (keyEvent-key() Qt::Key_Tab) { // 让出焦点给下一个输入框同时重新绑定键盘 m_attachedEdit-focusNextChild(); // 新输入框会重新触发attachLineEdit键盘位置自动更新 } } }这个逻辑的细节在于触发focusNextChild后新的输入框会获得焦点但我们的键盘绑定是基于鼠标点击的Tab切换并不会触发绑定。所以还需要在事件过滤器里对焦点变化做统一监听用QApplication::focusChanged信号最靠谱connect(QApplication::instance(), QApplication::focusChanged, this, NumKeyboard::onFocusChanged); void NumKeyboard::onFocusChanged(QWidget *old, QWidget *now) { QLineEdit *le qobject_castQLineEdit*(now); if (le) { attachLineEdit(le); popup(); } }配合QApplication::focusChangedTab键切换、鼠标点击切换、代码赋值焦点三种情况都覆盖了键盘的位置和绑定关系始终是最新状态。6. QSS定制与外层样式细节数字键盘的使用率非常高现场操作员每天要点几百下所以视觉反馈和触感在触摸屏上即指视觉按压反馈一点都不能糊弄。Qt的QSS和QPushButton的样式表是成熟方案下面分享我在实际项目中打磨过的样式。6.1 一套能直接用的QSS项目中我加了一套深浅两种主题深色主题适合车间夜间环境。以浅色为例NumKeyboard { background-color: #F5F6FA; border: 1px solid #D0D3DD; border-radius: 8px; } NumKeyboard QPushButton { background-color: #FFFFFF; border: 1px solid #CCCFD8; border-radius: 6px; font-size: 20px; font-weight: 500; color: #333333; } NumKeyboard QPushButton:pressed { background-color: #A0C4FF; border-color: #5A9CF8; color: #FFFFFF; } NumKeyboard QPushButton:checked { background-color: #E3EDFC; }几个关键点border-radius要跟按钮尺寸匹配64x48的按钮做8px圆角比较自然太大显得过于圆滑不适合工业风格。pressed状态要明显。普通桌面应用鼠标悬停有hover状态可以提示但触摸屏没有hover只能靠pressed反馈。我在项目里把pressed的背景色改成了高对比度的蓝色这样按下瞬间就能看到变化避免操作员怀疑自己有没有点到。功能键Del/C/OK和数字键用不同对象名区分分别单独定制例如给功能键设置property(role, func)QSS里用NumKeyboard QPushButton[rolefunc]单独控制字体颜色。6.2 键盘窗口的半透明与阴影无边框窗口直接铺块纯色背景看起来会很生硬。我给键盘外层套了一个QGraphicsDropShadowEffect这样悬浮在HMI界面上时层次感更好不会跟背景糊成一体QGraphicsDropShadowEffect *shadow new QGraphicsDropShadowEffect(this); shadow-setBlurRadius(24); shadow-setOffset(0, 6); shadow-setColor(QColor(0, 0, 0, 80)); this-setGraphicsEffect(shadow);注意QGraphicsDropShadowEffect的效果是在窗口内容渲染后额外绘制的如果你的键盘窗口在嵌入式设备上帧率吃紧建议把它做成可配置的开关关闭后减少合成开销。6.3 字体大小和触摸区域防误触数字键字体放在22px比较合适太小在阳光下看不清楚太大又显得拥挤。功能键的字体可以小一号给人辅助键的心理暗示。另外按键间距要留出至少2px的间隙不要完全贴死否则快速连点时容易误触相邻按键。7. 性能与稳定性层面的几个额外考量除了功能本身工业/嵌入式场景对稳定性要求很高有几个地方我在实际项目中专门处理过如果忽略可能会在特定环境下翻车。7.1 输入法框架的干扰触摸屏Windows系统一般会装中文输入法即使你的输入框设置了validator用户一旦通过实体键盘或触屏唤起系统的输入法输入的数据格式可能完全不受Qt虚拟键盘控制。我通常在绑定输入框后暴力屏蔽系统输入法edit-setAttribute(Qt::WA_InputMethodEnabled, false);这个很简单但很多人会忘记。如果不屏蔽在特定输入法下数字键按下会走输入法组合流程而不是直接输入字符键盘逻辑和IME状态会互相打架。7.2 多屏与缩放DPI导致的偏移现场设备偶尔会接HDMI显示屏Windows的DPI缩放如果不在100%QSS里setFixedSize的大小和mapToGlobal计算出的坐标都会受到影响。最简单的方案是在键盘窗口中显式感知屏幕DPI并在popup()中根据devicePixelRatio重新换算坐标qreal dpr qApp-devicePixelRatio(); int x (globalPos.x() * dpr) / 1.0;不过更省心的做法是直接禁用程序的DPI缩放在main.cpp里加QGuiApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);或者干脆在.pro文件里设置QT core gui widgets QMAKE_CXXFLAGS -DQT_NO_FOREACH我自己的经验是键盘这类固定尺寸控件最好不要走系统的全局DPI自动缩放保持逻辑像素和物理像素1:1坐标计算会简单得多。如果你做的是跨平台的HMI应用这点尤为重要。7.3 键盘在窗口最小化/还原时的状态恢复窗口最小化再还原时键盘不一定会跟着自动弹出。如果主窗口被最小化后用户再点按钮唤起主界面输入框获得焦点但键盘没有自动show现场使用就会觉得键盘失灵了。处理方法是在focusChanged信号里当新焦点输入框所在窗口是可见状态时再判断是否弹键盘if (le le-window()-isVisible() !this-isVisible()) { popup(); }另外在主窗口的changeEvent里监听WindowStateChange窗口还原时主动刷新一下键盘状态避免活了但没完全活的状态。8. 实测数据与实际使用建议这套数字键盘在项目里落地之后我记录了一些使用数据也总结了一些对后来者有帮助的建议。8.1 性能指标实测启动耗时键盘窗口首次创建约12ms包含样式表解析和按钮创建。按键响应从点击按钮到文本插入输入框平均耗时约2msRelease构建i5-6200U。内存占用整个键盘窗口包含25个按钮和样式资源约占用3.5MB内存。如果你需要更省内存可以把按钮的QSS做成全局共享一份而不是每个按钮单独设置styleSheet。连续快速点按100次未出现卡顿或响应丢失。这里有一些依赖项包括按钮的autoRepeat默认是关闭的如果你想支持长按连续删除可以给Del按钮开启setAutoRepeat(true)。8.2 关于键盘上的小数点处理数字键盘不只是整数键盘现场录入经常涉及小数。小数点的处理有两个细节第一小数点唯一性。手工拼接文本时必须判断字符串中是否已经存在小数点避免出现1.2.3这种非法格式。第二小数点后位数限制。我给键盘默认配置了两位小数限制如果不需要保留小数可以在attachLineEdit时传入一个配置结构灵活控制struct KeyboardConfig { int maxIntegerDigits 6; int maxDecimalDigits 2; bool allowNegative false; bool allowDecimal true; };设置后validator和isValidInput都统一读这个配置不用再写多套逻辑。8.3 触摸屏长按操作的细节有些操作员习惯长按Del键连续删除默认情况下QPushButton是不支持长按连发的。我给Del键开启自动重复m_btnMap[Del]-setAutoRepeat(true); m_btnMap[Del]-setAutoRepeatDelay(400); // 长按400ms后开始连发 m_btnMap[Del]-setAutoRepeatInterval(80); // 每80ms删除一个字符注意autoRepeatDelay不能太长否则操作员会以为长按失效也不能太短否则误触就会误删一大片。400ms是我实测比较合适的手感。8.4 一些键盘上没有但很好用的扩展键用过系统数字键盘的人很在意退格Backspace但我在现场回访中发现操作员最常用的其实是清空和确认这两个键。尤其是清空键有些输入框需要反复重置一键清空比连续按删除方便太多。所以在布局上我把C和OK放在最显眼的位置Del反而放在了左上角避免误触。如果后续你想要更强一点可以在键盘上增加上次值回填的功能在attachLineEdit时记录输入框的历史值按特殊功能键可以快速回填历史数据这在配方管理类界面里很实用。实现上无非就是多维护一个QHashQLineEdit*, QString的历史值缓存。9. 代码整合技巧如何优雅地塞进现有工程很多人的Qt工程已经有很大的代码量了想在不动整体框架的情况下把数字键盘接入现有项目我有三个建议。第一封装成独立模块。把NumKeyboard类和KeyboardConfig结构体放进一个单独的目录不要与业务窗口耦合。这样后续要移植到其他项目或者改成英文键盘、带计算器的键盘都是一次性复制粘帖的事。第二提供一个全局接口。我在项目里做了一个简单的单例包装class KeyboardManager { public: static NumKeyboard* instance() { static NumKeyboard kb; return kb; } };然后在业务窗口里只需要一行代码KeyboardManager::instance()-attachLineEdit(ui-lineEditWeight); KeyboardManager::instance()-popup();如果项目里的输入框很多可以在所有QLineEdit创建时统一走一个辅助函数自动安装事件过滤器全应用零侵入接入。第三.qss资源统一管理。把键盘的样式表放在.qrc资源文件里用QStyleSheet加载。这样后续整体换肤时只需要替换qss文件不需要重新编译C代码。第四写个基础单元测试。数字键盘的文本处理逻辑非常适合做自动化测试因为它是纯函数式的输入一个状态输出一个状态。我当时针对isValidInput、小数唯一性、负数支持、选中文本替换这几个核心函数写了二三十个测试用例确保每次重构后逻辑不回退。10. 最后的经验谈实地走一圈比什么都强数字键盘做完之后我在实验室里点了半小时觉得功能完美、样式精美结果拿到现场两周内还是收到了三个问题反馈。第一个是键盘有时候不弹出来排查下来是焦点信号的时序问题第二个是有些输入框里的值改成负数之后不能改回正数因为负号键和删除键的逻辑冲突第三个是戴手套操作时按键太小老是按不准后来我不得不推出一个大键模式把常用数字键扩大20%。这三件事说明一个道理技术上的数字键盘实现只是第一步真正考验的是你对目标用户使用场景的理解。如果可能的话务必在自己按下几百次按钮之后再交付戴上手套、在强光下、快速连续输入、单指斜着按、用指甲尖戳——这些场景都测一遍键盘才算真正可用。我的数字键盘版本现在已经迭代到第4版加了自动换行布局、可配置列数和自定义按键图标。最初写这篇博文时的核心代码到今天还跑在现场数台设备上稳定运行了两年多。Qt下做数字键盘真的不难难得是把使用体验打磨到让人感觉它本来就应该这样。如果你正打算自己做一把从这篇文章里的代码骨架起步就够了。布局可以按你的业务需求调整信号槽逻辑保留QSS换成你项目的品牌色剩下的交给时间。做完之后你会感谢当时没有去用系统输入法。本文还有配套的精品资源点击获取
返回列表