SSD4 实验四

1.需求分析

分为两个部分:时间显示和时区显示修改。时间显示包括日期显示和当前时分秒显示。日期在日历中展示出来,当前时分秒使用三个spinner。时区通过地图显示,通过地图上方的下拉列表框修改。点击“Apply”和”Cancel”的时候分别更改/不更改内容;点击”OK”时显示更改后的内容并退出程序。

2.概要设计

九种数据:

  1. 秒钟设置(0-59)
  2. 分钟设置(0-59)
  3. 小时设置(24小时制,0-23)
  4. 当前日
  5. 当前月份
  6. 当前年份
  7. 当前选择的时区时间
  8. 当前时区相对标准时间的偏差
  9. 当前选择的时区的标题

3.详细设计

日历:通过Qt的日历组件实现。
时间:通过三个spinbox实现。改变和改变的关联通过槽函数实现。
两个不同界面:通过tabWidget组件实现。
时区:通过Combo box显示。
时钟:通过QPaintEvent()函数实现,分别画时针、分针、秒针。
地图的显示:通过在图片上增加一个透明度为120
时区的改变:当点击Apply按钮时,将框移动到当前时区对应的地图位置(和箭头相同);当点击Cancel时,将下拉列表框的内容恢复为改变之前的内容(通过一个变量保存),将绿色箭头恢复到原来位置。点击OK按钮时,退出程序。

4.调试分析

在写弹出窗口的时候出现了这样的错误:
在这里插入图片描述

百度发现这个问题很少,在stackoverflow上看到一个人在使用印度语的时候出现了这个问题;后来看到有人说Qt的bug report里有这个问题:[OpenType-Rendering-Issue] (https://bugreports.qt.io/browse/QTBUG-30213),在转换时会无法输出文字信息,而是显示方块(下图):不能解决。问了同学,也没有实现这个实验要求。所以我就选择不显示messageBox,在OK和apply的时候只执行更改确认的操作。
在这里插入图片描述

5.用户使用说明

通过spinbox改变当前时间;通过下拉列表框选中需要改到的时区,会在下面用箭头提示地图上的位置。点击”OK”或”Apply”可以改变当前时区,点击”Cancel”会取消改变并将箭头和下拉列表框的内容恢复之前的内容。

6.测试结果

直接运行:显示当前北京时间,时区默认为(GMT+8:00)。
Date&TimeTimeZone
对时区的改变:
在下拉列表框中选择想要的内容:(此处选择GMT-11:00)
在这里插入图片描述
点击选中:
绿色箭头指向目的时区,红框不改变位置
点击“Cancel“:
返回当前时区,时间不改变
点击”Apply”:
(时区改变,当前时间也改变)
Date&Time里的Current Time Zone也改变显示内容为当前时区,显示时间也改变
对时间的改变:
当前时间:
当前时间
改变分钟的spinbox:(减小):
spinbox显示时间改变,时钟显示也改变
增加到临界点:
在这里插入图片描述
继续增加:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.附录

Time_adjust.pro
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    timezone_map_small.qrc

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QTimer>
#include<QPainter>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    bool eventFilter(QObject *obj, QEvent *event);
    void paintEvent(QPaintEvent* );

public slots:
    void do_second();

private slots:
    void on_OKButton_clicked();

    void on_secondSpinBox_valueChanged(int arg1);

    void on_minuteSpinBox_valueChanged(int arg1);

    void on_hourSpinBox_valueChanged(int arg1);

    void on_cancelButton_clicked();

    void on_applyButton_clicked();

    void on_comboBox_currentIndexChanged(int index);

private:
    Ui::MainWindow *ui;
    QTimer* timer1s;
    int currentTimeZoneIndex;
};
#endif // MAINWINDOW_H

mainwindow.h
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include<QMessageBox>
#include<QLabel>
#include<QMovie>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //显示地图图片
    QMovie *movie = new QMovie("D:/code/Qt/time_adjust/timezone_map_small.gif");
    ui->mapSetTimeLabel->setMovie(movie);
    movie->setScaledSize(ui->mapSetTimeLabel->size());
    movie->start();

    //显示当前北京时间
    ui->comboBox->setCurrentIndex(20);
    ui->arrowLabel->move(480, 320);
    ui->frameorkLabel->move(480, 90);

    //获取当前时间
    QDateTime current_date_time = QDateTime::currentDateTime();
    QTime current_time = current_date_time.time();
    int hour = current_time.hour();
    int minute = current_time.minute();
    int second = current_time.second();

    //保存当前时间
    currentTimeZoneIndex = 20;

    //将当前时间显示在spinbox中
    ui->hourSpinBox->setValue(hour);
    ui->minuteSpinBox->setValue(minute);
    ui->secondSpinBox->setValue(second);

    setWindowTitle("time showing");
    setWindowIconText("Good");
//    ui->hourSpinBox->setAttribute(Qt::WA_Hover,true);//开启悬停事件
//    ui->hourSpinBox->installEventFilter(this);       //安装事件过滤器
//    ui->minuteSpinBox->setAttribute(Qt::WA_Hover,true);
//    ui->minuteSpinBox->installEventFilter(this);
//    ui->secondSpinBox->setAttribute(Qt::WA_Hover,true);
//    ui->secondSpinBox->installEventFilter(this);

    //设置计时器每秒钟秒数+1
    timer1s = new QTimer();
    timer1s->setInterval(1000);
    timer1s->start();

    //连接信号与槽
    connect(timer1s, SIGNAL(timeout()), this, SLOT(do_second()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::do_second(){
    int value = ui->secondSpinBox->value();
    value++;
    ui->secondSpinBox->setValue(value);

    //repaint
    repaint();
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{

    //事件过滤器
    if(obj == ui->hourSpinBox||obj == ui->minuteSpinBox||obj == ui->secondSpinBox) {
        if(event->type() == QEvent::HoverEnter) {
            timer1s->stop();
            return true;
        }else if(obj == ui->hourSpinBox){
            if(event->type() == QEvent::HoverLeave){
                timer1s->start();
                return true;
            }
        }
    }
    return QWidget::eventFilter(obj,event);
}

void MainWindow::on_OKButton_clicked()
{
    int adjustment = ui->comboBox->currentIndex()-20;//设置相对于北京时间的更改
    int x = 120 + ui->comboBox->currentIndex()*18;
    ui->arrowLabel->move(x, 320);
    ui->frameorkLabel->move(x, 90);

    //change timezone show
    QString data = ui->comboBox->currentText();
    ui->timezoneLabel->setText("Current Time Zone:"+data);
    currentTimeZoneIndex = ui->comboBox->currentIndex();

    //change time show
    QDateTime current_date_time = QDateTime::currentDateTime();
    QTime current_time = current_date_time.time();
    int hour = current_time.hour();
    int minute = current_time.minute();
    int second = current_time.second();
    hour += adjustment;

    //将改变后的时间显示在spinbox中
    ui->hourSpinBox->setValue(hour);
    ui->minuteSpinBox->setValue(minute);
    ui->secondSpinBox->setValue(second);

    this->close();
}

void MainWindow::on_secondSpinBox_valueChanged(int arg1)
{
    if(arg1==-1){
        //减少到-1
        //改变分钟:原来数值-1
        int min = ui->minuteSpinBox->value();
        min--;
        ui->minuteSpinBox->setValue(min);

        //改变秒钟:59
        ui->secondSpinBox->setValue(59);
    }else if(arg1==60){
        //增加到60
        //改变分钟:原来数值+1
        int min = ui->minuteSpinBox->value();
        min++;
        ui->minuteSpinBox->setValue(min);

        //改变秒钟:0
        ui->secondSpinBox->setValue(0);
    }
    //repaint
    repaint();
}

void MainWindow::on_minuteSpinBox_valueChanged(int arg1)
{
    if(arg1==-1){
        //减少到-1
        //改变时钟:原来数值-1
        int hour = ui->hourSpinBox->value();
        hour--;
        ui->hourSpinBox->setValue(hour);

        //改变分钟:59
        ui->minuteSpinBox->setValue(59);
    }else if(arg1==60){
        //增加到60
        //改变时钟:原来数值+1
        int hour = ui->hourSpinBox->value();
        hour++;
        ui->hourSpinBox->setValue(hour);

        //改变分钟:0
        ui->minuteSpinBox->setValue(0);
    }
    //repaint
    repaint();
    return;
}

void MainWindow::on_hourSpinBox_valueChanged(int arg1)
{
    if(arg1==-1){
        ui->hourSpinBox->setValue(23);
    }else if(arg1==24){
        ui->hourSpinBox->setValue(0);
    }
    //repaint
    repaint();
}

void MainWindow::on_cancelButton_clicked()
{
    QDateTime current_date_time = QDateTime::currentDateTime();
    QTime current_time = current_date_time.time();
    int hour = current_time.hour();
    int minute = current_time.minute();
    int second = current_time.second();

    //将改变后的时间显示在spinbox中
    ui->hourSpinBox->setValue(hour);
    ui->minuteSpinBox->setValue(minute);
    ui->secondSpinBox->setValue(second);

    //将comboxBox的内容和绿色箭头恢复
    ui->comboBox->setCurrentIndex(currentTimeZoneIndex);
    int x = 120 + currentTimeZoneIndex*18;
    ui->arrowLabel->move(x, 320);

//    //弹出提示框
//    QMessageBox* msg = new QMessageBox(this);
//    msg->setWindowTitle("Date_and_time");
//    msg->setText("Cancelled...\n=========="
//                 "\nYear = "+QString(year)+
//                 "\nMonth = "+QString(current_date.month())+
//                 "\nDay = "+QString(current_date.day())+
//                 "\nHour = "+QString(hour)+
//                 "\nMinute = "+QString(minute)+
//                 "\nSecond = "+QString(second)+
//                 "\nTimezone = "+QString(currentTimeZone)+
//                 "\nAuto Daylight = false"+
//                 "\n=========="+
//                 "\n(Time not saved)"
//                 );
//    msg->show();
}

void MainWindow::on_applyButton_clicked()
{
    int adjustment = ui->comboBox->currentIndex()-20;//设置相对于北京时间的更改

    //change timezone show
    QString data = ui->comboBox->currentText();
    ui->timezoneLabel->setText("Current Time Zone:"+data);
    int x = 120 + ui->comboBox->currentIndex()*18;
    ui->arrowLabel->move(x, 320);
    ui->frameorkLabel->move(x, 90);
    currentTimeZoneIndex = ui->comboBox->currentIndex();


    //change time show
    QDateTime current_date_time = QDateTime::currentDateTime();
    QTime current_time = current_date_time.time();
    int hour = current_time.hour();
    int minute = current_time.minute();
    int second = current_time.second();
    hour += adjustment;

    //将改变后的时间显示在spinbox中
    ui->hourSpinBox->setValue(hour);
    ui->minuteSpinBox->setValue(minute);
    ui->secondSpinBox->setValue(second);
}

void MainWindow::paintEvent(QPaintEvent *)
{
    static const QPoint hour[3] = {
        QPoint(14, 15),
        QPoint(-14, 15),
        QPoint(0, -110)
    };
    static const QPoint minute[3] = {
        QPoint(11, 13),
        QPoint(-11, 13),
        QPoint(0, -170)
    };
    static const QPoint second[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -210)
    };
    int size=qMin(width(),height());
//    QTime time=QTime::currentTime();//获取系统当前时间
    int current_hour = ui->hourSpinBox->text().toInt();
    int current_minute = ui->minuteSpinBox->text().toInt();
    int current_second = ui->secondSpinBox->text().toInt();
    QPainter p(this);//创建画家对象
    p.setRenderHint(QPainter::Antialiasing);//防止图形走样
    p.translate(width()/1.25,height()/2);//平移坐标系置中心
    p.scale(size/920.0,size/920.0);//缩放

    QBrush brush;//定义画刷
    brush.setColor(QColor(245,182,96));//设置画刷颜色
    brush.setStyle(Qt::SolidPattern);//设置样式


    QPen pen;//定义画笔
    pen.setWidth(18);//设置画笔宽度
    pen.setColor(QColor(205,214,216));//rgb设置颜色
    pen.setStyle(Qt::SolidLine);//设置风格
    p.setPen(pen);//将画笔交给画家
    p.drawEllipse(QPoint(0,0),280,280);//画圆
    pen.setColor(Qt::white);
    pen.setWidth(160);//设置画笔宽度
    p.setPen(pen);//将画笔交给画家
    p.drawEllipse(QPoint(0,0),160,160);//画圆
    //画时针
    p.setBrush(brush);//将画刷交给画家
    p.setPen(Qt::NoPen);
    p.save();//保存当下状态
    p.rotate(30.0*(current_hour+current_minute/60.0));//图形旋转,以原点为旋转中心,顺时针水平旋转对应时针的角度
    p.drawConvexPolygon(hour,3);//画时针这个凸多边形,第一个参数为所有的点,第二个参数为点的个数
    p.restore();//恢复上一次保存的结果,和save()成对出现

    //绘制小时线
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(5);
    pen.setColor(Qt::black);
    p.setPen(pen);
    for(int i=0;i<12;i++)
    {
        p.drawLine(0,268,0,276);//画小时线
        p.drawText(-5,-235,QString::number(i));//表明小时数
        p.rotate(30);//每画一次旋转30度
    }

    //画分针
    p.setPen(Qt::NoPen);
    p.setBrush(QColor(144,199,247));
    p.save();//保存当下状态
    p.rotate(6.0*(current_minute+current_second/60.0));//顺时针旋转至分针的位置
    p.drawConvexPolygon(minute,3);//画分针这个凸多边形,第一个参数为所有的点,第二个参数为点的个数
    p.restore();//恢复上一次保存的结果,和save()成对出现

    //绘制分钟线
    pen.setStyle(Qt::SolidLine);
    pen.setColor(QColor(0,0,0));
    pen.setWidth(1);
    p.setPen(pen);
    for(int i=0;i<60;i++)
    {
        if((i%5)!=0)
        p.drawLine(0,265,0,276);//5的倍数时不画,因为有小时线
        p.rotate(6);//每画一次旋转6度
    }

    //画秒线
    p.setPen(Qt::NoPen);
    p.setBrush(QColor(119,217,175));
    p.save();
    p.rotate(6*current_second);//顺时针旋转至秒针的位置
    p.drawConvexPolygon(second, 3);//画秒针这个凸多边形,第一个参数为所有的点,第二个参数为点的个数
    p.restore();

    //画圆心
    p.setBrush(Qt::black);
    p.setPen(Qt::white);
    p.save();
    p.drawEllipse(QPoint(0,0),3,3);//画圆心
    p.restore();

    //表明上午还是下午
    p.setPen(Qt::black);
    if(current_hour>=12)
    p.drawText(-6,-50,"PM");//画文本区
    else
    p.drawText(-6,-50,"AM");//画文本区
}

void MainWindow::on_comboBox_currentIndexChanged(int index)
{
    int x = 120 + index*18;
    ui->arrowLabel->move(x, 320);
}

main.cpp
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值