0

タスクのリストを保持するアプリを作成しようとしていますが、締め切りごとに、締め切りに達したら関数を実行 (ポップアップを表示) したいと考えています。

私はこれを持っています:

#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 は完全に機能します (テスト済み)

エラーは接続にあると思いますが、よくわかりません...

4

2 に答える 2

2

短い答え:

変化する:

now.currentDateTime();

now = QDateTime::currentDateTime();

長い答え:

currentDateTime()は静的関数であり、既存のオブジェクトを変更する代わりに、実際には新しいQDataTimeオブジェクトを返します。これをメンバー関数として呼び出していますが、それでも静的関数として呼び出され、オブジェクトはそのまま残ります。これはまだ無効です。

後でsecsTo()無効なデータ時刻を呼び出すと、負の数または非常に大きな数が渡された(トリガーされない)か、将来的に非常に遅くなる可能性があります。

于 2012-08-17T00:37:04.113 に答える
0

これは、より一般的な解決策になる可能性があるものです。

#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;
};

次のように使用できます:

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

 CurrQObjectClass::SomeMethod()
 {

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

だけでなく、ビジーウェイトの場合:

RelativeTimer::wait_ms(2000);

楽しみ。

于 2013-01-03T18:07:47.400 に答える