我在理解如何使用QTimer
时遇到问题,因此我重复特定操作(点击按钮或网络请求)。
关注此answer的question后,我无法弄清楚如何将定时器的QTimer::Timeout
信号连接到MainWIndow::request
信号就像我当前连接的按钮一样。问题是我无法重复;它编译并运行没有错误,但没有重复。
(就像发布问题的人一样,如果我将所有代码都放在main.cpp
中,我也可以重复计时器,但我想知道在这种情况下如何完成它。)< / p>
以下是从该示例中获取的简化代码,以指出我的尝试:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QKeyEvent>
#include <QApplication>
#include <QtWidgets>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// GUI setup here //
networkManager = new QNetworkAccessManager;
connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::on_NetworkManagerFinished);
connect(ui->getButton, &QPushButton::clicked, this, &MainWindow::on_getButton_clicked);
// Connect the timer to repeat the GET request
QTimer timer;
// [1st attempt]
connect(&timer, SIGNAL(&QTimer::timeout), this, SLOT(&MainWindow::on_TimerTimeout));
// [2nd attempt]
connect(&timer, SIGNAL(timeout()), this, SLOT(timer_buttonClicked()));
timer.start(1500); // 1.5 secs
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_NetworkManagerFinished(QNetworkReply *reply)
{
// Parse and display JSON here //
}
// Make GET request when button is clicked
void MainWindow::on_getButton_clicked() //on_TimerTimeout()
{
// Make GET request
QUrlQuery query;
QUrl url("http://blah/blahblah");
query.addQueryItem("blah", "blah");
url.setQuery(query);
QNetworkRequest networkRequest(url);
networkManager->get(networkRequest);
ui->getButton->setEnabled(false);
// Restart timer
timer->start(1500); // 1.5 secs
// Do stuff in the GUI here //
}
更新
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_NetworkManagerFinished(QNetworkReply* reply);
void on_getButton_clicked();
private:
Ui::MainWindow *ui;
QNetworkAccessManager *networkManager;
};
#endif // MAINWINDOW_H
正如在评论部分中可以看到的那样,我还尝试在mainwindow.h
中使用onTimeout替换按钮的私有插槽,并在连接之前在mainwindow.cpp
中创建了一个QTimer对象启动它,然后我使用该对象来定义connect(&timer,&QTimer::timeout,this,&MainWindow::onTimeout);
。另外,我用onTimeout相关代码替换了最后的按钮插槽定义。
如果您可以解释我缺少的内容,或者甚至提供我看到here的确切示例的代码,这对我来说很有用。
答案 0 :(得分:3)
下面的代码片段根据您提供的代码说明了正确的方法:
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
// setup your GUI
// declare a pointer variable for pointing to a QTimer object
QTimer *timer = new QTimer;
// make the connection using the timer variable
connect(timer, &QTimer::timeout, this, &MainWindow::on_getButton_clicked);
// start the timer object by first dereferencing that object first
timer->start(1500);
// do other stuff //
}
您应该对指针进行进一步阅读,并使用点(。)运算符进行differences。
注意强>
使用计时器作为班级成员时,ddriver的答案会更好;这避免了我的方法中指针引用的局部性。
答案 1 :(得分:2)
如果您的代码甚至编译,则意味着您的班级中很可能有=IF(F2=1,"Resistant to 1",IF(F2=0,"Resistant to 0","Resistant to More than 1"))
成员。您可以从以下几行中推断出这一点:
QTimer *timer
如果您没有,请将其添加到课程中:
// Restart timer
timer->start(1500); // 1.5 secs
但是,在类构造函数中,您正在创建名为class MainWindow {
Q_OBJECT
...
private:
QTimer *timer; // add this
};
的另一个变量,并将数据成员隐藏起来:
timer
你绝对不想在那里引入新的变量。更重要的是,这个变量有自动存储,这意味着它将在其封闭范围的末尾被破坏(这是构造函数本身:所以当你从构造函数返回时,{{1对象消失了。)
解决方案:只是不要声明一个全新的变量,使用现有的数据成员。将构造函数更改为:
// Connect the timer to repeat the GET request
QTimer timer;
关于实际的timer
语句。
这个是错的:
// not introducing any new variable here!
timer = new QTimer(this);
connect(timer, ...);
它将编译,但在运行时发出警告。摆脱它。 (为什么你最后输入这个?如果你正在使用Qt Creator你会有SIGNAL和SLOT宏的自动完成......)
这一个:
connect
具有正确的语法,但我不知道它是否真的有用,你有connect(&timer, SIGNAL(&timeout()), this, SLOT(&MainWindow::on_TimerTimeout));
成员函数标记为插槽吗?另一个connect(&timer, SIGNAL(timeout()), this, SLOT(timer_buttonClicked()));
使用另一个函数。
如果您使用的是Qt 5,请尽快转到:
void timer_buttonClicked()
如果出现问题,在编译时失败。
答案 2 :(得分:2)
我说最简单的解决方案就是让计时器成为一个类成员,实际上不需要使用堆分配:
class YourClass : public QObject {
Q_OBJECT
QTimer timer;
public:
YourClass() {
connect(&timer, SIGNAL(timeout()), this, SLOT(timer_yourSlot()));
// or the new and safer syntax in Qt 5
// connect(&timer, &QTimer::timeout, this, &YourClass::yourSlot);
timer.start(1500);
}
public slots:
void yourSlot() { ... }
};
除非您知道所需内容,否则建议避免堆分配。在这种情况下,你不需要它。避免它的原因很多 - 它更慢,它将使用更多的内存,它可能会失败(如果你的内存不足),它将需要额外的管理 - 自动或手动,并且它更容易出错。将计时器作为类成员将自动将其与类实例的生命周期联系起来,这样就可以避免所有不必要的开销。
Peppe的回答假设你有一个QTimer * timer;
班级成员,你不会,这是额外混乱的根源。
如果我
QTimer timer; timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &MainWindow::on_getButton_clicked);
我得到了 &#39; C2679没有找到哪个操作符采用类型的右操作数 QTimer&#39;
此处的问题是,计时器的类型为QTimer
,而new QTimer
会将指针返回给QTimer
,而不是QTimer
。非常不同的事情。然后connect()
需要一个对象指针,但在你的情况下timer
是一个对象实例,而不是一个对象指针。使用&
运算符,您可以在内存中获取计时器地址,或者换句话说,指向它的指针。
如果我
timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &MainWindow::on_getButton_clicked);
我得到&#39;计时器未声明 标识符&#39;
正如它所说,计时器是未声明的,编译器不知道timer
是什么,因为你没有用适当的类型声明它。现在,如果执行QTimer * timer
,编译器就知道timer
是指向计时器的类型指针。