Qt 数字键盘实现,包含标准数字键盘、密码键盘、自定义样式、信号槽机制等功能。
一、项目结构
DigitalKeyboard/
├── main.cpp
├── digitalkeyboard.h
├── digitalkeyboard.cpp
├── passwordkeyboard.h
├── passwordkeyboard.cpp
├── keyboardbutton.h
├── keyboardbutton.cpp
└── styles.qss
二、核心实现代码
2.1 主程序 (main.cpp)
cpp
#include "digitalkeyboard.h"
#include "passwordkeyboard.h"
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 设置应用程序样式
QFile styleFile(":/styles.qss");
if (styleFile.open(QFile::ReadOnly)) {
QString styleSheet = QLatin1String(styleFile.readAll());
a.setStyleSheet(styleSheet);
styleFile.close();
}
// 创建主窗口
QMainWindow mainWindow;
mainWindow.setWindowTitle("Qt 数字键盘示例");
mainWindow.resize(400, 300);
// 创建中央部件
QWidget *centralWidget = new QWidget(&mainWindow);
mainWindow.setCentralWidget(centralWidget);
// 创建输入框
QLineEdit *lineEdit = new QLineEdit(centralWidget);
lineEdit->setPlaceholderText("点击此处输入数字...");
lineEdit->setAlignment(Qt::AlignCenter);
lineEdit->setStyleSheet(
"QLineEdit {"
" border: 2px solid #4A90E2;"
" border-radius: 5px;"
" padding: 8px;"
" font-size: 16px;"
" background-color: white;"
"}"
);
// 创建按钮
QPushButton *normalKeyboardBtn = new QPushButton("打开数字键盘", centralWidget);
QPushButton *passwordKeyboardBtn = new QPushButton("打开密码键盘", centralWidget);
normalKeyboardBtn->setStyleSheet(
"QPushButton {"
" background-color: #4A90E2;"
" color: white;"
" border: none;"
" border-radius: 5px;"
" padding: 10px;"
" font-size: 14px;"
"}"
"QPushButton:hover { background-color: #357ABD; }"
"QPushButton:pressed { background-color: #2868B0; }"
);
passwordKeyboardBtn->setStyleSheet(
"QPushButton {"
" background-color: #7B68EE;"
" color: white;"
" border: none;"
" border-radius: 5px;"
" padding: 10px;"
" font-size: 14px;"
"}"
"QPushButton:hover { background-color: #6A5ACD; }"
"QPushButton:pressed { background-color: #594FB8; }"
);
// 布局
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->addWidget(lineEdit);
layout->addSpacing(20);
layout->addWidget(normalKeyboardBtn);
layout->addWidget(passwordKeyboardBtn);
layout->addStretch();
// 连接信号槽
QObject::connect(normalKeyboardBtn, &QPushButton::clicked, {
DigitalKeyboard *keyboard = new DigitalKeyboard(&mainWindow);
keyboard->setLineEdit(lineEdit);
keyboard->show();
});
QObject::connect(passwordKeyboardBtn, &QPushButton::clicked, {
PasswordKeyboard *keyboard = new PasswordKeyboard(&mainWindow);
keyboard->setLineEdit(lineEdit);
keyboard->show();
});
mainWindow.show();
return a.exec();
}
2.2 数字键盘类 (digitalkeyboard.h)
cpp
#ifndef DIGITALKEYBOARD_H
#define DIGITALKEYBOARD_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QGridLayout>
#include <QSignalMapper>
class DigitalKeyboard : public QWidget
{
Q_OBJECT
public:
explicit DigitalKeyboard(QWidget *parent = nullptr);
~DigitalKeyboard();
void setLineEdit(QLineEdit *lineEdit);
void setMaxLength(int maxLength);
void setDecimalEnabled(bool enabled);
void setNegativeEnabled(bool enabled);
signals:
void numberClicked(const QString &number);
void backspaceClicked();
void enterClicked();
void clearClicked();
private slots:
void onNumberClicked(const QString &number);
void onBackspaceClicked();
void onClearClicked();
void onEnterClicked();
void onDotClicked();
void onSignClicked();
private:
void createButtons();
void setupLayout();
void setupConnections();
QLineEdit *targetLineEdit;
QSignalMapper *signalMapper;
// 按钮
QPushButton *btn0, *btn1, *btn2, *btn3, *btn4, *btn5, *btn6, *btn7, *btn8, *btn9;
QPushButton *btnDot, *btnSign, *btnBackspace, *btnClear, *btnEnter;
QPushButton *btnClose;
// 属性
int maxLength;
bool decimalEnabled;
bool negativeEnabled;
bool hasDecimalPoint;
};
#endif // DIGITALKEYBOARD_H
2.3 数字键盘实现 (digitalkeyboard.cpp)
cpp
#include "digitalkeyboard.h"
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDebug>
DigitalKeyboard::DigitalKeyboard(QWidget *parent)
: QWidget(parent)
{
// 初始化属性
maxLength = 10;
decimalEnabled = true;
negativeEnabled = false;
hasDecimalPoint = false;
// 创建按钮
createButtons();
// 设置布局
setupLayout();
// 连接信号槽
setupConnections();
// 设置窗口属性
setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
setFixedSize(320, 420);
}
DigitalKeyboard::~DigitalKeyboard()
{
}
void DigitalKeyboard::setLineEdit(QLineEdit *lineEdit)
{
targetLineEdit = lineEdit;
}
void DigitalKeyboard::setMaxLength(int maxLength)
{
this->maxLength = maxLength;
}
void DigitalKeyboard::setDecimalEnabled(bool enabled)
{
decimalEnabled = enabled;
btnDot->setEnabled(enabled);
}
void DigitalKeyboard::setNegativeEnabled(bool enabled)
{
negativeEnabled = enabled;
btnSign->setEnabled(enabled);
}
void DigitalKeyboard::createButtons()
{
// 数字按钮
btn0 = new QPushButton("0");
btn1 = new QPushButton("1");
btn2 = new QPushButton("2");
btn3 = new QPushButton("3");
btn4 = new QPushButton("4");
btn5 = new QPushButton("5");
btn6 = new QPushButton("6");
btn7 = new QPushButton("7");
btn8 = new QPushButton("8");
btn9 = new QPushButton("9");
// 功能按钮
btnDot = new QPushButton(".");
btnSign = new QPushButton("+/-");
btnBackspace = new QPushButton("←");
btnClear = new QPushButton("清除");
btnEnter = new QPushButton("确认");
btnClose = new QPushButton("×");
// 设置按钮样式
QString buttonStyle =
"QPushButton {"
" background-color: #F5F5F5;"
" border: 1px solid #CCCCCC;"
" border-radius: 8px;"
" font-size: 18px;"
" font-weight: bold;"
" color: #333333;"
" padding: 15px;"
"}"
"QPushButton:hover {"
" background-color: #E8E8E8;"
"}"
"QPushButton:pressed {"
" background-color: #D8D8D8;"
"}";
QString specialButtonStyle =
"QPushButton {"
" background-color: #4A90E2;"
" border: none;"
" border-radius: 8px;"
" font-size: 16px;"
" font-weight: bold;"
" color: white;"
" padding: 15px;"
"}"
"QPushButton:hover {"
" background-color: #357ABD;"
"}"
"QPushButton:pressed {"
" background-color: #2868B0;"
"}";
QString enterButtonStyle =
"QPushButton {"
" background-color: #5CB85C;"
" border: none;"
" border-radius: 8px;"
" font-size: 18px;"
" font-weight: bold;"
" color: white;"
" padding: 15px;"
"}"
"QPushButton:hover {"
" background-color: #449D44;"
"}"
"QPushButton:pressed {"
" background-color: #398439;"
"}";
// 应用样式
for (auto btn : {btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9}) {
btn->setStyleSheet(buttonStyle);
btn->setFixedSize(70, 70);
}
btnDot->setStyleSheet(buttonStyle);
btnSign->setStyleSheet(buttonStyle);
btnBackspace->setStyleSheet(specialButtonStyle);
btnClear->setStyleSheet(specialButtonStyle);
btnEnter->setStyleSheet(enterButtonStyle);
btnClose->setStyleSheet(
"QPushButton {"
" background-color: transparent;"
" border: none;"
" font-size: 20px;"
" color: #666666;"
"}"
"QPushButton:hover { color: #FF0000; }"
);
btnDot->setFixedSize(70, 70);
btnSign->setFixedSize(70, 70);
btnBackspace->setFixedSize(70, 70);
btnClear->setFixedSize(70, 70);
btnEnter->setFixedSize(150, 70);
btnClose->setFixedSize(40, 40);
}
void DigitalKeyboard::setupLayout()
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(20, 20, 20, 20);
mainLayout->setSpacing(10);
// 顶部栏
QHBoxLayout *topBarLayout = new QHBoxLayout();
topBarLayout->addStretch();
topBarLayout->addWidget(btnClose);
mainLayout->addLayout(topBarLayout);
// 按钮网格
QGridLayout *gridLayout = new QGridLayout();
gridLayout->setSpacing(10);
// 第一行
gridLayout->addWidget(btn7, 0, 0);
gridLayout->addWidget(btn8, 0, 1);
gridLayout->addWidget(btn9, 0, 2);
gridLayout->addWidget(btnBackspace, 0, 3);
// 第二行
gridLayout->addWidget(btn4, 1, 0);
gridLayout->addWidget(btn5, 1, 1);
gridLayout->addWidget(btn6, 1, 2);
gridLayout->addWidget(btnClear, 1, 3);
// 第三行
gridLayout->addWidget(btn1, 2, 0);
gridLayout->addWidget(btn2, 2, 1);
gridLayout->addWidget(btn3, 2, 2);
gridLayout->addWidget(btnSign, 2, 3);
// 第四行
gridLayout->addWidget(btn0, 3, 0);
gridLayout->addWidget(btnDot, 3, 1);
gridLayout->addWidget(btnEnter, 3, 2, 1, 2); // 跨两列
mainLayout->addLayout(gridLayout);
}
void DigitalKeyboard::setupConnections()
{
// 创建信号映射器
signalMapper = new QSignalMapper(this);
// 连接数字按钮
for (auto btn : {btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9}) {
connect(btn, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(btn, btn->text());
}
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(onNumberClicked(QString)));
// 连接功能按钮
connect(btnDot, SIGNAL(clicked()), this, SLOT(onDotClicked()));
connect(btnSign, SIGNAL(clicked()), this, SLOT(onSignClicked()));
connect(btnBackspace, SIGNAL(clicked()), this, SLOT(onBackspaceClicked()));
connect(btnClear, SIGNAL(clicked()), this, SLOT(onClearClicked()));
connect(btnEnter, SIGNAL(clicked()), this, SLOT(onEnterClicked()));
connect(btnClose, SIGNAL(clicked()), this, SLOT(close()));
}
void DigitalKeyboard::onNumberClicked(const QString &number)
{
if (!targetLineEdit) return;
QString currentText = targetLineEdit->text();
// 检查长度限制
if (currentText.length() >= maxLength) {
return;
}
// 如果当前是0,替换而不是追加
if (currentText == "0" && number != ".") {
targetLineEdit->setText(number);
} else {
targetLineEdit->setText(currentText + number);
}
emit numberClicked(number);
}
void DigitalKeyboard::onDotClicked()
{
if (!targetLineEdit || !decimalEnabled) return;
QString currentText = targetLineEdit->text();
// 检查是否已经包含小数点
if (hasDecimalPoint || currentText.contains('.')) {
return;
}
// 如果为空,添加"0."
if (currentText.isEmpty()) {
targetLineEdit->setText("0.");
} else {
targetLineEdit->setText(currentText + ".");
}
hasDecimalPoint = true;
}
void DigitalKeyboard::onSignClicked()
{
if (!targetLineEdit || !negativeEnabled) return;
QString currentText = targetLineEdit->text();
if (currentText.startsWith('-')) {
targetLineEdit->setText(currentText.mid(1)); // 移除负号
} else {
targetLineEdit->setText("-" + currentText); // 添加负号
}
}
void DigitalKeyboard::onBackspaceClicked()
{
if (!targetLineEdit) return;
QString currentText = targetLineEdit->text();
if (currentText.isEmpty()) return;
// 删除最后一个字符
targetLineEdit->setText(currentText.left(currentText.length() - 1));
// 检查是否还有小数点
hasDecimalPoint = currentText.left(currentText.length() - 1).contains('.');
emit backspaceClicked();
}
void DigitalKeyboard::onClearClicked()
{
if (!targetLineEdit) return;
targetLineEdit->clear();
hasDecimalPoint = false;
emit clearClicked();
}
void DigitalKeyboard::onEnterClicked()
{
if (!targetLineEdit) return;
QString currentText = targetLineEdit->text();
// 验证输入
if (currentText.isEmpty()) {
targetLineEdit->setText("0");
} else if (currentText == "." || currentText == "-") {
targetLineEdit->setText("0");
} else if (currentText.endsWith(".")) {
targetLineEdit->setText(currentText + "0");
}
emit enterClicked();
close();
}
2.4 密码键盘类 (passwordkeyboard.h)
cpp
#ifndef PASSWORDKEYBOARD_H
#define PASSWORDKEYBOARD_H
#include "digitalkeyboard.h"
class PasswordKeyboard : public DigitalKeyboard
{
Q_OBJECT
public:
explicit PasswordKeyboard(QWidget *parent = nullptr);
~PasswordKeyboard();
void setPasswordMode(bool passwordMode);
void setMaskCharacter(const QString &maskChar);
private:
bool passwordMode;
QString maskCharacter;
QString actualText;
void updateDisplayText();
};
#endif // PASSWORDKEYBOARD_H
2.5 密码键盘实现 (passwordkeyboard.cpp)
cpp
#include "passwordkeyboard.h"
PasswordKeyboard::PasswordKeyboard(QWidget *parent)
: DigitalKeyboard(parent)
{
passwordMode = true;
maskCharacter = "*";
// 隐藏小数点和符号按钮
setDecimalEnabled(false);
setNegativeEnabled(false);
// 修改确认按钮文本
QPushButton *enterBtn = findChild<QPushButton*>("btnEnter");
if (enterBtn) {
enterBtn->setText("确认");
}
}
PasswordKeyboard::~PasswordKeyboard()
{
}
void PasswordKeyboard::setPasswordMode(bool passwordMode)
{
this->passwordMode = passwordMode;
}
void PasswordKeyboard::setMaskCharacter(const QString &maskChar)
{
maskCharacter = maskChar;
}
void PasswordKeyboard::updateDisplayText()
{
if (!targetLineEdit) return;
if (passwordMode) {
QString maskedText = QString(maskCharacter).repeated(actualText.length());
targetLineEdit->setText(maskedText);
} else {
targetLineEdit->setText(actualText);
}
}
// 重写父类方法
void PasswordKeyboard::onNumberClicked(const QString &number)
{
if (!targetLineEdit) return;
QString currentText = targetLineEdit->text();
if (passwordMode) {
actualText += number;
updateDisplayText();
} else {
DigitalKeyboard::onNumberClicked(number);
}
}
void PasswordKeyboard::onBackspaceClicked()
{
if (!targetLineEdit) return;
if (passwordMode) {
if (!actualText.isEmpty()) {
actualText.chop(1);
updateDisplayText();
}
} else {
DigitalKeyboard::onBackspaceClicked();
}
}
void PasswordKeyboard::onClearClicked()
{
if (!targetLineEdit) return;
if (passwordMode) {
actualText.clear();
updateDisplayText();
} else {
DigitalKeyboard::onClearClicked();
}
}
2.6 自定义按钮类 (keyboardbutton.h)
cpp
#ifndef KEYBOARDBUTTON_H
#define KEYBOARDBUTTON_H
#include <QPushButton>
#include <QPropertyAnimation>
#include <QEasingCurve>
class KeyboardButton : public QPushButton
{
Q_OBJECT
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
public:
explicit KeyboardButton(const QString &text, QWidget *parent = nullptr);
~KeyboardButton();
QColor backgroundColor() const;
void setBackgroundColor(const QColor &color);
void startPressAnimation();
void startReleaseAnimation();
protected:
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
QColor m_backgroundColor;
QPropertyAnimation *m_animation;
bool m_hovered;
};
#endif // KEYBOARDBUTTON_H
2.7 自定义按钮实现 (keyboardbutton.cpp)
cpp
#include "keyboardbutton.h"
#include <QPainter>
#include <QMouseEvent>
KeyboardButton::KeyboardButton(const QString &text, QWidget *parent)
: QPushButton(text, parent)
{
m_backgroundColor = QColor("#F5F5F5");
m_hovered = false;
m_animation = new QPropertyAnimation(this, "backgroundColor");
m_animation->setDuration(150);
m_animation->setEasingCurve(QEasingCurve::OutQuad);
setCursor(Qt::PointingHandCursor);
}
KeyboardButton::~KeyboardButton()
{
delete m_animation;
}
QColor KeyboardButton::backgroundColor() const
{
return m_backgroundColor;
}
void KeyboardButton::setBackgroundColor(const QColor &color)
{
m_backgroundColor = color;
update();
}
void KeyboardButton::startPressAnimation()
{
m_animation->setEndValue(QColor("#D8D8D8"));
m_animation->start();
}
void KeyboardButton::startReleaseAnimation()
{
m_animation->setEndValue(m_hovered ? QColor("#E8E8E8") : QColor("#F5F5F5"));
m_animation->start();
}
void KeyboardButton::enterEvent(QEvent *event)
{
m_hovered = true;
m_animation->setEndValue(QColor("#E8E8E8"));
m_animation->start();
QPushButton::enterEvent(event);
}
void KeyboardButton::leaveEvent(QEvent *event)
{
m_hovered = false;
m_animation->setEndValue(QColor("#F5F5F5"));
m_animation->start();
QPushButton::leaveEvent(event);
}
void KeyboardButton::mousePressEvent(QMouseEvent *event)
{
startPressAnimation();
QPushButton::mousePressEvent(event);
}
void KeyboardButton::mouseReleaseEvent(QMouseEvent *event)
{
startReleaseAnimation();
QPushButton::mouseReleaseEvent(event);
}
void KeyboardButton::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制圆角矩形背景
painter.setBrush(m_backgroundColor);
painter.setPen(Qt::NoPen);
painter.drawRoundedRect(rect(), 8, 8);
// 绘制文字
painter.setPen(QColor("#333333"));
painter.setFont(font());
painter.drawText(rect(), Qt::AlignCenter, text());
}
2.8 样式表 (styles.qss)
css
/* 全局样式 */
QWidget {
font-family: "Microsoft YaHei", "Segoe UI", Arial;
font-size: 14px;
}
/* 数字键盘样式 */
DigitalKeyboard {
background-color: white;
border-radius: 15px;
border: 1px solid #E0E0E0;
}
/* 密码键盘样式 */
PasswordKeyboard {
background-color: white;
border-radius: 15px;
border: 1px solid #E0E0E0;
}
/* 输入框样式 */
QLineEdit {
border: 2px solid #4A90E2;
border-radius: 8px;
padding: 10px;
font-size: 16px;
background-color: white;
}
QLineEdit:focus {
border-color: #357ABD;
outline: none;
}
/* 按钮样式 */
QPushButton {
border-radius: 8px;
padding: 10px;
font-weight: bold;
}
/* 数字按钮 */
QPushButton[objectName^="btn"] {
background-color: #F5F5F5;
border: 1px solid #CCCCCC;
color: #333333;
}
QPushButton[objectName^="btn"]:hover {
background-color: #E8E8E8;
}
QPushButton[objectName^="btn"]:pressed {
background-color: #D8D8D8;
}
/* 功能按钮 */
QPushButton#btnEnter {
background-color: #5CB85C;
color: white;
border: none;
}
QPushButton#btnEnter:hover {
background-color: #449D44;
}
QPushButton#btnClear, QPushButton#btnBackspace {
background-color: #4A90E2;
color: white;
border: none;
}
QPushButton#btnClear:hover, QPushButton#btnBackspace:hover {
background-color: #357ABD;
}
/* 关闭按钮 */
QPushButton#btnClose {
background-color: transparent;
color: #666666;
border: none;
font-size: 20px;
}
QPushButton#btnClose:hover {
color: #FF0000;
}
/* 主窗口样式 */
QMainWindow {
background-color: #F8F9FA;
}
三、CMakeLists.txt
cmake
cmake_minimum_required(VERSION 3.16)
project(DigitalKeyboard LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5 REQUIRED COMPONENTS Widgets)
add_executable(${PROJECT_NAME}
main.cpp
digitalkeyboard.cpp
passwordkeyboard.cpp
keyboardbutton.cpp
styles.qss
)
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
参考代码 QT编写的数字键盘 www.youwenfan.com/contentcsv/115946.html
四、使用说明
4.1 基本用法
cpp
// 创建数字键盘
DigitalKeyboard *keyboard = new DigitalKeyboard(this);
keyboard->setLineEdit(ui->lineEdit);
keyboard->setMaxLength(10);
keyboard->setDecimalEnabled(true);
keyboard->setNegativeEnabled(false);
keyboard->show();
4.2 密码键盘
cpp
// 创建密码键盘
PasswordKeyboard *passwordKeyboard = new PasswordKeyboard(this);
passwordKeyboard->setLineEdit(ui->passwordEdit);
passwordKeyboard->setPasswordMode(true);
passwordKeyboard->setMaskCharacter("*");
passwordKeyboard->show();
4.3 信号槽连接
cpp
// 连接信号
connect(keyboard, &DigitalKeyboard::numberClicked, const QString &number {
qDebug() << "Number clicked:" << number;
});
connect(keyboard, &DigitalKeyboard::enterClicked, {
qDebug() << "Enter clicked";
});
五、功能特点
标准数字键盘 - 0-9数字输入
密码键盘 - 支持密码掩码
小数输入 - 可选小数点
正负号 - 可选负数输入
长度限制 - 限制最大输入长度
动画效果 - 按钮按压动画
自定义样式 - 支持 QSS 样式表
弹出式窗口 - 无边框弹出键盘
信号槽机制 - 完整的事件处理