Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Update Class Value using Slider



  • I have a class definition with a value in it that I would like updated every time the horizontal slider value is changed. Can you help me know how to do this? I understand how to connect signals and slots between buttons and such, but how would I pass the updated slider value into the class definition?


  • Lifetime Qt Champion

    @ke7omc said in Update Class Value using Slider:

    but how would I pass the updated slider value into the class definition?

    You don't. https://doc.qt.io/qt-5/qabstractslider.html#sliderMoved passes the value to the connected slots. So, add a slot with an int parameter to your class and connect it to that signal.



  • Thank you. That makes more sense. I am struggling a little bit on how to actually connect them though. Essentially I have a header file that defines my sphere class and inside that class is coefficientOfRestitution that I would like to update with the slider value in the GUI. So in the mainwindow.cpp I wrote:

    QObject::connect(mMainWindowUI->horizontalslider, SIGNAL(valueChanged(int)), , SLOT(updateCoefficientOfRestitution(int))).

    Where updateCoefficientOfRestitution is defined as a public slot in the Sphere Class. As you can see I am not sure what to put for the third argument because I don't actually create an instance of the class in the mainwindow.cpp file. Can you help me with this too?



  • @ke7omc said in Update Class Value using Slider:

    As you can see I am not sure what to put for the third argument because I don't actually create an instance of the class in the mainwindow.cpp file

    But that is the key. The 3rd parameter needs to be the instance of the Sphere whose coefficient is to be changed.

    You have to arrange your program so that somewhere has access to both the slider and the sphere.

    When you do, you will be helped by changing to the new style of Qt connections:

    QObject::connect(mMainWindowUI->horizontalslider, &QSlider::valueChanged, sphereInstance, &Sphere::updateCoefficientOfRestitution);
    


  • Do you have any thoughts or suggestions on how to do that? I am sorry, still new to programming and I am having trouble with it. I have included my mainwindow.cpp which has access to the slider and my osgwidget.cpp calls the instance: newBall. Could you help explain to me how you might arrange it to be able to have access to slider and newBall?

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindowform.h"
    #include "osgwidget.h"
    #include "SphereUpdateCallback.h"
    
    #include <QDockWidget>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow{parent},
        mMainWindowUI{new Ui::MainWindowForm}
    {
        mMainWindowUI->setupUi(this);
       // QObject::connect(mMainWindowUI->horizontalScrollBar,SIGNAL(valueChanged(int)),   ,SLOT(setCOR(int)));
    }
    
    MainWindow::~MainWindow()
    {
        delete mMainWindowUI;
    }
    
    void MainWindow::on_actionExit_triggered()
    {
        QApplication::quit();
    }
    
    
    
    

    osgwidget.cpp

    #include "osgwidget.h"
    #include "PhysicsLibrary.hpp"
    #include "SphereUpdateCallback.h"
    #include "mainwindow.h"
    
    #include <osg/Camera>
    #include <osg/DisplaySettings>
    #include <osg/Geode>
    #include <osg/Material>
    #include <osg/Shape>
    #include <osg/ShapeDrawable>
    #include <osg/StateSet>
    #include <osgDB/WriteFile>
    #include <osgGA/EventQueue>
    #include <osgViewer/View>
    #include <osgViewer/ViewerEventHandlers>
    #include <osg/MatrixTransform>
    #include <osg/NodeVisitor>
    #include <osg/LineWidth>
    #include <osgUtil/SmoothingVisitor>
    #include <osg/PositionAttitudeTransform>
    
    #include <cassert>
    #include <vector>
    
    #include <QKeyEvent>
    #include <QPainter>
    #include <QWheelEvent>
    
    
    SphereUpdateCallback newBall;
    SphereUpdateCallback *ptr = &newBall;
    
    OSGWidget::OSGWidget( QWidget* parent, Qt::WindowFlags flags ):
        QOpenGLWidget{ parent,flags },
        mGraphicsWindow{ new osgViewer::GraphicsWindowEmbedded{ this->x(),
                                                                this->y(),
                                                                this->width(),
                                                                this->height() } }
      , mViewer{ new osgViewer::CompositeViewer }
    
    {
        mRoot = new osg::Group;
    
        mView = new osgViewer::View;
    
        float aspectRatio = static_cast<float>( this->width() ) / static_cast<float>( this->height() );
        auto pixelRatio   = this->devicePixelRatio();
    
        osg::Camera* camera = new osg::Camera;
        camera->setViewport( 0, 0, this->width() * pixelRatio, this->height() * pixelRatio );
    
        camera->setClearColor( osg::Vec4( 0.f, 0.f, .5, 1.f ) );
        camera->setProjectionMatrixAsPerspective( 45.f, aspectRatio, 1.f, 1000.f );
        camera->setGraphicsContext( mGraphicsWindow );
        mView->setCamera( camera );
    
    
        mView->setSceneData( mRoot.get() );
        mView->addEventHandler( new osgViewer::StatsHandler );
    
        osg::ref_ptr<osgGA::TrackballManipulator> manipulator = new osgGA::TrackballManipulator;
        manipulator->setAllowThrow( false );
        manipulator->setHomePosition(osg::Vec3d(0.0,-20.0,3.0),osg::Vec3d(0,0,0),osg::Vec3d(0,0,1));
        mView->setCameraManipulator( manipulator );
    
    
        mViewer->addView( mView );
        mViewer->setThreadingModel( osgViewer::CompositeViewer::SingleThreaded );
        mViewer->realize();
        mView->home();
    
        osg::Sphere* sphere    = new osg::Sphere( osg::Vec3( 0.f, 0.f, 0.f ), 2.0f );
        osg::ShapeDrawable* sd = new osg::ShapeDrawable( sphere );
        sd->setColor( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
        sd->setName( "Sphere" );
    
        osg::Geode* geode = new osg::Geode;
        geode->addDrawable( sd );
    
        osg::StateSet* stateSet = geode->getOrCreateStateSet();
        osg::Material* material = new osg::Material;
    
        material->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE );
    
        stateSet->setAttributeAndModes( material, osg::StateAttribute::ON );
        stateSet->setMode( GL_DEPTH_TEST, osg::StateAttribute::ON );
    
        osg::PositionAttitudeTransform *transform = new osg::PositionAttitudeTransform;
        transform->setPosition(osg::Vec3( 0.f, 0.f, -9.f ));
        transform->setUpdateCallback(ptr);
        transform->addChild(geode);
    
    
    
        mRoot->addChild(transform);
    
        this->setFocusPolicy( Qt::StrongFocus );
        this->setMinimumSize( 100, 100 );
        this->setMouseTracking( true );
    
        this->update();
    
        double framesPerSecond{30};
        double timeStep{1.0};
        double timerDurationInMilliSeconds{timeStep/framesPerSecond * 1000};
        mTimerId=startTimer(timerDurationInMilliSeconds);
    
    }
    
    OSGWidget::~OSGWidget()
    {
        killTimer(mTimerId);
        delete mViewer;
    }
    
    void OSGWidget::timerEvent(QTimerEvent *)
    {
        update();
    }
    
    void OSGWidget::paintEvent( QPaintEvent* /* paintEvent */ )
    {
        this->makeCurrent();
    
        QPainter painter( this );
        painter.setRenderHint( QPainter::Antialiasing );
    
        this->paintGL();
    
        painter.end();
    
        this->doneCurrent();
    }
    
    void OSGWidget::paintGL()
    {
        mViewer->frame();
    }
    
    void OSGWidget::resizeGL( int width, int height )
    {
        this->getEventQueue()->windowResize( this->x(), this->y(), width, height );
        mGraphicsWindow->resized( this->x(), this->y(), width, height );
    
        this->on_resize( width, height );
    }
    
    void OSGWidget::on_resize( int width, int height )
    {
        std::vector<osg::Camera*> cameras;
        mViewer->getCameras( cameras );
    
        auto pixelRatio = this->devicePixelRatio();
    
        cameras[0]->setViewport( 0, 0, width * pixelRatio, height * pixelRatio );
    }
    
    osgGA::EventQueue* OSGWidget::getEventQueue() const
    {
        osgGA::EventQueue* eventQueue = mGraphicsWindow->getEventQueue();
    
        if( eventQueue )
            return eventQueue;
        else
            throw std::runtime_error( "Unable to obtain valid event queue");
    }
    
    
    


  • @ke7omc
    The main window has the slider, which sends the signal.

    You show a whole load of code of OSGWidget, but your main doesn't create one. I have no idea how they are related.

    SphereUpdateCallback newBall;
    SphereUpdateCallback *ptr = &newBall;
    

    I can only say these lines look dubious?

    I don't know anything about OpenGL/graphics scene stuff here, maybe someone who does will know what you are trying to achieve.



  • Thanks for your time. I was able to figure it out. I took those two lines of code you mentioned and put them in my SphereUpdateCallback.h header file. Then right clicked on the scrollbar in mainwindowform.ui, clicked on go to slots, clicked the appropriate slot and then defined the action as this:

    void MainWindow::on_horizontalScrollBarChangeCoefficientOfRestitution_valueChanged(int value)
    {
        OSGWidget *osgWidget = qobject_cast<OSGWidget *>(findChild<QObject *>("widget"));
        osgWidget->newBall.coefficientOfRestitution = value/100.0;
    }
    

    Again, thank you for your time;)


  • Lifetime Qt Champion

    'widget' is a really bad name when you want to use findChild.
    Also why do you search for a QObject when you case it to a OSGWidget later on? Why not directly searching for a OSGWidget?


Log in to reply