Evgenii Legotckoi
Evgenii LegotckoiТам. 20, 2015, 8:45 Т.Ж.

Qt/C++ - Сабақ 009. QTimer немесе Qt тілінде таймермен қалай жұмыс істеу керек?

Qt-де QTimer класын пайдалану туралы аздап сөйлесейік. Бұл QSqlTabelModel және оның салдары туралы ұзақ мақалалар сериясынан кейінгі шағын жеңіл тақырып. Ал содан кейін қазірдің өзінде өте сұр зат қайнайды.

Белгілі бір жиілікте TCP/IP стегі арқылы жергілікті желідегі құрылғыларды сұрау немесе деректерді немесе серверге белсенді қосылымдарды сағат сайын тексеру үшін бізге таймер қажет болуы мүмкін. Иә, кез келген нәрсе үшін!? Мұнда QTimer көмекке келеді, біз QLabel-те уақыттың әрбір екінші шығуының мысалын пайдалана отырып қарастырамыз.

Код Qt 5.4.1 негізінде QtCreator 3.3.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
  • Там. 8, 2017, 6: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
  • Там. 8, 2017, 6: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
  • Там. 8, 2017, 7:30 Т.Ж.

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

AC
  • Қыр. 6, 2022, 3:40 Т.Қ.

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

Evgenii Legotckoi
  • Қыр. 7, 2022, 3:16 Т.Ж.
  • (өңделген)

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

f
  • Қыр. 7, 2022, 11 Т.Қ.

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

Evgenii Legotckoi
  • Қыр. 12, 2022, 3:04 Т.Ж.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз