123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- #include "PatternCodeLock.h"
- #include <QPainter>
- #include <QPainterPath>
- #include <QPaintEvent>
- PatternCodeLockWidget::PatternCodeLockWidget(int numberOfEachRowAndCol, QWidget *parent)
- : QWidget(parent), numberOfEachRowAndCol(numberOfEachRowAndCol)
- {
- setMouseTracking(true);
- setMinimumSize(400, 400);
- for (int i = 0; i < numberOfEachRowAndCol; ++i) {
- for (int j = 0; j < numberOfEachRowAndCol; ++j) {
- circularStateList << CircularState::normal;
- smartCircularRectList << QRect();
- }
- }
- connect(&hoverTimer, &QTimer::timeout, this, &PatternCodeLockWidget::onHoverTimer);
- hoverTimer.setInterval(40);
- }
- PatternCodeLockWidget::~PatternCodeLockWidget() { }
- void PatternCodeLockWidget::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing, true);
- const auto rect = event->rect();
- painter.fillRect(rect, QColor("#1D1D1D"));
- auto width = rect.width();
- auto height = rect.height();
- auto sideLength = std::min(width, height) - 20;
- auto halfSideLength = sideLength / 2;
- QRect drawZoneRect = QRect(-halfSideLength, -halfSideLength, sideLength, sideLength);
- drawZoneRect.translate(rect.center());
- painter.save();
- painter.setPen(QPen(QBrush("#141414"), 5));
- painter.drawRoundedRect(drawZoneRect, 12, 12);
- painter.restore();
- radiu = sideLength / (1 + 1 + numberOfEachRowAndCol * 2 + (numberOfEachRowAndCol - 1) * 3);
- bool mustUpdateCircularRect = isUpdateSmartCircularRect;
- for (int i = 0, listIndex = 0; i < numberOfEachRowAndCol; ++i) {
- for (int j = 0; j < numberOfEachRowAndCol; ++j, ++listIndex) {
- QPoint circularCenter =
- drawZoneRect.topLeft() + QPoint(2 * radiu + i * 5 * radiu, 2 * radiu + j * 5 * radiu);
- if (setList.contains(listIndex)) {
- if (PatternCodeLockSetUpState == PatternCodeLockState::setting
- || PatternCodeLockSetUpState == PatternCodeLockState::setted_valid) {
- painter.setPen(QPen(QBrush(QColor("#00FF80")), 3));
- } else {
- painter.setPen(QPen(QBrush(QColor("#FE4C40")), 3));
- }
- } else {
- painter.setPen(QPen(QBrush(Qt::white), 3));
- }
- if (listIndex == lastHoverIndex && hoverTimer.isActive()
- && PatternCodeLockSetUpState == PatternCodeLockState::setting) {
- painter.drawEllipse(circularCenter, radiu + currentchangeLength, radiu + currentchangeLength);
- } else {
- painter.drawEllipse(circularCenter, radiu, radiu);
- }
- if (mustUpdateCircularRect) {
- QRect newCircularRect = QRect(-radiu / 2, -radiu / 2, radiu, radiu);
- newCircularRect.translate(circularCenter);
- smartCircularRectList[listIndex] = newCircularRect;
- }
- painter.save();
- switch (circularStateList.at(listIndex)) {
- case CircularState::normal: {
- if (listIndex == lastHoverIndex && hoverTimer.isActive()
- && PatternCodeLockSetUpState == PatternCodeLockState::notSet) {
- painter.setBrush(Qt::white);
- painter.setPen(Qt::transparent);
- painter.drawEllipse(circularCenter, static_cast<int>(radiu * 0.5 + currentchangeLength),
- static_cast<int>(radiu * 0.5 + currentchangeLength));
- } else {
- painter.setBrush(QColor("#888888"));
- painter.setPen(Qt::transparent);
- painter.drawEllipse(circularCenter, radiu / 2, radiu / 2);
- }
- } break;
- case CircularState::hoverOnInnerSamrtCircular: {
- painter.setPen(Qt::transparent);
- if (PatternCodeLockSetUpState == PatternCodeLockState::notSet) {
- painter.setBrush(Qt::white);
- if (hoverTimer.isActive()) {
- painter.drawEllipse(circularCenter, static_cast<int>(radiu * 0.5 + currentchangeLength),
- static_cast<int>(radiu * 0.5 + currentchangeLength));
- } else {
- painter.drawEllipse(circularCenter, static_cast<int>(radiu * 0.7),
- static_cast<int>(radiu * 0.7));
- }
- } else {
- if (PatternCodeLockSetUpState == PatternCodeLockState::setting
- || PatternCodeLockSetUpState == PatternCodeLockState::setted_valid) {
- painter.setBrush(QColor("#00FF80"));
- } else {
- painter.setBrush(QColor("#FE4C40"));
- }
- painter.drawEllipse(circularCenter, static_cast<int>(radiu * 0.7), static_cast<int>(radiu * 0.7));
- }
- } break;
- }
- painter.restore();
- }
- }
- if (PatternCodeLockSetUpState != PatternCodeLockState::notSet) {
- painter.setBrush(Qt::transparent);
- if (PatternCodeLockSetUpState == PatternCodeLockState::setted_invalid) {
- painter.setPen(QPen(QBrush(QColor("#FE4C40")), 7, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- } else {
- painter.setPen(QPen(QBrush(QColor("#00FF80")), 7, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
- int setListSize = setList.size();
- for (int i = 0; i < setListSize; ++i) {
- if (i < (setListSize - 1)) {
- painter.drawLine(smartCircularRectList.at(setList.at(i)).center(),
- smartCircularRectList.at(setList.at(i + 1)).center());
- }
- }
- if (PatternCodeLockSetUpState == PatternCodeLockState::setting) {
- painter.drawLine(smartCircularRectList.at(setList.last()).center(), settingMousPos);
- }
- }
- if (mustUpdateCircularRect)
- isUpdateSmartCircularRect = false;
- }
- void PatternCodeLockWidget::resizeEvent(QResizeEvent *event)
- {
- isUpdateSmartCircularRect = true;
- QWidget::resizeEvent(event);
- }
- void PatternCodeLockWidget::mouseMoveEvent(QMouseEvent *event)
- {
- auto pos = event->pos();
- int currentHoverIndex = -1;
- if (PatternCodeLockSetUpState == PatternCodeLockState::notSet) {
- bool mouseInSomeSmartCircular { false };
- for (int i = 0; i < smartCircularRectList.size(); ++i) {
- if (smartCircularRectList.at(i).contains(pos)) {
- circularStateList[i] = CircularState::hoverOnInnerSamrtCircular;
- currentHoverIndex = i;
- mouseInSomeSmartCircular = true;
- } else {
- circularStateList[i] = CircularState::normal;
- }
- }
- if (mouseInSomeSmartCircular) {
- lastHoverIndex = currentHoverIndex;
- setCursor(Qt::PointingHandCursor);
- } else {
- setCursor(Qt::ArrowCursor);
- }
- if (!hoverTimer.isActive()) {
- if (this->mouseInSomeSmartCircular != mouseInSomeSmartCircular) //鼠标进入了某个小圆或从小圆出来
- {
- this->mouseInSomeSmartCircular = mouseInSomeSmartCircular;
- if (this->mouseInSomeSmartCircular) {
- currentchangeLength = 0;
- } else {
- currentchangeLength = radiu * 0.2;
- }
- hoverTimer.start();
- }
- }
- } else if (PatternCodeLockSetUpState == PatternCodeLockState::setting) {
- bool mouseInSomeSmartCircular { false };
- for (int i = 0; i < smartCircularRectList.size(); ++i) {
- if (smartCircularRectList.at(i).contains(pos)) {
- if (!setList.contains(i)) {
- setList << i;
- circularStateList[i] = CircularState::hoverOnInnerSamrtCircular;
- currentHoverIndex = i;
- }
- mouseInSomeSmartCircular = true;
- }
- }
- if (this->mouseInSomeSmartCircular != mouseInSomeSmartCircular) {
- this->mouseInSomeSmartCircular = mouseInSomeSmartCircular;
- if (mouseInSomeSmartCircular) {
- lastHoverIndex = currentHoverIndex;
- setCursor(Qt::PointingHandCursor);
- if (!hoverTimer.isActive()) {
- currentchangeLength = 0;
- hoverTimer.start();
- }
- } else {
- setCursor(Qt::ArrowCursor);
- }
- }
- settingMousPos = pos;
- }
- update();
- QWidget::mouseMoveEvent(event);
- }
- void PatternCodeLockWidget::onHoverTimer()
- {
- if (PatternCodeLockSetUpState == PatternCodeLockState::notSet) {
- if (mouseInSomeSmartCircular) {
- if (currentchangeLength >= (radiu * 0.2)) {
- hoverTimer.stop();
- }
- currentchangeLength += 2;
- } else {
- if (currentchangeLength <= -(radiu * 0.1)) {
- hoverTimer.stop();
- }
- currentchangeLength -= 2;
- }
- } else if (PatternCodeLockSetUpState == PatternCodeLockState::setting) {
- if (currentchangeLength >= (radiu * 0.1)) {
- hoverTimer.stop();
- }
- currentchangeLength += 2;
- }
- update();
- }
- void PatternCodeLockWidget::mousePressEvent(QMouseEvent *event)
- {
- if (lastHoverIndex != -1) {
- if (PatternCodeLockSetUpState == PatternCodeLockState::notSet) //开始设置
- {
- PatternCodeLockSetUpState = PatternCodeLockState::setting;
- setList << lastHoverIndex;
- circularStateList[lastHoverIndex] = CircularState::hoverOnInnerSamrtCircular;
- settingMousPos = event->pos();
- currentchangeLength = 0;
- hoverTimer.start();
- update();
- }
- }
- QWidget::mousePressEvent(event);
- }
- void PatternCodeLockWidget::mouseDoubleClickEvent(QMouseEvent *event)
- {
- if (PatternCodeLockSetUpState == PatternCodeLockState::setting && !mouseInSomeSmartCircular) {
- if (setList.size() < 4) {
- PatternCodeLockSetUpState = PatternCodeLockState::setted_invalid;
- emit setPassword("4位以下的无效密码");
- } else {
- PatternCodeLockSetUpState = PatternCodeLockState::setted_valid;
- emit setPassword(getPassWord());
- }
- update();
- }
- QWidget::mouseDoubleClickEvent(event);
- }
- QString PatternCodeLockWidget::getPassWord()
- {
- QString psw;
- for (const int &value : setList) {
- psw.append(QString::number(value, 16));
- }
- return psw;
- }
- int PatternCodeLockWidget::getNumberOfEachRowAndCol() const
- {
- return numberOfEachRowAndCol;
- }
- void PatternCodeLockWidget::setNumberOfEachRowAndCol(int newNumberOfEachRowAndCol)
- {
- if (newNumberOfEachRowAndCol > 1 && newNumberOfEachRowAndCol < 10) {
- reset();
- circularStateList.clear();
- smartCircularRectList.clear();
- numberOfEachRowAndCol = newNumberOfEachRowAndCol;
- for (int i = 0; i < numberOfEachRowAndCol; ++i) {
- for (int j = 0; j < numberOfEachRowAndCol; ++j) {
- circularStateList << CircularState::normal;
- smartCircularRectList << QRect();
- }
- }
- update();
- }
- }
- void PatternCodeLockWidget::reset()
- {
- PatternCodeLockSetUpState = PatternCodeLockState::notSet;
- std::fill(circularStateList.begin(), circularStateList.end(), CircularState::normal);
- lastHoverIndex = -1;
- hoverTimer.stop();
- currentchangeLength = 0;
- isUpdateSmartCircularRect = true;
- mouseInSomeSmartCircular = false;
- setList.clear();
- settingMousPos = QPoint(0, 0);
- update();
- }
- /************************ demo **************************************
- #include <QVBoxLayout>
- #include <QHBoxLayout>
- #include <QLabel>
- #include <QSpinBox>
- #include <QLineEdit>
- #include <QPushButton>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- PatternCodeLockWidget *w = new PatternCodeLockWidget(4);
- QWidget widget;
- auto hb = new QHBoxLayout;
- hb->addWidget(new QLabel("设置的密码:"));
- auto lineEdit = new QLineEdit;
- hb->addWidget(lineEdit);
- hb->addWidget(new QLabel("设置行列数:"));
- auto spinbox = new QSpinBox;
- spinbox->setRange(2, 9);
- spinbox->setMinimumWidth(100);
- spinbox->setValue(w->getNumberOfEachRowAndCol());
- hb->addWidget(spinbox);
- auto btn = new QPushButton("还原");
- hb->addWidget(btn);
- auto vb = new QVBoxLayout;
- vb->addWidget(w, 5);
- vb->addLayout(hb, 1);
- widget.setLayout(vb);
- QObject::connect(w, &PatternCodeLockWidget::setPassword, lineEdit, &QLineEdit::setText);
- QObject::connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), w,
- &PatternCodeLockWidget::setNumberOfEachRowAndCol);
- QObject::connect(btn, &QPushButton::clicked, w, &PatternCodeLockWidget::reset);
- widget.show();
- return a.exec();
- }
- *********************************************************************************/
|