Funkcja wywoływana co pewien czas

0

Witam. Jest może w C++ funkcja która będzie wywoływała inną funkcję co pewien czas? Wiem że są sleep oraz delay. Ale mnie chodzi raczej aby zawsze co np 1 sekundę była wywoływana jakaś funkcja niezależnie od tego co dzieje się w programie. Taki wątek który wykonuje operacje co pewien czas.

0

Załóż osobny wątek przez pthread(), działający w pętli i wywołujący Twoją funkcję.

0

Udało mi się z pomocą QT4 i klasy QTimer.

0

Jak to zrobiłeś? Ja mam podobny problem.
Mianowicie: zrobiłem klasę diody, wsadziłem 7 diod w moduł(osobna klasa) i cały moduł wyświetlam w mainwindow. I tak z poziomu mainwindow włączam lub wyłączam kontrolki modul->setOn(index). Przy tym mechaniźmie chcę pozostać i jednocześnie rozbudować diodę o mruganie. W tym celu dioda ma zmienna mode (1-swiatlo ciagle, 2-migowe wolne, 3-migowe szybkie). mode oczywiście ustawiam za pośrednictwem modulu. Niestety w przypadku mode > 1 obiekt i tak zachowuje się tak samo jak w sytuacji przy mode = 1; czyli timer albo nie startuje albo nie daje sygnalu, albo(i raczej na pewno) ja coś źle rozumiem.

dioda.h

 #ifndef DIODA_H
#define DIODA_H

#include <QWidget>
#include <QPainter>
#include <QTimer>

#define FAST_DELAY 250
#define SLOW_DELAY 500

class dioda : public QWidget{
    Q_OBJECT
private:
    void paintEvent(QPaintEvent *);
    void blink(int delay);
    QColor paintColor;
    QColor onColor;
    QColor offColor;
    bool state;
    int shift;
    int radius;
    int mode;
    QTimer *timer;

public:
    dioda();
    void setOnColor(QColor color);
    void setOffColor(QColor color);
    bool setMode(int i);
    void setShift(int s);
    void setRadius(int r);

public slots:
    void setOn();
    void setOff();
};

#endif // DIODA_H

dioda.cpp

#include "dioda.h"

dioda::dioda(){
    offColor = Qt::gray;
    onColor = Qt::white;
    paintColor = offColor;
    shift = 10;
    radius = 10;
    state = false;
    mode = 1;
    timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(setOn()));
}

void dioda::paintEvent(QPaintEvent *){
    QPainter dioda(this);
    dioda.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
    QRadialGradient gradient(shift+radius/2, shift+radius/2, radius/2, shift+radius/4, shift+radius/4);
    paintColor  == Qt::black ? gradient.setColorAt(0.2, Qt::darkGray) : gradient.setColorAt(0.2, Qt::white);
    gradient.setColorAt(0.8, paintColor);
    gradient.setColorAt(1.0, Qt::black);
    dioda.setPen((QPen(Qt::black, 0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin)));
    dioda.setBrush(QBrush(gradient));
    dioda.drawEllipse(shift,shift,radius,radius);
}

void dioda::setOnColor(QColor color){
    onColor = color;
    repaint();
}

void dioda::setOffColor(QColor color){
    onColor = color;
    repaint();
}

bool dioda::setMode(int i){
    if(i<1 || i>3) return false;
    mode = i;
    /*if(i>1) {
        timer = new QTimer(this);
        connect(timer,SIGNAL(timeout()),this,SLOT(setOn()));
    }*/
    return true;
}

void dioda::setOn(){
    switch(mode){
        case 1:
            paintColor = onColor;
            state = true;
            repaint();
            break;
        case 2:
            blink(SLOW_DELAY);
            break;
        case 3:
            blink(FAST_DELAY);
            break;
    default:break;
    }
}

void dioda::setOff(){
    paintColor = offColor;
    state = false;
    repaint();
}

void dioda::setShift(int s){
    shift = s;
    repaint();
}

void dioda::setRadius(int r){
    radius = r;
    repaint();
}

void dioda::blink(int delay){
    if(state) paintColor = offColor;
    else paintColor = onColor;
    repaint();
    //timer->setInterval(delay);
    //timer->setSingleShot(true);
    timer->start(delay);
}

 

modul.cpp - fragment przykładu sterowania kontrolką led

 led = new dioda();
led->setMode(2);
led->setOn();
0

temat jest stary, wiec watpie zeby Ci odpowiedzial
mozesz zrobic to na dwa sposoby

  1. (lepszy) uruchom osobny watek ktory bedzie sobie odliczal czas i co jakis N wywolywal ta funkcje
  2. gdzies w jakies funkcji ktora wykonuje sie co kazdy obieg programu wrzuc to samo co trzeba napisac w 1

napisanie kodu bedzie praktycznie takie samo, jednak jest roznica gdzie go "umiescisz"

0

Nigdy nie używałem jeszcze wątków. Proponujesz abym utworzył klasę dziedziczącą po QThread która z każdym shotem swojego prywatnego timera będze wywoływał funkcję setOn() z klasy dioda, a obiekt nowej klasy tworzyć wewnątrz obiektu diody, tak?

mainwindow
->modul
->dioda
->wątek
(?)

@Edit
uzależniłem się od zmienej state ale w metodzie blink jej niezmieniałem. wystarczyło dodać state=!state;

void dioda::blink(int delay){
    if(state) paintColor = offColor;
    else paintColor = onColor;
    
    state=!state;

    repaint();
    //timer->setInterval(delay);
    //timer->setSingleShot(true);
    timer->start(delay);
}
  

i działa ale tylko w ostatnim utworzonym obiekcie tego typu - dlaczego?

0

przykładowe użycie timera,

	QTimer* timer = new QTimer;
	timerHandles_[addr] = std::unique_ptr<QTimer>(timer); // mapa, która trzyma timer
	timerTasks_[timer] = f; // mapa, która trzyma zadanie dla timera (std::function<void()> const&)
	connect(timer, SIGNAL(timeout()),
			this, SLOT(repeatLastMessage())); // funkcja handlująca sygnał timeout, sygnał ten jest emitowany co czas, który podasz w start.
	timer->start(msec); // start

te mapy mam dlatego, aby móc obsłużyć kilka timerów w 1 funkcji handlującej (repeatLastMessage()), na podstawie obiektu który wyemitował sygnał (QObject::sender()), wybierasz zadanie dla timera

0

a czym jest f przy timerTasks_[timer] = f;

0

jak masz 1 timer to ten cały mechanizm jest zbędny, implementujesz logikę bezpośrednio w repeatLastMessage i nie bawisz się w trzymanie timerów i ich zadań

1
// nagłówek, musi być bo qt moc nie ogarnie tego w main
#ifndef OBJ_H
#define OBJ_H

#include <memory>

#include <QObject>
#include <QTimer>

class Obj : public QObject
{
	Q_OBJECT
public:
	explicit Obj() : timer_(nullptr) {}

	void startMyTimer(int msecs);
public slots:
	void repeatTask();
private:
	std::unique_ptr<QTimer> timer_;
};

void Obj::startMyTimer(int msecs)
{
	if(timer_) {
		return;
	} else {
		timer_ = std::make_unique<QTimer>();
		QObject::connect(timer_.get(), SIGNAL(timeout()),
				this, SLOT(repeatTask()));
		timer_->start(msecs); // start
	}
}

void Obj::repeatTask()
{
	std::cout << "Timer here !\n";
}

#endif // OBJ_H

// main
#include <iostream>

#include <QCoreApplication>

#include "obj.h"

int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);
	Obj obj;
	obj.startMyTimer(2000);

	a.exec();
}

zbuduj sobie projekt i zobacz jak to działa

1 użytkowników online, w tym zalogowanych: 0, gości: 1