Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to update progress bar?
Forum Updated to NodeBB v4.3 + New Features

How to update progress bar?

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 2.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    ke7omc
    wrote on last edited by ke7omc
    #1

    I am having some trouble updating the progress bar in my UI. I created a class called counter that inherits from qobject (2nd Code snipet). Then in mainwindow I create an instance of that class called enginePowerCounter and connect enginePowerCounter signal valueChanged with progress bar slot setValue. Later on I set a new value of enginePowerCounter and when that new value is set I want a signal to be sent to the progress bar and set a new value with value of enginePowerCounter.

    The instance declaration happens after all of the #includes. The connect happens after ui->setupUi(this), and the value of enginePowerCounter is updated in void MainWindow::setup(). In the 2nd code snippet, I define slot but I do not define signal. Originally I tried defining signal but then I got an error saying "This is not a signal declaration".

    Admittedly I believe I do not correctly understand how signals and slots work, expecially when creating custom ones. I can get signals from windowform.ui alright, but I think its the custom stuff that I have more problems with. I read the documentation where the idea for the counter class actually came from but I may be missing something fundamental. Can anybody help me get this working and understanding signals and slots better?

    mainwindow.cpp

    #define _USE_MATH_DEFINES
    
    #include "mainwindow.h"
    #include "./ui_mainwindow.h"
    #include "EngineCharacteristicsNamespace.hpp"
    #include "math.h"
    #include "counter.hpp"
    #include "QObject"
    
    #include <vtkVersion.h>
    #include <vtkSmartPointer.h>
    #include <vtkFloatArray.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkContextView.h>
    #include <vtkContextScene.h>
    #include <vtkChartXY.h>
    #include <vtkTable.h>
    #include <vtkPlot.h>
    #include <vtkContextInteractorStyle.h>
    #include <vtkEventQtSlotConnect.h>
    #include <QVTKOpenGLWidget.h>
    #include <vtkGenericOpenGLRenderWindow.h>
    
    Counter enginePowerCounter;
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
       connect(&enginePowerCounter,SIGNAL(valueChanged(int newValue)),ui->progressBar,SLOT(setValue(int)));
    
        mQVtkWidget= new QVTKOpenGLWidget(this);
    
        QGridLayout* layout = new QGridLayout(ui->frame);
        layout->addWidget(mQVtkWidget,1,1);
        ui->frame->setLayout(layout);
    
        vtkNew<vtkGenericOpenGLRenderWindow> window;
        mQVtkWidget->SetRenderWindow(window);
    
        mView->SetRenderWindow(window);
        mView->SetInteractor(window->GetInteractor());
    
        setup();
    
    }
    
    void MainWindow::on_pushButton_simulateEngine_clicked()
    {
        EngineCharacteristics::rodToHalfStrokeRatio = EngineCharacteristics::rodLength/(EngineCharacteristics::strokeLength/2);
        EngineCharacteristics::cylinderVolume = M_PI*pow((EngineCharacteristics::bore/2),2)*EngineCharacteristics::strokeLength;
        EngineCharacteristics::combustionChamberVolume = EngineCharacteristics::cylinderVolume/(EngineCharacteristics::compressionRatio-1);
        setup();
    
    }
    
    
    void MainWindow::selectionChanged(vtkObject*, unsigned long, void*, void* callData)
    {
        vtkChartPlotData* plotData = reinterpret_cast<vtkChartPlotData*>(callData);
        if(plotData)
        {
            //Plot values.
            float x=plotData->Position.GetX();
            float y=plotData->Position.GetY();
            QString xlabel="X: "+QString::number(x);
            ui->xLabel->setText(xlabel);
    
            QString ylabel="Y: "+QString::number(y);
            ui->yLabel->setText(ylabel);
            this->mQVtkWidget->GetRenderWindow()->Render();
        }
    }
    
    void MainWindow::setup()
    {
        vtkNew<vtkTable> table;
    
        vtkNew<vtkFloatArray> RPM;
        RPM->SetName("RPM");
        table->AddColumn(RPM);
    
        vtkNew<vtkFloatArray> power;
        power->SetName("Engine Power");
        table->AddColumn(power);
    
        // Fill in the table with some example values
        int numPoints = EngineCharacteristics::maximumRevolutionsPerSecond/100;
        table->SetNumberOfRows(numPoints);
        for (int i = 0; i < numPoints; ++i)
        {
            table->SetValue(i, 0, i * 100);
            if (i==0)
            {
                EngineCharacteristics::enginePower = 0;
            }
            else
            {
            EngineCharacteristics::enginePower = -(calculate_total_work(EngineCharacteristics::constantPressureSpecificHeat, EngineCharacteristics::constantVolumeSpecificHeat, EngineCharacteristics::gasConstant, EngineCharacteristics::intakePlenumAirTemperature,EngineCharacteristics::heatingValueOfFuel,EngineCharacteristics::airToFuelRatio,EngineCharacteristics::compressionRatio,EngineCharacteristics::rodToHalfStrokeRatio,EngineCharacteristics::combustionChamberVolume,EngineCharacteristics::intakeValveDiameter,EngineCharacteristics::intakeValveStemDiameter,EngineCharacteristics::atmosphericPressure,EngineCharacteristics::ratioOfSpecificHeats,EngineCharacteristics::frictionCoefficient,EngineCharacteristics::maximumIntakeValveLift,EngineCharacteristics::intakeAdvertisedDuration,EngineCharacteristics::lobeSeparationAngle,EngineCharacteristics::exhaustAdvertisedDuration,EngineCharacteristics::maximumExhaustValveLift,EngineCharacteristics::exhaustValveDiameter,EngineCharacteristics::exhaustValveStemDiameter,EngineCharacteristics::engineLoad,EngineCharacteristics::combustionStartCrankAngle,EngineCharacteristics::combustionDurationInAngles,EngineCharacteristics::weibeFormFactorN,EngineCharacteristics::weibeEfficiencyFactorA,i*100))*EngineCharacteristics::numberOfCylinders * (i*100) / (60 * 2 * 1000);
            enginePowerCounter.setValue(i*100/numPoints);
            }
            table->SetValue(i, 1, EngineCharacteristics::enginePower);
        }
    
        // Set up the view
        mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
    
        // Add multiple line plots, setting the colors etc
        mChart->SetTitle("Hales Dynamometer");
        mView->GetScene()->AddItem(mChart);
        vtkSmartPointer<vtkPlot> line = mChart->AddPlot(vtkChart::LINE);
        line->SetInputData(table, 0, 1);
        line->SetColor(255, 0, 0, 255);
        line->SetWidth(2.0);
    
    
        mConnections->Connect(
                    mChart,
                    vtkCommand::SelectionChangedEvent,
                    this,
                    SLOT(selectionChanged(vtkObject*, unsigned long, void*, void*)));
    
    
        this->mQVtkWidget->GetRenderWindow()->Render();
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    counter.hpp

    #ifndef COUNTER_HPP
    #define COUNTER_HPP
    
    #include <QObject>
    
    class Counter : public QObject
    {
        Q_OBJECT
    
    public:
        Counter() { m_value = 0; }
    
        int value() const { return m_value; }
    
    public slots:
        void setValue(int value)
        {
            m_value = value;
        }
    
    signals:
        void valueChanged(int newValue);
    
    private:
        int m_value;
    };
    
    
    
    #endif // COUNTER_HPP
    
    
    JonBJ 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      First thing: do not create static QObject based object like that.

      Next: when calling setup from the constructor, you try to update a progress bar in a widget that in fact does not exists physically yet. You won't see anything while doing this in your constructor.

      As for why there's no update at all: you never emit the signal in your counter object. In your slot you just update the value. Therefore nothing more will happen. Signals are not automatically emitted when you implement it like that. What you should do is to compare if the new value is different from the old one and emit the signal it's the case.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • K ke7omc

        I am having some trouble updating the progress bar in my UI. I created a class called counter that inherits from qobject (2nd Code snipet). Then in mainwindow I create an instance of that class called enginePowerCounter and connect enginePowerCounter signal valueChanged with progress bar slot setValue. Later on I set a new value of enginePowerCounter and when that new value is set I want a signal to be sent to the progress bar and set a new value with value of enginePowerCounter.

        The instance declaration happens after all of the #includes. The connect happens after ui->setupUi(this), and the value of enginePowerCounter is updated in void MainWindow::setup(). In the 2nd code snippet, I define slot but I do not define signal. Originally I tried defining signal but then I got an error saying "This is not a signal declaration".

        Admittedly I believe I do not correctly understand how signals and slots work, expecially when creating custom ones. I can get signals from windowform.ui alright, but I think its the custom stuff that I have more problems with. I read the documentation where the idea for the counter class actually came from but I may be missing something fundamental. Can anybody help me get this working and understanding signals and slots better?

        mainwindow.cpp

        #define _USE_MATH_DEFINES
        
        #include "mainwindow.h"
        #include "./ui_mainwindow.h"
        #include "EngineCharacteristicsNamespace.hpp"
        #include "math.h"
        #include "counter.hpp"
        #include "QObject"
        
        #include <vtkVersion.h>
        #include <vtkSmartPointer.h>
        #include <vtkFloatArray.h>
        #include <vtkRenderer.h>
        #include <vtkRenderWindow.h>
        #include <vtkRenderWindowInteractor.h>
        #include <vtkContextView.h>
        #include <vtkContextScene.h>
        #include <vtkChartXY.h>
        #include <vtkTable.h>
        #include <vtkPlot.h>
        #include <vtkContextInteractorStyle.h>
        #include <vtkEventQtSlotConnect.h>
        #include <QVTKOpenGLWidget.h>
        #include <vtkGenericOpenGLRenderWindow.h>
        
        Counter enginePowerCounter;
        
        MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent)
            , ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
        
           connect(&enginePowerCounter,SIGNAL(valueChanged(int newValue)),ui->progressBar,SLOT(setValue(int)));
        
            mQVtkWidget= new QVTKOpenGLWidget(this);
        
            QGridLayout* layout = new QGridLayout(ui->frame);
            layout->addWidget(mQVtkWidget,1,1);
            ui->frame->setLayout(layout);
        
            vtkNew<vtkGenericOpenGLRenderWindow> window;
            mQVtkWidget->SetRenderWindow(window);
        
            mView->SetRenderWindow(window);
            mView->SetInteractor(window->GetInteractor());
        
            setup();
        
        }
        
        void MainWindow::on_pushButton_simulateEngine_clicked()
        {
            EngineCharacteristics::rodToHalfStrokeRatio = EngineCharacteristics::rodLength/(EngineCharacteristics::strokeLength/2);
            EngineCharacteristics::cylinderVolume = M_PI*pow((EngineCharacteristics::bore/2),2)*EngineCharacteristics::strokeLength;
            EngineCharacteristics::combustionChamberVolume = EngineCharacteristics::cylinderVolume/(EngineCharacteristics::compressionRatio-1);
            setup();
        
        }
        
        
        void MainWindow::selectionChanged(vtkObject*, unsigned long, void*, void* callData)
        {
            vtkChartPlotData* plotData = reinterpret_cast<vtkChartPlotData*>(callData);
            if(plotData)
            {
                //Plot values.
                float x=plotData->Position.GetX();
                float y=plotData->Position.GetY();
                QString xlabel="X: "+QString::number(x);
                ui->xLabel->setText(xlabel);
        
                QString ylabel="Y: "+QString::number(y);
                ui->yLabel->setText(ylabel);
                this->mQVtkWidget->GetRenderWindow()->Render();
            }
        }
        
        void MainWindow::setup()
        {
            vtkNew<vtkTable> table;
        
            vtkNew<vtkFloatArray> RPM;
            RPM->SetName("RPM");
            table->AddColumn(RPM);
        
            vtkNew<vtkFloatArray> power;
            power->SetName("Engine Power");
            table->AddColumn(power);
        
            // Fill in the table with some example values
            int numPoints = EngineCharacteristics::maximumRevolutionsPerSecond/100;
            table->SetNumberOfRows(numPoints);
            for (int i = 0; i < numPoints; ++i)
            {
                table->SetValue(i, 0, i * 100);
                if (i==0)
                {
                    EngineCharacteristics::enginePower = 0;
                }
                else
                {
                EngineCharacteristics::enginePower = -(calculate_total_work(EngineCharacteristics::constantPressureSpecificHeat, EngineCharacteristics::constantVolumeSpecificHeat, EngineCharacteristics::gasConstant, EngineCharacteristics::intakePlenumAirTemperature,EngineCharacteristics::heatingValueOfFuel,EngineCharacteristics::airToFuelRatio,EngineCharacteristics::compressionRatio,EngineCharacteristics::rodToHalfStrokeRatio,EngineCharacteristics::combustionChamberVolume,EngineCharacteristics::intakeValveDiameter,EngineCharacteristics::intakeValveStemDiameter,EngineCharacteristics::atmosphericPressure,EngineCharacteristics::ratioOfSpecificHeats,EngineCharacteristics::frictionCoefficient,EngineCharacteristics::maximumIntakeValveLift,EngineCharacteristics::intakeAdvertisedDuration,EngineCharacteristics::lobeSeparationAngle,EngineCharacteristics::exhaustAdvertisedDuration,EngineCharacteristics::maximumExhaustValveLift,EngineCharacteristics::exhaustValveDiameter,EngineCharacteristics::exhaustValveStemDiameter,EngineCharacteristics::engineLoad,EngineCharacteristics::combustionStartCrankAngle,EngineCharacteristics::combustionDurationInAngles,EngineCharacteristics::weibeFormFactorN,EngineCharacteristics::weibeEfficiencyFactorA,i*100))*EngineCharacteristics::numberOfCylinders * (i*100) / (60 * 2 * 1000);
                enginePowerCounter.setValue(i*100/numPoints);
                }
                table->SetValue(i, 1, EngineCharacteristics::enginePower);
            }
        
            // Set up the view
            mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
        
            // Add multiple line plots, setting the colors etc
            mChart->SetTitle("Hales Dynamometer");
            mView->GetScene()->AddItem(mChart);
            vtkSmartPointer<vtkPlot> line = mChart->AddPlot(vtkChart::LINE);
            line->SetInputData(table, 0, 1);
            line->SetColor(255, 0, 0, 255);
            line->SetWidth(2.0);
        
        
            mConnections->Connect(
                        mChart,
                        vtkCommand::SelectionChangedEvent,
                        this,
                        SLOT(selectionChanged(vtkObject*, unsigned long, void*, void*)));
        
        
            this->mQVtkWidget->GetRenderWindow()->Render();
        
        }
        
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        

        counter.hpp

        #ifndef COUNTER_HPP
        #define COUNTER_HPP
        
        #include <QObject>
        
        class Counter : public QObject
        {
            Q_OBJECT
        
        public:
            Counter() { m_value = 0; }
        
            int value() const { return m_value; }
        
        public slots:
            void setValue(int value)
            {
                m_value = value;
            }
        
        signals:
            void valueChanged(int newValue);
        
        private:
            int m_value;
        };
        
        
        
        #endif // COUNTER_HPP
        
        
        JonBJ Online
        JonBJ Online
        JonB
        wrote on last edited by
        #3

        @ke7omc said in How to update progress bar?:

        connect(&enginePowerCounter,SIGNAL(valueChanged(int newValue)),ui->progressBar,SLOT(setValue(int)));

        Have you verified this returned success? Do you get a message? I was unable to find a formal definition for whether old-style SIGNAL/SLOT() actually accepts parameter names, but according to https://www.informit.com/articles/article.aspx?p=1405224&seqNum=2

        Similarly, Qt will give a warning if parameter names are included in the signal or slot signatures.

        You really should change over to New Signal Slot Syntax.

        1 Reply Last reply
        1
        • K Offline
          K Offline
          ke7omc
          wrote on last edited by
          #4

          @SGaist
          Thank you for responding. Regarding the first thing about static QObject, could you help me understand what should be done? I am fairly new to programming and was just trying to follow the example in the documentation here.

          Regarding the second thing. I might be getting confused about the order of things. So when the program opens there is some small sample code that is run and updating the progress bar is not so important. However, after the user inputs their data and clicks simulate engine button, setup() is called a second time. During the second time is when I would like the progress bar to start updating. Are you saying that the widget also does not yet physically exist after the user clicks the simulate button? If so, I am a little confused as the widget is essentially a graph that after clicking simulate engine button would show the initial graph from just opening the program, as well as showing a second line in the same graph from the user input data.

          As for the third thing, thank you for helping me understand that. I have now added the compare that you suggested as well as the emit command.

          1 Reply Last reply
          0
          • K Offline
            K Offline
            ke7omc
            wrote on last edited by
            #5

            @JonB
            Thanks for the suggestion Jon! I was not aware that the notation had changed and was just trying to follow some examples I found online. I do have a question about the new method. Here is the new code I tried:

            connect(enginePowerCounter,&enginePowerCounter::valueChanged,ui->progressBar,&progressBar::setValue);
            

            However, I got these errors:
            mainwindow.cpp:34:33: error: 'enginePowerCounter' is not a class, namespace, or enumeration
            mainwindow.cpp:26:9: note: 'enginePowerCounter' declared here
            mainwindow.cpp:34:82: error: use of undeclared identifier 'progressBar'

            Can you help me understand what I am doing wrong with the new notation?
            Thanks,

            JonBJ 1 Reply Last reply
            0
            • K ke7omc

              @JonB
              Thanks for the suggestion Jon! I was not aware that the notation had changed and was just trying to follow some examples I found online. I do have a question about the new method. Here is the new code I tried:

              connect(enginePowerCounter,&enginePowerCounter::valueChanged,ui->progressBar,&progressBar::setValue);
              

              However, I got these errors:
              mainwindow.cpp:34:33: error: 'enginePowerCounter' is not a class, namespace, or enumeration
              mainwindow.cpp:26:9: note: 'enginePowerCounter' declared here
              mainwindow.cpp:34:82: error: use of undeclared identifier 'progressBar'

              Can you help me understand what I am doing wrong with the new notation?
              Thanks,

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #6

              @ke7omc
              Re-read, for your own benefit, that wiki page.

              Note that the slots are methods in a class. You cannot address them via instance::method, it must be Class::method. So:

              connect(enginePowerCounter, &EnginePowerCounterClass::valueChanged,
                      ui->progressBar, &QProgressBar::setValue);
              
              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Make your instance of counter a class member.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1
                • K Offline
                  K Offline
                  ke7omc
                  wrote on last edited by
                  #8

                  @JonB
                  Thanks Jon. Originally I had done that but I got this error:
                  "mainwindow.cpp:34:85: error: call to non-static member function without an object argument"
                  which is why I thought I might have to use the instance of the Counter Class. I am not really sure why I am getting this error if it is supposed to be Class::Method.

                  JonBJ 1 Reply Last reply
                  0
                  • K ke7omc

                    @JonB
                    Thanks Jon. Originally I had done that but I got this error:
                    "mainwindow.cpp:34:85: error: call to non-static member function without an object argument"
                    which is why I thought I might have to use the instance of the Counter Class. I am not really sure why I am getting this error if it is supposed to be Class::Method.

                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote on last edited by JonB
                    #9

                    @ke7omc
                    You also need to do as @SGaist said :)

                    Make your instance of counter a class member.

                    You're going to be calling a class method, so you're going to need to call it on a correct class instance object!

                    Note how for the slot you have

                    ui->progressBar, &QProgressBar::setValue
                    

                    ui->progressBar is an instance of QProgressBar. You need the same for the signal side.

                    connect(senderInstance, &SenderClass::signalMethod,
                            receiverInstance, &ReceiverClass::slotMethod)
                    

                    This will arrange, somehow, for emit senderInstance->signalMethod() to call receiverInstance->slotMethod(). By magic.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved