#include "numkeydia.h" #include "ui_numkeydia.h" #include #include #include #include #include #include // --- 私有类定义 --- class NumKeyDiaPrivate { Q_DECLARE_PUBLIC(NumKeyDia) public: NumKeyDiaPrivate(NumKeyDia *q) : q_ptr(q) {} // 成员变量移入 D-pointer Ui::NumKeyDia *ui = nullptr; QString value; QPoint m_point; bool m_firstInputFlag = true; enum class InputPage { NumberPage, SymbolPage }; InputPage m_inputPage = InputPage::NumberPage; // 辅助函数 void setInputPage(InputPage page); void refreshInputButtons(); void configureInputButton(QPushButton *button, const QString &label, const QString &value, bool enabled, bool isModeSwitch = false); void loadStyleSheet(); private: NumKeyDia *q_ptr; // 反向指针 }; // --- 私有类逻辑实现 --- void NumKeyDiaPrivate::loadStyleSheet() { QFile file(QStringLiteral(":/commonWidget.qss")); if (file.open(QFile::ReadOnly | QFile::Text)) { QTextStream stream(&file); q_ptr->setStyleSheet(stream.readAll()); } } void NumKeyDiaPrivate::setInputPage(InputPage page) { m_inputPage = page; refreshInputButtons(); } void NumKeyDiaPrivate::refreshInputButtons() { if (m_inputPage == InputPage::NumberPage) { configureInputButton(ui->btn_1, "1", "1", true); configureInputButton(ui->btn_2, "2", "2", true); configureInputButton(ui->btn_3, "3", "3", true); configureInputButton(ui->btn_4, "4", "4", true); configureInputButton(ui->btn_5, "5", "5", true); configureInputButton(ui->btn_6, "6", "6", true); configureInputButton(ui->btn_7, "7", "7", true); configureInputButton(ui->btn_8, "8", "8", true); configureInputButton(ui->btn_9, "9", "9", true); configureInputButton(ui->btn_sub, "#+=", "", true, true); configureInputButton(ui->btn_0, "0", "0", true); configureInputButton(ui->pushButton_dot, ".", ".", true); } else { configureInputButton(ui->btn_1, "/", "/", true); configureInputButton(ui->btn_2, "-", "-", true); configureInputButton(ui->btn_3, ":", ":", true); QString deg = QChar(0x00B0); configureInputButton(ui->btn_4, deg, deg, true); configureInputButton(ui->btn_5, "'", "'", true); configureInputButton(ui->btn_6, "\"", "\"", true); configureInputButton(ui->btn_7, ".", ".", true); configureInputButton(ui->btn_8, "_", "_", true); configureInputButton(ui->btn_9, "@", "@", true); configureInputButton(ui->btn_sub, "123", "", true, true); configureInputButton(ui->btn_0, "+", "+", true); configureInputButton(ui->pushButton_dot, ",", ",", true); } } void NumKeyDiaPrivate::configureInputButton(QPushButton *button, const QString &label, const QString &value, bool enabled, bool isModeSwitch) { if (!button) return; button->setText(label); button->setEnabled(enabled); button->setProperty("inputValue", value); button->setProperty("isModeSwitch", isModeSwitch); } // --- 公共类实现 --- NumKeyDia *NumKeyDia::singleton = nullptr; NumKeyDia::NumKeyDia(QWidget *parent) : QDialog(parent) , d_ptr(new NumKeyDiaPrivate(this)) // 初始化 d_ptr { Q_D(NumKeyDia); if (!singleton) singleton = this; Q_INIT_RESOURCE(NumKeyBoard); d->ui = new Ui::NumKeyDia; d->ui->setupUi(this); d->loadStyleSheet(); setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); d->ui->lineEdit_input->setFocusPolicy(Qt::StrongFocus); auto btnList = d->ui->widget_input->findChildren(); for (auto *btn : btnList) { connect(btn, &QPushButton::clicked, this, &NumKeyDia::btn_input_clicked); btn->setFocusPolicy(Qt::NoFocus); } auto *okShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); connect(okShortcut, &QShortcut::activated, this, &NumKeyDia::on_btn_ok_clicked); d->ui->toolButton_ico->installEventFilter(this); d->ui->label_appInfo->installEventFilter(this); d->ui->btn_clear->setText(QStringLiteral("<")); d->setInputPage(NumKeyDiaPrivate::InputPage::NumberPage); } NumKeyDia::~NumKeyDia() { if (singleton == this) singleton = nullptr; // QScopedPointer 会自动删除 d_ptr,但 Ui 需手动销毁(如果没设置 parent) Q_D(NumKeyDia); delete d->ui; } NumKeyDia* NumKeyDia::instance() { if(!singleton) singleton = new NumKeyDia; return singleton; } bool NumKeyDia::eventFilter(QObject *, QEvent *event) { Q_D(NumKeyDia); if (event->type() == QEvent::MouseButtonPress) { auto *mouseEvent = static_cast(event); d->m_point = mouseEvent->globalPos() - frameGeometry().topLeft(); } else if (event->type() == QEvent::MouseMove) { auto *mouseEvent = static_cast(event); move(mouseEvent->globalPos() - d->m_point); } return false; } void NumKeyDia::setValue(const QString &value) { Q_D(NumKeyDia); d->value = value; d->setInputPage(NumKeyDiaPrivate::InputPage::NumberPage); d->ui->lineEdit_input->setFocus(); d->ui->lineEdit_input->setText(value); d->ui->lineEdit_input->setCursorPosition(d->ui->lineEdit_input->text().size()); d->m_firstInputFlag = true; } QString &NumKeyDia::getValue() { Q_D(NumKeyDia); return d->value; } void NumKeyDia::on_btn_ok_clicked() { Q_D(NumKeyDia); QString res = d->ui->lineEdit_input->text(); d->value = res.isEmpty() ? "0" : res; closeKeyBoard(); } void NumKeyDia::on_btn_cancel_clicked() { closeKeyBoard(); } void NumKeyDia::on_btn_clear_clicked() { Q_D(NumKeyDia); d->m_firstInputFlag = false; int pos = d->ui->lineEdit_input->cursorPosition(); d->ui->lineEdit_input->setCursorPosition(qMax(0, pos - 1)); d->ui->lineEdit_input->setFocus(); } void NumKeyDia::on_btn_back_clicked() { Q_D(NumKeyDia); d->m_firstInputFlag = false; int index = d->ui->lineEdit_input->cursorPosition(); QString text = d->ui->lineEdit_input->text(); if (index > 0) { text.remove(index - 1, 1); d->ui->lineEdit_input->setText(text); d->ui->lineEdit_input->setCursorPosition(index - 1); } d->ui->lineEdit_input->setFocus(); } void NumKeyDia::btn_input_clicked() { Q_D(NumKeyDia); auto *btn = qobject_cast(sender()); if (!btn) return; if (btn->property("isModeSwitch").toBool()) { auto nextPage = (d->m_inputPage == NumKeyDiaPrivate::InputPage::NumberPage) ? NumKeyDiaPrivate::InputPage::SymbolPage : NumKeyDiaPrivate::InputPage::NumberPage; d->setInputPage(nextPage); d->ui->lineEdit_input->setFocus(); return; } if (d->m_firstInputFlag) { d->ui->lineEdit_input->clear(); d->m_firstInputFlag = false; } QString input = btn->property("inputValue").toString(); if (input.isEmpty()) return; int index = d->ui->lineEdit_input->cursorPosition(); QString text = d->ui->lineEdit_input->text(); text.insert(index, input); d->ui->lineEdit_input->setText(text); d->ui->lineEdit_input->setFocus(); d->ui->lineEdit_input->setCursorPosition(index + input.size()); } void NumKeyDia::closeKeyBoard() { this->close(); } namespace KeyBoard { NumKeyDia *app() { return NumKeyDia::instance(); } }