首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Qt中运行定时器5秒

在Qt中运行定时器5秒
EN

Stack Overflow用户
提问于 2016-04-21 12:39:42
回答 2查看 4.5K关注 0票数 1

我试图使用QTimer函数运行一个函数大约5秒。在研究了文档和测试之后,我似乎找不到在Qt中这样做的函数。

我尝试了以下方法:

代码语言:javascript
复制
QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(myFunction());
    timer->start(5000);

该方法每隔5秒运行一次函数。这不是我想要达到的目标。我还尝试使用以下代码使用singleShot()属性:

代码语言:javascript
复制
QTimer::singleShot(5000,this,SLOT(myFunction()));

这个函数只触发我的函数一次。是否有QTimer的任何属性可以在给定时间内运行我的函数。类似于:

代码语言:javascript
复制
run function and timeout function after 5 seconds.

编辑:更多信息:这是为机器人比赛在我的大学。我要做的是通过TCP驱动机器人的轮子。我知道两个轮子需要多少秒才能让机器人转动一个特定的角度。myFunction中的插槽将类似于senddatatoRobot() --这个函数基本上是通过TCP将数据发送给我的机器人,根据机器人从期望的端点的方向将它转换成一个特定的角度。例如,我知道我的机器人将进行360度转弯,如果我发送一个PWM值4096和0到左和右车轮5秒。例如,要做一个45度的转弯,我会发送指定的秒数的数据。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-21 13:10:06

你可以试试这样的方法:

代码语言:javascript
复制
QElapsedTimer t;
t.start();

while (t.elapsed() < 5000) { ...do stuff... } // this will block the thread

你也可以这样做:

代码语言:javascript
复制
startDoingStuff(); // must not block the thread
QTimer::singleShot(5000, this, "stopDoingStuff");

但是,从您的评论中可以看出,您需要分享该功能的实际功能,并且非常肯定地了解更多关于事件驱动编程的知识,然后您将能够提出一个更好的设计。

该功能主要是通过TCP将数据发送给我的机器人,根据机器人从期望的端点定位到一定的角度。例如,我知道我的机器人将进行360度转弯,如果我发送一个PWM值4096和0到左和右车轮5秒。例如,为了进行45度转弯,我输入发送数据的时间为指定的秒数。

在我看来,更有效的解决方案是只发送值更改,而不是重复发送相同的数据。

因此,在您的机器人的微控制器代码中,您将连续地缓存和使用这些值,并且从您的控制器应用程序中,您只需要“设置”远程值:

代码语言:javascript
复制
public slots:
    void reset() { send(0, 0); }
...
// begin turning
send(4096, 0);
QTimer::singleShot(5000, this, "reset"); // end turning in 5 secs

一个更好的解决方案是不发送PWM值,而是发送您的机器人特定的命令,并让机器人的微控制器保持定时,因为它很可能比QTimer更好。您甚至可以获得更具体的信息,例如,一个以T秒为单位来转换X度的命令。在机器人微控制器代码方面,你肯定有很大的改进空间。

如果必须使用当前正在尝试的方法,则可以使用QElapsedTimer方法实现具有函数void send(v1, v2, time)的工作人员,只要您将该工作人员放到另一个线程中,就不会阻塞主线程,这将导致操作系统将应用程序报告为“没有响应”。但是这种方式不能中断命令,在当前命令完成之前不能发出新命令。您可以通过实现非阻塞工作人员来改进这一点,如this example中所述。这样,您就可以通过中断来在当前命令完成之前发出新命令。

票数 1
EN

Stack Overflow用户

发布于 2016-04-21 13:11:13

你还没有说明你如何指挥你的机器人。有两种方法:

  1. 在间隔开始时发送ON命令,然后在间隔结束时发送OFF命令;
  2. 在间隔期间重复发送ON命令,在接收到最后一条命令后,电机“很快”关闭,没有明确的off命令。

这两种方法都很容易使用状态机实现。让我们看看如何实现第一种方法。

控制器可以封装这些行为。isIdleisActive信号将连接到向机器人发送命令的操作。

代码语言:javascript
复制
class Controller : public QObject {
   Q_OBJECT
   QStateMachine m_machine{this};
   QState
      m_idle    {&m_machine},
      m_active  {&m_machine};
   Transition
      m_go{&m_idle, &m_active};
   Delay
      m_activeTime{&m_active, &m_idle, 0};
public:
   Controller(QObject * parent = 0) : QObject(parent) {
      connect(&m_idle, &QState::entered, this, &Controller::isIdle);
      connect(&m_active, &QState::entered, this, &Controller::isActive);
      m_machine.setInitialState(&m_idle);
      m_machine.start();
   }
   Q_SLOT void moveFor(int ms) {
      m_activeTime.setDuration(ms);
      m_go();
   }
   Q_SIGNAL void isIdle();
   Q_SIGNAL void isActive();
};

TransitionDelay类实现与状态转换相链接的行为:

代码语言:javascript
复制
// https://github.com/KubaO/stackoverflown/tree/master/questions/robot-state-timer-36769933
#include <QtWidgets>

struct Transition : public QObject {
   Q_OBJECT
public:
   Transition(QState * source, QState * destination) : QObject(source->machine()) {
      source->addTransition(this, &Transition::trigger, destination);
   }
   Q_SIGNAL void trigger();
   void operator()() { trigger(); }
};

class Delay : public Transition {
   Q_OBJECT
   int m_duration;
   QBasicTimer m_timer;
   void timerEvent(QTimerEvent * ev) {
      if (m_timer.timerId() != ev->timerId()) return;
      m_timer.stop();
      trigger();
   }
public:
   Delay(QState * src, QState * dst, int ms) : Transition(src, dst), m_duration(ms) {
      connect(src, &QState::entered, this, [this]{ m_timer.start(m_duration, this);});
   }
   Q_SLOT void setDuration(int duration) { m_duration = duration; }
};

测试工具可以使示例完整。

代码语言:javascript
复制
int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   Controller ctl;
   QWidget w;
   QFormLayout layout{&w};
   QPushButton start{"Go"};
   QLineEdit duration{"5000"};
   QPlainTextEdit log;
   log.setReadOnly(true);
   layout.addRow("Duration", &duration);
   layout.addRow(&start);
   layout.addRow(&log);

   QObject::connect(&ctl, &Controller::isIdle, &log, [&]{ log.appendPlainText("Idle"); });
   QObject::connect(&ctl, &Controller::isActive, &log, [&]{ log.appendPlainText("Active"); });
   QObject::connect(&start, &QPushButton::clicked, &ctl, [&]{
      ctl.moveFor(duration.text().toInt());
   });
   w.show();
   return app.exec();
}

#include "main.moc"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36769933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档