Evgenii Legotckoi
Evgenii Legotckoi20 серпня 2015 р. 08:45

Qt/C++ - Урок 009. QTimer – Як працювати з таймером?

Трохи поговоримо про застосування класу QTimer у Qt. Це невелика легка тема після серії об'ємних статей про QSqlTabelModel і наслідків, що випливають з неї. А то вже у самого сіра речовина закипає.

Таймери нам можуть знадобитися для створення опитування пристроїв по ЛОМ через стек TCP/IP з певною періодичністю або для щогодинної перевірки даних або активних підключень до сервера. Та навіщо завгодно!? І тут нам на допомогу приходить QTimer, який ми розглянемо на прикладі щомиті виведення часу в QLabel.

Програмний код був написаний QtCreator 3.3.1 на основі Qt 5.4.1.

Структура проекту для QTimer

Використовуємо мінімум файлів у нашому проекті:

  • QDataMapperWidget.pro - профайл;
  • mainwindow.h - заголовний файл основного вікна програми;
  • mainwindow.cpp - вихідний код вікна;
  • main.cpp - основний вихідний файл, з якого стартує програма;
  • mainwindow.ui - форма основного вікна програми;
  • А форму намалюємо в Дизайнері QtCreator. Втім, там і малювати нічого. Кинули QLabel у середину і готове.

mainwindow.h

Все, що нам потрібно для щастя в цьому проекті - це слот, який реагуватиме на спрацювання QTimer, та сам об'єкт цього класу.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFont>
#include <QTimer>
#include <QTime>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    /* Будем использовать только один слот */
private slots:
    void slotTimerAlarm();

private:
    Ui::MainWindow *ui;
    /* Да сам объект QTimer */
    QTimer *timer;
};

#endif // MAINWINDOW_H

mainwindow.cpp

А тепер кілька рядків із запуску таймера. По-моєму, коментарів більше, ніж коду. Зазвичай так на Assembler'і пишуть - 20% коду та 80% коментарів.

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    /* Немножко подшаманим QLabel, чтобы он был больше,
     * и заметнее в пустующем окне
     * */
    QFont font("Times", 28, QFont::Bold);
    ui->label->setFont(font);

    /* При первом запуске приложения поместим текущее время в QLabel
     * */
    ui->label->setText(QTime::currentTime().toString("hh:mm:ss"));

    /* Инициализируем Таймер и подключим его к слоту,
     * который будет обрабатывать timeout() таймера
     * */
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(slotTimerAlarm()));
    timer->start(1000); // И запустим таймер
}

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

/* Слот для обработки timeout() таймера
 * */
void MainWindow::slotTimerAlarm()
{
    /* Ежесекундно обновляем данные по текущему времени
     * Перезапускать таймер не требуется
     * */
    ui->label->setText(QTime::currentTime().toString("hh:mm:ss"));
}

Підсумок

В результаті при запуску виявимо, як кожну секунду у нас змінюється час у вікні програми

Приклад QTimer

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

N
  • 08 серпня 2017 р. 06:03

Добрый день! Появилась проблемка. Есть клиент-серверное приложение. Нужно послать с сервера к клиентам сообщение через определенные промежутки времени.  Реализовал это таким образом, что если у нас в QList лежит больше 1 сокета, то сначало посылается сообщение 1 клиенту, а потом включается таймер, но перед этим записывалось значение i в глобальную переменну(i взято из for). Использовал QTimer::singleshot(2000,this,Slot(slotZ()));. происходит вызов другой функции, где значение сокета берется из списка, по номеру как раз взятого из глобальной переменны, но почему то заместо того чтобы послать на 2 и 3 клиент через 2 сек сообщение, он посылает 2 сообщения на последний клиент.

void MyServer::slotWriteClient()
{
    if(lis.length() != 0)
    {
        QString str;


        for(int i = 0; i < lis.length(); i++)
        {
            socet = lis.at(i);
            if(lineEdit_4->text() == NULL){
                str = QString::number(i + 1) + " Client";
                sendToClient(socet,
                             "Server Response: Received \"" + str + "\""
                             );
            }
            else
            {
                str = lineEdit_4->text();
                
                if(i >= 1)
                {    

                    socn = i;
//                    QTimer *timer = new QTimer(this);
//                    timer->setInterval(2000);
//                    connect(timer, SIGNAL(timeout()), this, SLOT(slotZad(i)));

//                    timer->start();
                    QTimer::singleShot(2000, this, SLOT(slotZad()));

                }
                else
                    sendToClient(socet, str);
            }
        }
    }
    else
        m_ptxt->append("Пуст");
}

void MyServer::slotZad()
{
    QString str;

    qDebug() << socn;
    socet = lis.at(socn);
    str = lineEdit_4->text();
    sendToClient(socet, str);
}
Evgenii Legotckoi
  • 08 серпня 2017 р. 06:35
Добрый день!
Цикл for успевает отработать и сформировать переменную socn до того, как слот slotZad отработает хотя бы раз. При этом цикл for выполнится полностью. В результате в переменной socn будет использоваться переменная i равная последнему индексу.
Вам нужно переделать участок с QTimer::singleShot как-то иначе, например, прерывать цикл for, как только запустили QTimer::singleShot. А в слоте slotZad() инкрементировать переменную socn с проверкой на выход за пределы списка сокетов. И если есть ещё не обработанные сокеты, то запускать заново QTimer::singleShot в слоте slotZad().

Дополнительное code review:
Вместо этого
if(lineEdit_4->text() == NULL){
используйте метод QString::isEmpty()
if(lineEdit_4->text().isEmpty()){

P/S/ В дальнейшем создавайте темы с подобными вопросами на форуме сайта. Вопрос, конечно, имеет отношение к статье, но косвенное.

N
  • 08 серпня 2017 р. 07:30

Спасибо! Учту.

AC
  • 06 вересня 2022 р. 15:40

Вижу вы используете
new QTimer();
А кто будет память освобождать?
Почему вы вообще используете указатель QTimer *timer; а не объявите поле QTimer timer;?

Evgenii Legotckoi
  • 07 вересня 2022 р. 03:16
  • (відредаговано)

Потому что 7 лет назад я был бестолковее, чем сейчас.

f
  • 07 вересня 2022 р. 23:00

QTimer унаследован от QObject и ему передан this, идиома Qt предпологает что при вызове деструктора обьекта класса MyServer, обьект *timer тоже будет освобожден. Поправьте если ошибаюсь!

Evgenii Legotckoi
  • 12 вересня 2022 р. 03:04

Да, именно так. Но в коде без this написано - это ошибка в статье.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 01:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 01:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 06:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 03:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 09:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Слідкуйте за нами в соціальних мережах