2012-08-16 5 views
0

작업 목록을 보유하는 응용 프로그램을 만들려고하고 있으며 마감일이 다가 오면 마감일을 맞으면 기능 (팝업 표시)을 실행하려고합니다.QT C++은 특정 시간에 함수가 실행될 때까지 대기합니다.

나는이 있습니다

#ifndef TIMER_H 
#define TIMER_H 
#include <QWidget> 
#include <QTimer> 
#include <QtGui> 
#include <QObject> 

class Timer : public QWidget 
{ 
    Q_OBJECT 
public: 
    Timer(QWidget * parent = 0); 
    void setTimer(QString title, QString description, QDate date, QTime reminderTime); 
public slots: 
    void showWarning() {QString show = tit; 
         QPushButton * thanks = new QPushButton(QObject::tr("Thank you for reminding me!")); 
         show.append("\n"); 
         show.append(des); 
         QMessageBox popup; 
         popup.setText(show); 
         popup.setWindowTitle("Calendar : Reminder"); 
         popup.setDefaultButton(thanks); 
         popup.exec(); 
         } 
private: 
    QString tit; 
    QString des; 
    QDateTime now; 
    QDateTime timeoftheaction; 
    QTimer *timer; 
}; 

CPP 파일 :

#endif // TIMER_H 
#include "timer.h" 
#include <iostream> 
using namespace std; 

Timer::Timer(QWidget * parent) 
    : QWidget(parent) 
{ 
} 

void Timer::setTimer(QString title, QString description, QDate date, QTime reminderTime) 
{ 
    now.currentDateTime(); 
    timer = new QTimer; 
    tit = title; 
    des = description; 
    timeoftheaction.setDate(date); 
    timeoftheaction.setTime(reminderTime); 
    connect(timer, SIGNAL(timeout()),this,SLOT(showWarning())); 
    timer->start(now.secsTo(timeoftheaction)*1000); 
} 

그러나 기능 showWarning이 ... 컴파일 오류가, 기능 showWarning 완벽

(시험 없음) 작품이라는되고 있지 않습니다

오류가 연결에 있다고 생각하지만 확실하지 않습니다 ...

+1

'now.secsTo (timeoftheaction) * 1000'이 실제로 당신이 생각하는 것을 당신에게주는 것을 확인 했습니까? – enderland

+0

타이머를 : timer-> start (1)'로 설정하면 즉시 작동합니까? 그렇다면 @ 엔더 랜드의 제안은 맞습니다 – jdi

+0

이것은 해결책이 될 수도 있습니다 : http://stackoverflow.com/questions/11996706/qt-c-wait-till-specific-time-to-execute-function/14144614 # 14144614 – formiaczek

답변

2

짧은 답변 :

변경 :

now.currentDateTime(); 

로는
now = QDateTime::currentDateTime(); 

기름 한 답 :

currentDateTime() 실제로 대신 기존 개체를 변경하는 정적 기능입니다 새 QDataTime을 반환합니다. 피하십시오. 멤버 함수로 부르기는하지만 여전히 정적 함수라고 불리우며 객체는 그대로 유지됩니다. 이는 여전히 유효하지 않습니다.

잘못된 데이터 시간에 나중에 secsTo()으로 전화하면 아마도 통과하지 못했던 (실제로는 트리거하지 않음) 또는 실제로 늦게 정말로 부정적이거나 실제로 큰 숫자가 생깁니다.

0

좀 더 일반적인 해결책 일 수 있습니다.

CurrQObjectClass::OnTimeout() 
{ 
// ... 
} 

CurrQObjectClass::SomeMethod() 
{ 

RelativeTimer::notify_timeout_ms(5000, this, "OnTimeout"); 
} 

뿐만 아니라 바쁜 대기를 위해 :

#include <QThread> 
#include <QTimer> 
#include <QObject> 

#include <map> 


/** 
* Singleton to implement simple 'relative' timer. 
* Implements busy wait and also timeout-notifications (useful to monitor operations that could hang, etc). 
* 
* If the whole application is stalled (e.g. when a new device is connected), and we only want to 
* wait for a period during which application was 'really' working (not just hanging waiting for OS) 
* - then ticks will be missed too. This way - it's should be possible to avoid unnecessary timeouts 
*  that could happen if global time was measured (especially annoying on WINdows platforms) 
*/ 
class RelativeTimer : public QObject 
{ 
    Q_OBJECT 

    typedef std::multimap <unsigned int, std::pair <QObject*, QString> > Notifications; 

public: 

    /** 
    * Call to busy-wait for number of ticks. 
    */ 
    static void wait_num_of_ticks(unsigned int num_of_ticks_to_wait) 
    { 
     if(self.timer_id == 0) 
     { 
      qDebug("timer not initialised, call 'RelativeTimer::Init()'"); 
      return; 
     } 

     if(num_of_ticks_to_wait > 0) 
     { 
      unsigned long until = self.tick_counter + num_of_ticks_to_wait; // it's ok if it wraps around.. 
      while(self.tick_counter != until) 
      { 
       QCoreApplication::processEvents(); // let others to their job.. 
       // or comment above out and just busy wait.. 
      } 
     } 
    } 

    /** 
    * Call to busy-wait until ms_to_wait have elapsed. 
    * If ms_to_wait is < tick period 
    * Interval will define 'tick' frequency (and accuracy). 
    */ 
    static void wait_ms(unsigned int ms_to_wait) 
    { 
     wait_num_of_ticks(num_of_ticks_to_wait(ms_to_wait)); 
    } 


    /** 
    * Call to schedule a notification after a given timeout. 
    * returns notification_id that can be used to cancel this notification. 
    */ 
    static unsigned long notify_timeout_ms(unsigned int ms_to_wait, 
              QObject *receiver, 
              const char* method_name) 
    { 
     unsigned long ticks_to_wait = 0; 
     if(receiver && method_name) 
     { 
      ticks_to_wait = num_of_ticks_to_wait(ms_to_wait); 
      if(ticks_to_wait > 1) 
      { 
       ticks_to_wait += self.tick_counter; 
       if(ticks_to_wait == 0) // avoid 0 - make it one tick more (to alow to see if successfully added this notif) 
       { 
        ticks_to_wait = 1; 
       } 
       self.notifications.insert(std::make_pair(ticks_to_wait, 
                 std::make_pair(receiver, method_name))); 
       qDebug("added delayed call.."); 
      } 
      else 
      { 
       QMetaObject::invokeMethod(receiver, method_name, Qt::QueuedConnection); 
       ticks_to_wait = 0; 
      } 
     } 
     return ticks_to_wait; 
    } 


    /** 
    * Call to cancel a notification with a given id. 
    * Specify name if there were more notification with the same id (scheduled for the same tick). 
    * returns true on successfull cancellation, false otherwise. 
    */ 
    static bool cancel_timeout_notification(unsigned long notification_id, QString notification_name="") 
    { 
     bool cancelled = false; 
     if(self.notifications.size()) 
     { 
      std::pair<Notifications::iterator, Notifications::iterator> to_cancel = self.notifications.equal_range(notification_id); 
      Notifications::iterator n = to_cancel.first; 
      for(;n != to_cancel.second; ++n) 
      { 
       if(notification_name.size()== 0 || n->second.second == notification_name) 
       { 
        self.notifications.erase(n); 
        cancelled = true; 
        break; 
       } 
      } 
     } 
     return cancelled; 
    } 

    static const unsigned int default_tick_period_ms = 100; 

    /** 
    * Call this method after event loop is created- to initiate (re-start) timer. 
    * tick period defines 'tick' frequency (and accuracy of the timer) 
    * (note on Windows that there's no point to go down below 100ms). 
    */ 
    static void Init(unsigned int tick_period_ms = default_tick_period_ms) 
    { 
     self.moveToThread(&self.thread); 
     self.thread.start(); 

     while(!self.thread.isRunning()); 

     self.current_interval = tick_period_ms; 

     // InitMe() should execute in the thread context.. 
     QMetaObject::invokeMethod(&self, "InitMe", Qt::QueuedConnection); 
    } 

private: 

    /** 
    * Internal method to convert ms to number of ticks. 
    */ 
    static unsigned int num_of_ticks_to_wait(unsigned int ms_to_wait) 
    { 
     if(ms_to_wait > self.current_interval) 
     { 
      if(ms_to_wait % self.current_interval) 
      { 
       // average it.. 
       ms_to_wait = ms_to_wait + self.current_interval/2; 
      } 
      ms_to_wait /= self.current_interval; 
     } 
     else 
     { 
      ms_to_wait = 0; 
     } 

     return ms_to_wait; 
    } 


    /** 
    * Internal method to handle tick. Increments counter and invokes notifications. 
    */ 
    void timerEvent (QTimerEvent* /*event*/) 
    { 
     tick_counter++; 

     if(notifications.size()) 
     { 
      std::pair<Notifications::iterator, Notifications::iterator> to_notify = notifications.equal_range(tick_counter); 
      Notifications::iterator n = to_notify.first; 
      for(;n != to_notify.second; ++n) 
      { 
       QMetaObject::invokeMethod(n->second.first, 
              n->second.second.toStdString().c_str(), 
              Qt::QueuedConnection); 
      } 
      notifications.erase(to_notify.first, to_notify.second); 
     } 
    } 

private slots: 
    /** 
    * Internal slot to initialize the timer. Should be called in this->timer context. 
    */ 
    void InitMe() 
    { 
     if(timer_id != 0) 
     { 
      killTimer(timer_id); 
      timer_id = 0; 
     } 

     tick_counter = 0; 
     timer_id = self.startTimer(self.current_interval); 
    } 

private: 
    RelativeTimer() 
    { 
    } 

    ~RelativeTimer() 
    { 
     thread.quit(); 
     thread.wait(); 
    } 

    QThread thread; 
    Notifications notifications; 
    int timer_id; 
    unsigned int current_interval; 
    unsigned long tick_counter; 

    static RelativeTimer self; // implement it as a signleton.. Define it in your C file, e.g.: 
           // RelativeTimer RelativeTimer::self; 
}; 

같이 사용할 수 있습니다

RelativeTimer::wait_ms(2000); 

을 즐길 수 있습니다.

관련 문제