0

I wrote this code , so I could monitor an ip address. I am using Qt and I want to make it, so when I press the button start it will ping the ip and return a value, like 1, which means that it is the minimum ping or whatever. The problem is that I cant put in a loop the change of a label. I tried QTimer but I couldn't figure it out. This is the code that I wrote:

#include "ui_mainwindow.h"
#include<iostream>
#include<vector>
#include<string>
#include<ctime>
#include<fstream>
#include<QMessageBox>
#include<Windows.h>
#include<QTimer>
#include<QDebug>
using namespace std;


int check(string file){
    string a,b;
    int x,c;
    vector<int>ms;
    ifstream fin(file);
    while(!fin.eof()){
        getline(fin,a);
        if(a[0]=='P'){
            if(a=="PING: transmit failed. General failure. ")
                return -1;
        }
        if(a[0]=='R'){
            if(a=="Request timed out.")
                return -1;
            for(unsigned int i=0;i<a.size();i++){
                if(a[i]=='t'){
                    x=i+4;
                    while(a[x]!='m'){
                        b+=a[x];
                        x++;
                    }
                c=stoi(b);
                ms.push_back(c);
                }
            }
        }
    }
    for(unsigned int i=0;i<ms.size();i++){
        if(ms[i]<20)
            return 0;
        else if(ms[i]>20 && ms[i]<60)
            return 1;
        else
            return 2;
    }
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked(){
    ofstream fout("traffic.txt");
    string file_name="result.txt";
    QString a="ping ";
    QString b = ui->lineEdit->text();
    string result;
    int j=0;
    a+=b;
    string x=a.toStdString();
    QTimer timer;
    constexpr int interval =10;
    timer.callOnTimeout([&]{
    //qInfo()<<"ok";
      system((x+">" + file_name).c_str());
        //time_t now = time(0);
        //tm *ltm = localtime(&now);
        j=check(file_name);
        //Sleep(3000);
        if(j==0)
           ui->label_2->setText("ok");
        else if(j==1)
            ui->label_2->setText("minimum");
        else if(j==-1)
            QMessageBox::critical(this,"Error","request time out.Check the ip");
        else
            QMessageBox::critical(this,"bad","bad");
            //Sleep(30000);

           timer.start(interval);

    });
    timer.start(interval);
   }
  • FYI: [Qt doc.: Timers](https://doc.qt.io/qt-5/timers.html), [Qt Analog Clock Example](https://doc.qt.io/qt-5/qtwidgets-widgets-analogclock-example.html), and other examples in [SO: Change interval timeouts of QTimer with slider](https://stackoverflow.com/a/64301362/7478597) and [SO: QTimer::timeout isn't firing](https://stackoverflow.com/a/54840605/7478597) (and there are many more in SO). – Scheff's Cat May 31 '21 at 12:36

1 Answers1

1

You should connect your timer timeout signal to your lambda function instead of calling timer.callOnTimeout:

connect(&timer, &QTimer::timeout, this, [this]() {
    .... your code
} );

also you don't need to start your timer again in your lambda function, because since you start it once, it will run continuously for it interval till you call timer.stop() .

Keep in mind that creating a Timer every time you push your button will create multiple instance of Timer that run simultaneously and will cause overload or memory overusing! try to use it more efficiently.

void MainWindow::on_pushButton_clicked(){
    ofstream fout("traffic.txt");
    QTimer timer;
    constexpr int interval =10;

    connect(&timer, &QTimer::timeout, this, [this]() {
    //qInfo()<<"ok";
    string file_name="result.txt";
    QString a="ping ";
    QString b = ui->lineEdit->text();
    string result;
    int j=0;
    a+=b;
    string x=a.toStdString();
      system((x+">" + file_name).c_str());
        //time_t now = time(0);
        //tm *ltm = localtime(&now);
        j=check(file_name);
        //Sleep(3000);
        if(j==0)
           ui->label_2->setText("ok");
        else if(j==1)
            ui->label_2->setText("minimum");
        else if(j==-1)
            QMessageBox::critical(this,"Error","request time out.Check the ip");
        else
            QMessageBox::critical(this,"bad","bad");
            //Sleep(30000);    
    });

    timer.start(interval);
   }
Farshid616
  • 1,404
  • 1
  • 14
  • 26
  • you mean just, replace timer.callOnTimeout with connect(&timer, &QQTimer::timeout, this, [this]() { ? –  May 31 '21 at 12:57
  • Yes, you should replace your line `timer.callOnTimeout([&]{` whith this `connect(&timer, &QTimer::timeout, this, [this]() {` – Farshid616 May 31 '21 at 13:24
  • I did that but now I have many errors for my variable x , j, file_name. The error is variable x/j cannot be implicitly capture in a lambda with no capture-default specified. –  May 31 '21 at 13:56
  • Yes it need refactoring, because they're it different scope. – Farshid616 May 31 '21 at 14:11
  • 1
    `QTimer::callOnTimeout` is a convenience method for connecting to the timeout signal, so I don't really see how this would help. However, only capturing `this` pointed out some serious problems with the original design, where all variables where captured by reference, and then go out of scope... That's something that needs to be refactored – king_nak May 31 '21 at 14:26
  • Sorry, guys but I really don't understand what do you mean by refactoring. Could you give me an exam on what should I do? Thanks. –  May 31 '21 at 20:26
  • @master_Ka1attas checkout my answer update – Farshid616 Jun 01 '21 at 05:23