使用sql制作闹钟

效果

image

代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QMainWindow>
#include <QDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QLabel>
#include <QTime>
#include <QSqlTableModel>
#include "numberpicker.h"
#include "switchbutton.h"

class NumberPicker;
class SwitchButton;

/* ListWiget项结构体 */
struct ItemObjectInfo {
    /* 闹钟开关 */
    SwitchButton *switchButton;
    /* Widget容器 */
    QWidget *widget;
    /* 水平布局 */
    QHBoxLayout *hBoxLayout;
};


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:

    /* 数据库连接类 */
    QSqlDatabase sqlDatabase;

    /* 数据库操作模型 */
    QSqlTableModel *model;

    /* 时针选择器 */
    NumberPicker *hourPicker;

    /* 分钟选择器 */
    NumberPicker *minutePicker;

    /* 弹出选择时间对话框 */
    QDialog *alarmDialog;

    /* 水平布局 */
    QHBoxLayout *hBoxLayout[3];

    /* 垂直布局 */
    QVBoxLayout *vBoxLayout[2];

    /* 显示闹钟列表 */
    QListWidget *listWidget;

    /* 主Widget */
    QWidget *mainWidget;

    /* 底部Wiget */
    QWidget *bottomWidget;

    /* 弹出对话框布局窗口选择时间容器 */
    QWidget *timeWidget;

    /* 弹出对话框布局窗口按钮容器 */
    QWidget *btWidget;

    /* 添加闹钟按钮 */
    QPushButton *addAlarm;

    /* 确认按钮 */
    QPushButton *yesButton;

    /* 取消按钮 */
    QPushButton *cancelButton;

    /* listWiget项信息存储 */
    QVector<ItemObjectInfo> itemObjectInfo;

private slots:
    /* 添加闹钟按钮被点击 */
    void addAlarmClicked();

    /* 列表被点击 */
    void listWidgetItemClicked(QListWidgetItem *);

    /* 确认按钮被点击 */
    void yesButtonClicked();

    /* 取消按钮被点击 */
    void cancelButtonClicked();

    /* 开关按钮点击 */
    void switchButtonClicked(bool);
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QDebug>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /* 设置主窗体的显示位置与大小 */
    this->setGeometry(0, 0, 800, 480);

    /* 查看本机可用的数据库驱动 */
    QStringList drivers = QSqlDatabase::drivers();
    foreach(QString driver, drivers) {
        qDebug()<<driver;
    }

    /* 以QSQLITE驱动方式打开或者创建数据库 */
    sqlDatabase = QSqlDatabase::addDatabase("QSQLITE");
    sqlDatabase.setDatabaseName("alarm.db");
    /* 以open的方式打开alarm.db数据库,则会创建一个alarm.db */
    if (!sqlDatabase.open())
        qDebug()<<"连接数据库错误"<<sqlDatabase.lastError()<<endl;
    else
        qDebug()<<"连接数据库成功"<<endl;

    QSqlQuery query(sqlDatabase);
    /* 使用指令式创建表 */
    query.exec("create table alarm (id int primary key, time vchar(15), flag vchar(5))");
    /* 以指令的方式插入数据 */
    //query.exec("insert into alarm values(0, '06:00', 'false')");

    model = new QSqlTableModel(this, sqlDatabase);

    /* 模型设置表的名字,需要与数据库的表的名字相同 */
    model->setTable("alarm");

    /* 如果有修改则同步修改到数据库,
     * 注意这个规则需要与tabview这样的控件才生效,
     * 因为tabview可以直接编辑表里的内容 */
    model->setEditStrategy(QSqlTableModel::OnFieldChange);

    /* 成功则返回true,查看数据库里是否有alarm这个表格 */
    model->select();

    /* 如果数据表数据为空,则添加两个闹钟 */
    if (model->rowCount() == 0) {
        /* 插入一行 */
        model->insertRow(model->rowCount());
        /* 在该行插入数据 */
        model->setData(model->index(0, 0), 1);
        model->setData(model->index(0, 1), "06:00");
        model->setData(model->index(0, 2), "false");
        /* 插入数据后记得提交 */
        model->submit();

        /* 再插入一行 */
        model->insertRow(model->rowCount());
        model->setData(model->index(1, 0), 2);
        model->setData(model->index(1, 1), "18:00");
        model->setData(model->index(1, 2), "true");
        /* 提交 */
        model->submit();
    }

    hourPicker = new NumberPicker(this);
    hourPicker->setRange(0, 24);

    minutePicker = new NumberPicker(this);
    minutePicker->setRange(0, 60);

    /* 标签,用于显示时&分 */
    QLabel *label[3];
    label[0] = new QLabel();
    label[1] = new QLabel();
    label[2] = new QLabel();

    QFont font;
    font.setBold(true);
    font.setPixelSize(10);
    QPalette pal;
    pal.setBrush(QPalette::WindowText, QColor(0, 0, 0));

    label[0]->setFont(font);
    label[1]->setFont(font);
    label[2]->setFont(font);

    label[0]->setText(" ");
    label[1]->setText("时");
    label[2]->setText("分");

    /* 主布局初始化 */
    listWidget = new QListWidget();
    mainWidget = new QWidget();
    bottomWidget = new QWidget();
    alarmDialog = new QDialog(this);
    timeWidget = new QWidget();
    btWidget = new QWidget();
    addAlarm = new QPushButton();
    yesButton = new QPushButton();
    cancelButton = new QPushButton();
    vBoxLayout[0] = new QVBoxLayout();
    vBoxLayout[1] = new QVBoxLayout();
    hBoxLayout[0] = new QHBoxLayout();
    hBoxLayout[1] = new QHBoxLayout();
    hBoxLayout[2] = new QHBoxLayout();

    addAlarm->setMaximumSize(84, 84);
    addAlarm->setObjectName("addAlarm");
    addAlarm->setMinimumSize(84, 84);
    bottomWidget->setMinimumHeight(84);
    bottomWidget->setMaximumHeight(84);
    yesButton->setText("确认");
    cancelButton->setText("取消");
    yesButton->setMaximumSize(100, 50);
    yesButton->setMinimumSize(100, 50);
    cancelButton->setMinimumSize(100, 50);
    cancelButton->setMaximumSize(100, 50);
    btWidget->setMaximumHeight(70);
    btWidget->setMinimumHeight(70);
    alarmDialog->setMinimumSize(300, 300);
    alarmDialog->setMaximumSize(300, 300);
    alarmDialog->setModal(true);
    yesButton->setObjectName("yesButton");
    cancelButton->setObjectName("cancelButton");

    /* 主布局 */
    vBoxLayout[0]->addWidget(listWidget);
    vBoxLayout[0]->addWidget(bottomWidget);
    vBoxLayout[0]->setContentsMargins(0, 0, 0, 0);

    mainWidget->setLayout(vBoxLayout[0]);

    setCentralWidget(mainWidget);

    /* 底部按钮布局 */
    hBoxLayout[0]->addWidget(addAlarm);
    hBoxLayout[0]->setContentsMargins(0, 0, 0, 0);
    bottomWidget->setLayout(hBoxLayout[0]);

    /* 对话框布局 */
    vBoxLayout[1]->addWidget(timeWidget);
    vBoxLayout[1]->addWidget(btWidget);
    vBoxLayout[1]->setContentsMargins(0, 0, 0, 0);
    alarmDialog->setLayout(vBoxLayout[1]);

    hBoxLayout[1]->addWidget(label[0]);
    hBoxLayout[1]->addWidget(hourPicker);
    hBoxLayout[1]->addWidget(label[1]);
    hBoxLayout[1]->addWidget(minutePicker);
    hBoxLayout[1]->addWidget(label[2]);
    hBoxLayout[1]->setContentsMargins(0, 0, 0, 0);
    timeWidget->setLayout(hBoxLayout[1]);

    hBoxLayout[2]->addWidget(yesButton);
    hBoxLayout[2]->addWidget(cancelButton);

    btWidget->setLayout(hBoxLayout[2]);

    /* 打印出闹钟数据库里的信息 */
    for (int i = 0; i < model->rowCount(); i++) {
        for (int j = 0; j < 3; j++) {
            QModelIndex qindex = model->index(i, j);
            switch (j) {
            case 0:
                qDebug()<<"第"<<model->data(qindex).toInt()<<"行数据";
                break;
            case 1:
                listWidget->addItem(model->data(qindex).toString());
                qDebug()<<"闹钟时间为:"<<model->data(qindex).toString();
                break;
            case 2:
                qDebug()<<"闹钟状态为:"
                       <<model->data(qindex).toString()<<endl;
                if (model->data(qindex).toString() != "true")
                    listWidget->item(i)
                            ->setTextColor(QColor(22, 22, 22, 60));
                else
                    listWidget->item(i)
                            ->setTextColor(QColor(22, 22, 22, 225));
                break;
            default:
                break;
            }
        }
    }

    /* 在列表里添加闹钟开关 */
    for (int i = 0; i < model->rowCount(); i++) {
        ItemObjectInfo info;
        info.widget = new QWidget();
        info.switchButton = new SwitchButton();
        info.hBoxLayout = new QHBoxLayout();
        info.switchButton->setMaximumSize(55, 30);
        info.switchButton->setMinimumSize(55, 30);
        info.hBoxLayout->setContentsMargins(0, 0, 0, 0);
        info.hBoxLayout->setAlignment(Qt::AlignRight);
        info.hBoxLayout->addWidget(info.switchButton);
        info.widget->setLayout(info.hBoxLayout);
        listWidget->setItemWidget(listWidget->item(i),
                                  info.widget);
        itemObjectInfo.append(info);

        /* 连接信号槽 */
        connect(info.switchButton,
                SIGNAL(toggled(bool)),
                this,
                SLOT(switchButtonClicked(bool)));

        /* 获取数据库里的闹钟开关状态 */
        QModelIndex qindex = model->index(i, 2);
        if (model->data(qindex).toBool())
            /* 设置列表里的闹钟开关按钮状态 */
            info.switchButton->setToggle(true);
    }

    /* 按钮 */
    connect(addAlarm, SIGNAL(clicked()), this,
            SLOT(addAlarmClicked()));

    connect(yesButton, SIGNAL(clicked()), this,
            SLOT(yesButtonClicked()));

    connect(cancelButton, SIGNAL(clicked()), this,
            SLOT(cancelButtonClicked()));

    /* 列表 */
    connect(listWidget,
            SIGNAL(itemClicked(QListWidgetItem*)),
            this,
            SLOT(listWidgetItemClicked(QListWidgetItem*)));
}

MainWindow::~MainWindow()
{
    /* 关闭数据库 */
    sqlDatabase.close();
}

void MainWindow::addAlarmClicked()
{
    /* 选择时间对话框里显示当前系统时间 */
    hourPicker->setValue(QTime::currentTime().hour());
    minutePicker->setValue(QTime::currentTime().minute());

    /* 取消按钮显示文本为"取消" */
    cancelButton->setText("取消");

    /* 如果是点击添加闹钟的按钮,则设置闹钟列表的索引index为-1 */
    listWidget->setCurrentRow(-1);

    /* 显示对话框 */
    alarmDialog->show();
}

void MainWindow::listWidgetItemClicked(QListWidgetItem *item)
{
    /* 从被点击项里获取闹钟数据 */
    QStringList list =
            listWidget->item(listWidget->row(item))->text().split(":");

    /* 选择时间对话框里显示被选择项的时间 */
    hourPicker->setValue(list.at(0).toInt());
    minutePicker->setValue(list.at(1).toInt());

    /* 取消按钮显示文本为"删除" */
    cancelButton->setText("删除");

    /* 显示闹钟选择对话框 */
    alarmDialog->show();

    /* 作用使其失去选择 */
    listWidget->clearSelection();
}

void MainWindow::yesButtonClicked()
{
    /* 获取数值选择值的数据,转为字符串 */
    QString hour;
    QString minute;

    if (hourPicker->readValue() < 10)
        hour = "0" + QString::number(hourPicker->readValue()) + ":";
    else
        hour = QString::number(hourPicker->readValue()) + ":";

    if (minutePicker->readValue() < 10)
        minute = "0" + QString::number(minutePicker->readValue());
    else
        minute = QString::number(minutePicker->readValue());

    /* 如果不是选中闹钟列表的数据 */
    if (listWidget->currentRow() == -1) {
        /* 插入一行数据,闹钟时间为选择的闹钟时间 */
        int row = model->rowCount();

        /* 插入数据到数据库 */
        model->insertRow(row);
        model->setData(model->index(row, 0), row + 1);
        model->setData(model->index(row, 1), hour + minute);
        model->setData(model->index(row, 2), "true");
        model->submit();

        /* 添加闹钟到列表 */
        listWidget->addItem(hour + minute);

        /* 添加到容器 */
        ItemObjectInfo info;
        info.widget = new QWidget();
        info.switchButton = new SwitchButton();
        info.hBoxLayout = new QHBoxLayout();
        info.switchButton->setMaximumSize(55, 30);
        info.switchButton->setMinimumSize(55, 30);
        info.hBoxLayout->setContentsMargins(0, 0, 0, 0);
        info.hBoxLayout->setAlignment(Qt::AlignRight);
        info.hBoxLayout->addWidget(info.switchButton);
        info.widget->setLayout(info.hBoxLayout);
        info.switchButton->setToggle(true);

        /* 连接信号槽 */
        connect(info.switchButton, SIGNAL(toggled(bool)), this,
                SLOT(switchButtonClicked(bool)));

        listWidget->setItemWidget(
                    listWidget->item(listWidget->count() - 1),
                    info.widget);
        itemObjectInfo.append(info);
    } else {
        /* 修改数据(更新闹钟数据) */
        int row =  listWidget->currentRow();
        model->setData(model->index(row, 0), row + 1);
        model->setData(model->index(row, 1), hour + minute);
        model->setData(model->index(row, 2), "true");
        model->submit();

        /* 设置当前项的闹钟文本 */
        listWidget->currentItem()->setText(hour + minute);
    }

    /* 再确保提交 */
    if (model->isDirty())
        model->submitAll();

    /* 关闭对话框 */
    alarmDialog->close();
}

void MainWindow::cancelButtonClicked()
{
    if (cancelButton->text() == "删除") {
        /* 删除数据库整一行数据 */
        model->removeRow(listWidget->currentRow());
        model->submit();
        /* 执行上面语句 */
        model->select();
        itemObjectInfo.remove(listWidget->currentRow());
        listWidget->takeItem(listWidget->currentRow());
    }

    /* 再确保提交 */
    if (model->isDirty())
        model->submitAll();

    /* 关闭对话框 */
    alarmDialog->close();
}


/* 当点击闹钟开关时,将闹钟开关状态同步更新到数据库里 */
void MainWindow::switchButtonClicked(bool checked)
{
    listWidget->clearSelection();

    SwitchButton *button = (SwitchButton *)sender();
    for (int i = 0; i < itemObjectInfo.count(); i++) {
        if (button == itemObjectInfo.at(i).switchButton) {
            if (checked) {
                model->setData(model->index(i, 2), "true");
                listWidget->item(i)
                        ->setTextColor(QColor(22, 22, 22, 225));
            } else {
                model->setData(model->index(i, 2), "false");
                listWidget->item(i)
                        ->setTextColor(QColor(22, 22, 22, 60));
            }

            model->submit();
            break;
        }
    }
}

numberpicker.h

#ifndef NUMBERPICKER_H
#define NUMBERPICKER_H

#include <QMainWindow>
#include <QPropertyAnimation>

class NumberPicker : public QWidget
{
    Q_OBJECT

    Q_PROPERTY(int deviation READ readDeviation WRITE setDeviation )
public:
    NumberPicker(QWidget *parent = nullptr);
    ~NumberPicker();

    /* 设置最大值与最小值的范围 */
    void setRange(int min, int max);

    /* 读取当前值 */
    int readValue();

protected:
    void mousePressEvent(QMouseEvent *);

    void mouseMoveEvent(QMouseEvent *);

    void mouseReleaseEvent(QMouseEvent *);

    void wheelEvent(QWheelEvent *);

    void paintEvent(QPaintEvent *);

public:
    /* 描绘数字 */
    void paintNum(QPainter &painter, int num, int deviation);

    /* 使选中的数字回到屏幕中间 */
    void homing();

    /* 鼠标移动偏移量,默认为0 */
    int readDeviation();

    /* 设置偏移量 */
    void setDeviation(int n);

    /* 设置字体大小 */
    void setNumSize(int);

    /* 设置间隔大小 */
    void setInterval(int);

    /* 设置分格数量,一般设置为3、5、7... */
    void setDevide(int);

    /* 设置数字颜色,设置rgb的数值 */
    void setNumberColor(QRgb rgb);

    /* 设置当前值 */
    void setValue(int value);

signals:

    void currentValueChanged(int value);

    void deviationChange(int deviation);

private:
    /* 最小值 */
    int minRange;

    /* 最大值 */
    int maxRange;

    /* 当前选中的值 */
    int currentValue;

    /* 鼠标是否按下 */
    bool isDragging;

    /* 偏移量,记录鼠标按下后移动的垂直距离 */
    int deviation;

    /* 鼠标按下的垂直位置 */
    int mouseSrcPos;

    /* 数字大小 */
    int numSize;

    /* 动画 */
    QPropertyAnimation *homingAni;

    /* 间隔大小 */
    int interval;

    /* 分格数量 */
    int devide;

    /* 数字颜色 */
    QColor numberColor;
};
#endif // NUMBERPICKER_H

numberpicker.cpp

#include <QMouseEvent>
#include <QDebug>
#include "numberpicker.h"
#include <QPainter>

NumberPicker::NumberPicker(QWidget *parent) :
    /* 最小值默认为0 */
    minRange(0),

    /* 最大值默认60 */
    maxRange(60),

    /* 当前值默认0 */
    currentValue(0),

    /* 按下标志位为假 */
    isDragging(false),

    /* 默认偏移量为0 */
    deviation(0),

    /* 数值越大 */
    numSize(15),

    /* 间隔为1 */
    interval(1),

    /* 默认分成3格 */
    devide(3),

    /* 默认颜色黑色 */
    numberColor(0, 0, 0)
{
    setParent(parent);
    setMinimumSize(50, 150);
    homingAni = new QPropertyAnimation(this, "deviation");
    homingAni->setDuration(300);
    homingAni->setEasingCurve(QEasingCurve::OutQuad);
}

NumberPicker::~NumberPicker()
{

}

void NumberPicker::setRange(int min, int max)
{
    minRange = min;
    maxRange = max;
    if (currentValue < min) {
        currentValue = min;
    }
    if (currentValue > max) {
        currentValue = max;
    }
    repaint();
}

int NumberPicker::readValue()
{
    return currentValue;
}

void NumberPicker::mousePressEvent(QMouseEvent *e)
{
    homingAni->stop();
    isDragging = true;
    mouseSrcPos = e->pos().y();
    QWidget::mousePressEvent(e);
}

void NumberPicker::mouseMoveEvent(QMouseEvent *e)
{
    if (isDragging){
        deviation = e->pos().y() - mouseSrcPos;

        /* 若移动速度过快,则进行限制 */
        if (deviation > (height() - 1) / devide) {
            deviation = (height() - 1) / devide;
        } else if (deviation < -(height() - 1) / devide) {
            deviation = -( height() - 1) / devide;
        }

        emit deviationChange(deviation / ((height() - 1) / devide));
        repaint();
    }
}

void NumberPicker::mouseReleaseEvent(QMouseEvent *)
{
    if (isDragging) {
        isDragging = false;
        homing();
    }
}

void NumberPicker::wheelEvent(QWheelEvent *e)
{
    if (e->delta() > 0) {
        deviation = (this->height() - 1) / devide;
    } else {
        deviation = -(this->height() - 1) / devide;
    }

    homing();
    repaint();
}

void NumberPicker::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    int Height = height() - 1;

    if (deviation >= Height / devide && currentValue > minRange ) {
        mouseSrcPos += Height / devide;
        deviation -= Height / devide;
        currentValue -= interval;
        /* 负数处理 */
        if (currentValue < 0)
            currentValue = maxRange + currentValue;
    }

    if (deviation <= -Height / devide && currentValue < maxRange ) {
        mouseSrcPos -= Height / devide;
        deviation += Height / devide;
        currentValue += interval;
    }

    if (qAbs(int(currentValue)) >= int(maxRange))
        currentValue = minRange;

    paintNum(painter, qAbs(int(currentValue + maxRange) % maxRange),
             deviation);

    paintNum(painter,
             qAbs((currentValue - interval + maxRange) % maxRange),
             deviation - Height / devide);

    paintNum(painter,
             qAbs((currentValue + interval + maxRange) % maxRange),
             deviation + Height / devide);

    for (int i = 2; i <= devide / 2; ++i) {
        if (qAbs(currentValue - interval * i) >= minRange) {
            paintNum(painter,
                     qAbs((currentValue - interval * i + maxRange)
                          % maxRange),
                     deviation - Height / devide * i);
        }

        if (qAbs(currentValue + interval * i) <= maxRange) {
            paintNum(painter,
                     qAbs((currentValue + interval * i + maxRange)
                          % maxRange),
                     deviation + Height / devide * i);
        }
    }
}

void NumberPicker::paintNum(QPainter &painter, int num, int deviation)
{
    int Width = width() - 1;
    int Height = height() - 1;

    /* 偏移量越大,数字越小 */
    //int size = (Height - qAbs(deviation)) / numSize;
    int size = (Height - qAbs(deviation)) * numSize / 80;
    int transparency = 255 - 255 * qAbs(deviation) / Height;
    int height = Height / devide;
    int y = Height / 2 + deviation - height / 2;

    QFont font;
    font.setPixelSize(size);
    painter.setFont(font);
    painter.setPen(QColor(numberColor.red(),
                          numberColor.green(),
                          numberColor.blue(),
                          transparency));

    if ( y >= 0 && y + height < Height) {
        //painter.drawRect(0, y, Width, height);
        if (num < 10)
            painter.drawText(QRectF(0, y, Width, height),
                             Qt::AlignCenter,
                             "0" + QString::number(num, 'f', 0));
        else
            painter.drawText(QRectF(0, y, Width, height),
                             Qt::AlignCenter,
                             QString::number(num, 'f', 0));
    }
}

void NumberPicker::homing()
{
    if (deviation > height() / 10) {
        homingAni->setStartValue((height() - 1 ) / 8 - deviation);
        homingAni->setEndValue(0);
        currentValue -= interval;
    } else if (deviation > -height() / 10) {
        homingAni->setStartValue(deviation);
        homingAni->setEndValue(0);
    } else if (deviation < -height() / 10) {
        homingAni->setStartValue(-(height() - 1) / 8 - deviation);
        homingAni->setEndValue(0);
        currentValue += interval;
    }

    emit currentValueChanged(currentValue);
    homingAni->start();
}

int NumberPicker::readDeviation()
{
    return deviation;
}

void NumberPicker::setDeviation(int n)
{
    deviation = n;
    repaint();
}

void NumberPicker::setNumSize(int size)
{
    numSize = size;
    repaint();
}

void NumberPicker::setInterval(int n)
{
    interval = n;
    repaint();
}

void NumberPicker::setDevide(int n)
{
    devide = n;
    repaint();
}

void NumberPicker::setNumberColor(QRgb rgb)
{
    numberColor.setRgb(rgb);
    repaint();
}

void NumberPicker::setValue(int value)
{
    if (value < minRange || value > maxRange) {
        qDebug()<<"数值设置必须在"<<minRange
               <<"和"<<maxRange<<"之间"<<endl;
        return;
    }
    currentValue = value;
    repaint();
}

switchbutton.h

#ifndef SWITCHBUTTON_H
#define SWITCHBUTTON_H

#include <QWidget>
#include <QTimer>

class SwitchButton : public QWidget
{
    Q_OBJECT

public:
    explicit SwitchButton(QWidget *parent = nullptr);

    /* 返回开关状态 - 打开:true 关闭:false */
    bool isToggled() const;

    /* 设置开关状态 */
    void setToggle(bool checked);

    /* 设置背景颜色 */
    void setBackgroundColor(QColor color);

    /* 设置选中颜色 */
    void setCheckedColor(QColor color);

    /* 设置不可用颜色 */
    void setDisbaledColor(QColor color);

protected:
    /* 绘制开关 */
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

    /* 鼠标按下事件 */
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

    /* 鼠标释放事件 - 切换开关状态、发射toggled()信号 */
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

    /* 大小改变事件 */
    void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;

    /* 缺省大小 */
    QSize sizeHint() const Q_DECL_OVERRIDE;
    QSize minimumSizeHint() const Q_DECL_OVERRIDE;

signals:
    /* 状态改变时,发射信号 */
    void toggled(bool checked);

private slots:
    /* 状态切换时,用于产生滑动效果 */
    void onTimeout();

private:
    /* 是否选中 */
    bool m_bChecked;

    /* 背景颜色 */
    QColor m_background;

    /* 选中颜色 */
    QColor m_checkedColor;

    /* 不可用颜色 */
    QColor m_disabledColor;

    /* 拇指颜色 */
    QColor m_thumbColor;

    /* 圆角 */
    qreal m_radius;

    /* x点坐标 */
    qreal m_nX;

    /* y点坐标 */
    qreal m_nY;

    /* 高度 */
    qint16 m_nHeight;

    /* 外边距 */
    qint16 m_nMargin;

    /* 定时器 */
    QTimer m_timer;
};
#endif // SWITCHBUTTON_H

switchbutton.cpp

#include "switchbutton.h"

#include <QPainter>
#include <QMouseEvent>

SwitchButton::SwitchButton(QWidget *parent)
    : QWidget(parent),
      m_bChecked(false),
      m_background(Qt::gray),
      m_checkedColor(34, 131, 246),
      m_disabledColor(190, 190, 190),
      m_thumbColor(Qt::gray),
      m_radius(12.5),
      m_nHeight(16),
      m_nMargin(3)
{
    /* 鼠标滑过光标形状 - 手型 */
    setCursor(Qt::PointingHandCursor);

    /* 连接信号槽 */
    connect(&m_timer, SIGNAL(timeout()),
            this, SLOT(onTimeout()));
}

/* 绘制开关 */
void SwitchButton::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QPainter painter(this);
    painter.setPen(Qt::NoPen);
    painter.setRenderHint(QPainter::Antialiasing);

    QPainterPath path;
    QColor background;
    QColor thumbColor;
    qreal dOpacity;
    /* 可用状态 */
    if (isEnabled()) {
        /* 打开状态 */
        if (m_bChecked) {
            background = m_checkedColor;
            thumbColor = m_checkedColor;
            dOpacity = 0.600;
            /* 关闭状态 */
        } else {
            background = m_background;
            thumbColor = m_thumbColor;
            dOpacity = 0.800;
        }
        /* 不可用状态 */
    } else {
        background = m_background;
        dOpacity = 0.260;
        thumbColor = m_disabledColor;
    }
    /* 绘制大椭圆 */
    painter.setBrush(background);
    painter.setOpacity(dOpacity);
    path.addRoundedRect(QRectF(m_nMargin,
                               m_nMargin, width() - 2 * m_nMargin,
                               height() - 2 * m_nMargin),
                        m_radius, m_radius);
    painter.drawPath(path.simplified());

    /* 绘制小椭圆 */
    painter.setBrush(thumbColor);
    painter.setOpacity(1.0);
    painter.drawEllipse(QRectF(m_nX - (m_nHeight / 2),
                               m_nY - (m_nHeight / 2),
                               height(),
                               height()));
}

/* 鼠标按下事件 */
void SwitchButton::mousePressEvent(QMouseEvent *event)
{
    if (isEnabled()) {
        if (event->buttons() & Qt::LeftButton) {
            event->accept();
        } else {
            event->ignore();
        }
    }
}

/* 鼠标释放事件 - 切换开关状态、发射toggled()信号 */
void SwitchButton::mouseReleaseEvent(QMouseEvent *event)
{
    if (isEnabled()) {
        if ((event->type() == QMouseEvent::MouseButtonRelease)
                && (event->button() == Qt::LeftButton)) {
            event->accept();
            m_bChecked = !m_bChecked;
            emit toggled(m_bChecked);
            m_timer.start(10);
        } else {
            event->ignore();
        }
    }
}

/* 大小改变事件 */
void SwitchButton::resizeEvent(QResizeEvent *event)
{
    m_nX = m_nHeight / 2;
    m_nY = m_nHeight / 2;
    QWidget::resizeEvent(event);
}

/* 默认大小 */
QSize SwitchButton::sizeHint() const
{
    return minimumSizeHint();
}

/* 最小大小 */
QSize SwitchButton::minimumSizeHint() const
{
    return QSize(2 * (m_nHeight + m_nMargin),
                 m_nHeight + 2 * m_nMargin);
}

/* 切换状态 - 滑动 */
void SwitchButton::onTimeout()
{
    if (m_bChecked) {
        m_nX += 1;
        if (m_nX >= width() - m_nHeight - m_nHeight / 2 ) {
            m_timer.stop();
            m_nX -= 1;
        }
    } else {
        m_nX -= 1;
        if (m_nX <= m_nHeight / 2) {
            m_timer.stop();
            m_nX += 1;
        }
    }
    update();
}

/* 返回开关状态 - 打开:true 关闭:false */
bool SwitchButton::isToggled() const
{
    return m_bChecked;
}

/* 设置开关状态 */
void SwitchButton::setToggle(bool checked)
{
    m_bChecked = checked;
    m_timer.start(10);
}

/* 设置背景颜色 */
void SwitchButton::setBackgroundColor(QColor color)
{
    m_background = color;
}

/* 设置选中颜色 */
void SwitchButton::setCheckedColor(QColor color)
{
    m_checkedColor = color;
}

/* 设置不可用颜色 */
void SwitchButton::setDisbaledColor(QColor color)
{
    m_disabledColor = color;
}

main.cpp

#include "mainwindow.h"

#include <QApplication>
#include <QFile>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    /* 指定文件 */
    QFile file(":/style.qss");

    /* 判断文件是否存在 */
    if (file.exists() ) {
        /* 以只读的方式打开 */
        file.open(QFile::ReadOnly);
        /* 以字符串的方式保存读出的结果 */
        QString styleSheet = QLatin1String(file.readAll());
        /* 设置全局样式 */
        qApp->setStyleSheet(styleSheet);
        /* 关闭文件 */
        file.close();
    }

    MainWindow w;
    w.show();
    return a.exec();
}

style.qss

QListWidget {
font-size: 30px;
outline:none;
}

QListWidget::item:active {
background: transparent;
}

QListWidget::item {
height:80;
}

QListWidget::item:selected:hover {
background:#22222222;
}

QListWidget::item:selected {
background:transparent;
color:#ee222222;
}

QPushButton#addAlarm {
border-image:url(:/icons/addalarm1.png);
background:transparent;
outline: none;
}

QPushButton#addAlarm:hover {
border-image:url(:/icons/addalarm2.png);
}

QPushButton#yesButton {
border: 1px solid #22222222;
border-radius: 25px;
background:#22222222;
outline:none;
}

QPushButton#yesButton:pressed {
background:#44222222;
color:white;
}

QPushButton#cancelButton {
border: 1px solid #22222222;
border-radius: 25px;
background:#22222222;
outline:none;
}

QPushButton#cancelButton:pressed {
background:#44222222;
color:white;
}

QScrollBar:vertical {
width:30px;
background:rgba(255, 255, 255, 100%)
}

QScrollBar::handle:vertical {
width:30px;
background:rgba(200, 200, 200, 20%);
border-radius:15px;
}

QScrollBar::add-line:vertical {
width:0px; height:0px;
}
QScrollBar::sub-line:vertical {
width:0px;
height:0px;
}
QScrollBar::handle:vertical:hover {
width:30px;
background:rgba(200, 200, 200, 80%);
border-radius:15px;
}
QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical {
background:rgba(255, 255, 255, 100%)
}

posted @ 2022-06-05 09:41  蘑菇王国大聪明  阅读(75)  评论(0编辑  收藏  举报