#include "dialogcontrolpassword.h" #include "ui_dialogcontrolpassword.h" #include #include #include #include #include #include #include #include #include #include namespace { const char* kDigitBoxStyleEmpty = "color: rgb(221, 225, 233);" "background-color: rgb(47, 48, 52);" "border: 1px solid rgb(70, 72, 78);" "border-radius: 4px;"; const char* kDigitBoxStyleFilled = "color: rgb(221, 225, 233);" "background-color: rgb(60, 120, 180);" "border: 1px solid rgb(80, 140, 200);" "border-radius: 4px;"; const char* kKeypadButtonStyle = "QPushButton {" " background-color: rgb(47, 48, 52);" " color: rgb(221, 225, 233);" " border: 1px solid rgb(70, 72, 78);" " border-radius: 4px;" "}" "QPushButton:hover {" " background-color: rgb(70, 72, 78);" "}" "QPushButton:pressed {" " background-color: rgb(40, 100, 160);" "}"; QPushButton* MakeKeypadButton(QWidget* parent, const QString& text) { auto* button = new QPushButton(text, parent); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); button->setMinimumSize(90, 72); button->setFocusPolicy(Qt::NoFocus); button->setStyleSheet(QString::fromLatin1(kKeypadButtonStyle)); QFont font = button->font(); font.setPointSize(22); font.setBold(true); button->setFont(font); return button; } } // namespace DialogControlPassword::DialogControlPassword(QWidget* parent) : QDialog(parent) , ui(new Ui::DialogControlPassword) { ui->setupUi(this); setModal(true); setWindowModality(Qt::ApplicationModal); setFixedSize(520, 720); setFocusPolicy(Qt::StrongFocus); if (ui->btnOK) { ui->btnOK->setFocusPolicy(Qt::NoFocus); } if (ui->btnCancel) { ui->btnCancel->setFocusPolicy(Qt::NoFocus); } ApplyUiFont(); if (ui->label_title) { QFont titleFont = ui->label_title->font(); titleFont.setPointSize(20); titleFont.setBold(true); ui->label_title->setFont(titleFont); } BuildDigitBoxes(); BuildKeypad(); UpdateOkEnabled(); } DialogControlPassword::~DialogControlPassword() { delete ui; } void DialogControlPassword::SetTitle(const QString& title) { const QString windowTitle = title.isEmpty() ? QStringLiteral("控制密码") : title; setWindowTitle(windowTitle); if (ui && ui->label_title) { ui->label_title->setText(windowTitle); } } QString DialogControlPassword::Password() const { return m_password; } void DialogControlPassword::SetError(const QString& text) { if (!ui || !ui->label_error) { return; } ui->label_error->setText(text); } void DialogControlPassword::SetPasswordChecker( const std::function& checker) { m_passwordChecker = checker; } void DialogControlPassword::on_btnOK_clicked() { TryAccept(); } void DialogControlPassword::on_btnCancel_clicked() { reject(); } void DialogControlPassword::ApplyUiFont() { QFont font; font.setPointSize(16); setFont(font); const QList widgets = findChildren(); for (QWidget* widget : widgets) { widget->setFont(font); } } void DialogControlPassword::BuildDigitBoxes() { if (!ui || !ui->widget_digits) { return; } auto* layout = new QHBoxLayout(ui->widget_digits); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(10); m_digitLabels.clear(); m_digitLabels.reserve(kPasswordLength); for (int i = 0; i < kPasswordLength; ++i) { auto* digitLabel = new QLabel(ui->widget_digits); digitLabel->setAlignment(Qt::AlignCenter); digitLabel->setMinimumSize(56, 56); QFont digitFont = digitLabel->font(); digitFont.setPointSize(22); digitFont.setBold(true); digitLabel->setFont(digitFont); layout->addWidget(digitLabel); m_digitLabels.append(digitLabel); } RefreshDigits(); } void DialogControlPassword::BuildKeypad() { if (!ui || !ui->widget_keypad) { return; } auto* layout = new QGridLayout(ui->widget_keypad); layout->setContentsMargins(0, 0, 0, 0); layout->setHorizontalSpacing(12); layout->setVerticalSpacing(12); const int keys[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; for (int i = 0; i < 9; ++i) { const int digit = keys[i]; QPushButton* button = MakeKeypadButton( ui->widget_keypad, QString::number(digit)); connect(button, &QPushButton::clicked, this, [this, digit]() { AppendDigit(QChar('0' + digit)); }); layout->addWidget(button, i / 3, i % 3); } QPushButton* backButton = MakeKeypadButton( ui->widget_keypad, QStringLiteral("删除")); connect(backButton, &QPushButton::clicked, this, [this]() { RemoveLastDigit(); }); layout->addWidget(backButton, 3, 0); QPushButton* zeroButton = MakeKeypadButton( ui->widget_keypad, QStringLiteral("0")); connect(zeroButton, &QPushButton::clicked, this, [this]() { AppendDigit(QLatin1Char('0')); }); layout->addWidget(zeroButton, 3, 1); QPushButton* clearButton = MakeKeypadButton( ui->widget_keypad, QStringLiteral("清空")); connect(clearButton, &QPushButton::clicked, this, [this]() { ClearPassword(); }); layout->addWidget(clearButton, 3, 2); } void DialogControlPassword::AppendDigit(QChar digit) { if (!digit.isDigit() || m_password.size() >= kPasswordLength) { return; } m_password.append(digit); SetError(QString()); RefreshDigits(); // 满 6 位后自动校验,正确关闭窗口,错误提示并清空。 if (m_password.size() == kPasswordLength) { QTimer::singleShot(50, this, [this]() { TryAccept(); }); } } void DialogControlPassword::RemoveLastDigit() { if (m_password.isEmpty()) { return; } m_password.chop(1); SetError(QString()); RefreshDigits(); } void DialogControlPassword::ClearPassword() { if (m_password.isEmpty()) { RefreshDigits(); return; } m_password.clear(); RefreshDigits(); } void DialogControlPassword::RefreshDigits() { for (int i = 0; i < m_digitLabels.size(); ++i) { QLabel* digitLabel = m_digitLabels[i]; if (!digitLabel) { continue; } const bool filled = i < m_password.size(); digitLabel->setText(filled ? QStringLiteral("●") : QString()); digitLabel->setStyleSheet(QString::fromLatin1( filled ? kDigitBoxStyleFilled : kDigitBoxStyleEmpty)); } UpdateOkEnabled(); } void DialogControlPassword::UpdateOkEnabled() { if (ui && ui->btnOK) { ui->btnOK->setEnabled(m_password.size() == kPasswordLength); } } void DialogControlPassword::TryAccept() { if (m_password.size() != kPasswordLength) { SetError(QStringLiteral("请输入6位数字密码")); return; } if (m_passwordChecker && !m_passwordChecker(m_password)) { SetError(QStringLiteral("密码错误")); ClearPassword(); return; } accept(); } void DialogControlPassword::showEvent(QShowEvent* event) { QDialog::showEvent(event); ClearPassword(); SetError(QString()); setFocus(); } void DialogControlPassword::keyPressEvent(QKeyEvent* event) { if (!event) { return; } if (event->key() == Qt::Key_Escape) { reject(); return; } if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { on_btnOK_clicked(); return; } if (event->key() == Qt::Key_Backspace) { RemoveLastDigit(); return; } const QString text = event->text(); if (text.size() == 1 && text[0].isDigit()) { AppendDigit(text[0]); return; } QDialog::keyPressEvent(event); }