Машина времени

  • Постановка задачи
  • Программа «Машина времени» определяет Юлианский день, показывает текущее время и дату, календарь (без дополнительных опций) и секундомер в виде семисегментного LCD-дисплея

  • Внешний вид приложения
  • 12

  • Файл widget.h
  • #ifndef WIDGET_H
    #define WIDGET_H
    #include <QToolBox>
    #include <QLabel>
    #include <QVBoxLayout>
    #include <QHBoxLayout>
    #include <QCalendarWidget>
    #include <QStackedLayout>
    #include <QPushButton>
    #include <QTimer>
    #include <QGroupBox>
    #include <QComboBox>
    #include <QLCDNumber>
    
    //#include "ui_widget.h"
    
    class Widget : public QWidget
    {
        Q_OBJECT
        
    public:
        explicit Widget(QWidget *parent = 0);
    
    private:
        QLabel *tab1;
        QLabel *tab2;
        QLabel *tab3;
        QLabel *lbl;
        QLabel *lbls1;
        QLabel *lbls2;
        QPushButton *extb;
        QPushButton *bjd;
        QPushButton *bdate;
        QPushButton *bcal;
        QPushButton *bcurt;
        QPushButton *bsect;
        QPushButton *bstop;
        QPushButton *breset;
        QToolBox *tbx;
        QVBoxLayout *vboxl;
        QVBoxLayout *vboxr;
        QHBoxLayout *hbox;
        QVBoxLayout *vboxtab1;
        QVBoxLayout *vboxtab2;
        QCalendarWidget *calnd;
        QStackedLayout *stack;
        QTimer *timer;
        QTimer *timer2;
        QGroupBox *gbox1;
        QGroupBox *gbox2;
        QComboBox *cbox;
        QLCDNumber *lcd;
        int z;
    
    private slots:
        void bjd_click();
        void bdate_click();
        void bcal_click();
        void bcurt_click();
        void bsect_click();
        void bstop_click();
        void breset_click();
    
    };
    
  • Файл widget.cpp
  • #include "widget.h"
    #include <QString>
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent)
    {
        resize(500,300);
        setWindowTitle(tr("Time Machine"));
        hbox = new QHBoxLayout(this);
        // Лэйаут 1 слева
        vboxl = new QVBoxLayout(this);
        // QStackedLayout не предоставляет пользователю никаких средств переключения страниц.
        // Для переключения страниц используем QComboBox который будет
        // содержать заголовки страниц QStackedLayout
        cbox = new QComboBox(this);
        cbox->addItem("Calendar");
        cbox->addItem("Date");
        cbox->addItem("Julian Day");
        vboxl->addWidget(cbox);
    
        // Будем использовать Тулбокс
        tbx = new QToolBox(this);
    
        // Его первый таб и <его> содержимое
        tab1 = new QLabel(this);
        vboxtab1 = new QVBoxLayout(this);
        bdate = new QPushButton("Date", this);
        bjd = new QPushButton("Julian Day", this);
        bcal = new QPushButton("Calendar", this);
        vboxtab1->addWidget(bdate);
        vboxtab1->addWidget(bjd);
        vboxtab1->addWidget(bcal);
        vboxtab1->addStretch(0);
        // На вкладку можно добавить только компонент, но не компоновщик.
        // Поэтому компоненты группируем в QGroupBox.
        gbox1 = new QGroupBox("",this);
        gbox1->setLayout(vboxtab1);
        tbx->addItem(gbox1, "Day");
    
    
        // Второй таб и его содержимое
        tab2 = new QLabel(this);
        vboxtab2 = new QVBoxLayout(this);
        bcurt = new QPushButton("Current", this);
        bsect = new QPushButton("Start Stopwatch", this);
        bstop = new QPushButton("Stop Stopwatch", this);
        breset = new QPushButton("Reset", this);
        vboxtab2->addWidget(bcurt);
        vboxtab2->addWidget(bsect);
        vboxtab2->addWidget(bstop);
        vboxtab2->addWidget(breset);
        vboxtab2->addStretch(0);
        gbox2 = new QGroupBox("",this);
        gbox2->setLayout(vboxtab2);
        tbx->addItem(gbox2, "Time");
    
        // Третий таб и его содержимое...
        // Впрочем, отдаю его вам на растерзание))
        tab3 = new QLabel(this);
        tbx->addItem(tab3, "Calc");
    
        // Развернутый таб по умолчанию
        tbx->setCurrentIndex(0);
        // Добавляем Тулбокс в лэйаут
        vboxl->addWidget(tbx);
    
        // Добавляем ещё что-то, например, метку
        lbl = new QLabel(this);
        lbl->setText("<b>This programm of Time Machine</b>");
        vboxl->addWidget(lbl);
    
        hbox->addLayout(vboxl);
    
        // 2 лэйаут по горизонтали справа
        vboxr = new QVBoxLayout(this);
        // Tам будет QStackedLayout:
        stack = new QStackedLayout(this);
        calnd = new QCalendarWidget(this);
        stack->addWidget(calnd);  // 0
        lbls1 = new QLabel(this);
        lbls1->setText("Date and Time");
        stack->addWidget(lbls1);  // 1
        lbls2 = new QLabel(this);
        lbls2->setText("JD");
        stack->addWidget(lbls2);  // 2
        // Подключаем "Электронный" дисплей
        lcd = new QLCDNumber(this);
        lcd->setSegmentStyle(QLCDNumber::Filled);
        stack->addWidget(lcd);    // 3
        vboxr->addLayout(stack);
    
        // И кнопка для удобного закрытия окна
        extb = new QPushButton("Exit");
        vboxr->addWidget(extb);
    
        // Собираем все вместе
        hbox->addLayout(vboxr);
        setLayout(hbox);
    
        // Сигналы
        connect(extb, SIGNAL(clicked()), this, SLOT(close()));
        // Вкладки тулбокса приводятся только для иллюстрации
        // Вы можете сами добавить полезные функции или вообще убрать тулбокс из приложения
        connect(cbox, SIGNAL(activated(int)), stack, SLOT(setCurrentIndex(int)));
        // Тоже самое делаем кнопками в первом табе, но выводим полезную информацию
        connect(bjd, SIGNAL(clicked()), this, SLOT(bjd_click()));
        connect(bdate, SIGNAL(clicked()), this, SLOT(bdate_click()));
        connect(bcal, SIGNAL(clicked()), this, SLOT(bcal_click()));
        // Сигналы для кнопок во втором табе
        // Связываем сигнал переполнения таймера со слотом
        // Но стартуем таймер после вызова, например, bcurt_click(), по клику на кнопке
        timer = new QTimer;
        connect(timer,SIGNAL(timeout()), this, SLOT(bcurt_click()));
        connect(bcurt, SIGNAL(clicked()), this, SLOT(bcurt_click()));
        z = 1;
        // Конечно, можно обойтись и одним!
        timer2 = new QTimer;
        connect(timer2, SIGNAL(timeout()),this,SLOT(bsect_click()));
        connect(bsect, SIGNAL(clicked()), this, SLOT(bsect_click()));
    
        connect(bstop, SIGNAL(clicked()), this, SLOT(bstop_click()));
        connect(breset, SIGNAL(clicked()), this, SLOT(breset_click()));
    
    }
    
    // Функции кнопок первого таба
    void Widget::bjd_click(){
        if (timer) {timer->stop();}
        if (timer2) {timer2->stop();}
        stack->setCurrentIndex(2);
        // Юлианский день
        int jd = QDate::currentDate().toJulianDay();
        QString str1;
        str1.setNum(jd);
        lbls2->setText("<div align=\"center\"><b><big>Julian Day = " + str1 + "</b></big></div>");
    }
    void Widget::bdate_click(){
        // Текущая дата и время
        if (timer) {timer->stop();}
        if (timer2) {timer2->stop();}
        stack->setCurrentIndex(1);
        QString str1, str2;
        str1 = QDate::currentDate().toString("dd.MM.yyyy");
        str2 = QTime::currentTime().toString("hh:mm:ss");
        lbls1->setText("<div align=\"center\">Date and Time:</div><div align=\"center\"><b><big>" +
                       str1 + "</b></big></div><div align=\"center\"><b><big>" +
                       str2 + "</b></big></div>");
    
    }
    void Widget::bcal_click(){
        if (timer) {timer->stop();}
        if (timer2) {timer2->stop();}
        stack->setCurrentIndex(0);
    }
    // Функции кнопок второго таба
    void Widget::bcurt_click(){
        // "Идущие часы"
        // Чтобы не было конфликта с timer2
        if (timer2) {timer2->stop();}
        stack->setCurrentIndex(1);
        //Задаем время срабатывания таймера (в мс)
        timer->start(1000);
        lbls1->setText("<div align=\"center\">Current Time:</div><div align=\"center\"><b><big>" +
                       QTime::currentTime().toString() + "</b></big></div>");
    }
    void Widget::bsect_click(){
        // Секундомер
        // Чтобы не было конфликта с timer
        if (timer) {timer->stop();}
        stack->setCurrentIndex(3);
        timer2->start(1000);
        lcd->display(z++);
    }
    
    void Widget::bstop_click()
    {
        if (timer2) {timer2->stop();}
    }
    
    void Widget::breset_click()
    {
        if (timer2) {timer2->stop();}
        timer2->start(1000);
        z = 0;
        lcd->display(z++);
    }
    
  • Файлы проекта
  • time_machine

  • Постановка задачи для самостоятельной работы
  • При проектировании данного приложения ставились задачи совместного использования классов QToolBox, QCalendarWidget, QStackedLayout, QTimer, QComboBox и QLCDNumber. Вместе с тем, некоторые виджеты, используемые в приложении не были доведены до полезного применения. Третья вкладка QToolBox пуста и требует заполнения. Попробуйте развернуть здесь конвертер величин, например, JD<->UTC, JD<->Unix Time и т. п. Можно также разместить аналоговые часы (ссылка ниже; попробуйте разобраться с графикой самостоятельно). Вкладки QComboBox тоже ничего полезного не выводят и здесь раздолье для вашего творчества. Такой сложный виджет, как календарь, не предоставляет дополнительных инструментов. Однако виджет может быть задействован в приложении с большой пользой, так как может работать с датой выбранной пользователем, а не системного таймера.

  • Ссылки
  • Пример «Analog Clock»
    Все классы

Добавить комментарий