[Programming a pushbutton to do a certain task]
-
Hello,
I hope you're all doing well.
So in my application, I have two classes: MainWindow and MainWidget.
In my mainwidget I have a paintGL() function in which I rotate an object using quaternion.
this is how it is done :
quaternion = QQuaternion(quat_w, quat_x, quat_y, quat_z); localMatrix.rotate(quaternion);
where localMatrix is the modelview matrix.
In mainwindow.ui, there are four spin boxes, each one of them corresponds to the quaternion components ( w, x, y and z).
So when the user changes these values, the object rotates.
Now I want to add a push button which when clicked the rotation will be applied. It means that the user should first insert quaternion values in the spin boxes then click on the push button to apply the rotation.
However I'm so confused because:
-The function of the push button exists in the mainwindow.cpp
-The quaternion and the rotating function exist in the paintGL() methods of the class mainwidget.I'm not sure how to connect them.
Should I use signals and slots to connect the changing of the values in the spin boxes and the rotating function ? The rotating function which is
quaternion.rotate(localMatrix)
should be in the paintGL() method of class mainwidget to ensure that the object rotates.
If anyone have a tip, I really would appreciate it if you share it with me.
As a first attempt I did this:
void MainWindow::on_pushButton_3_clicked() { this->ui->mainwidget->localMatrix.rotate(this->ui->mainwidget->quaternion); }
But this didn't work and things got really messed up.
Plus the rotate function should be inside the paintGL().Thank you all.
-
@appdev said in [Programming a pushbutton to do a certain task]:
this->ui->mainwidget->localMatrix.rotate(this->ui->mainwidget->quaternion);
You should not do things like this. Do not access internal details of a class from another one. MainWindow should not know anything about mainwidget internals like localMatrix. Instead implement a public method in your mainwidget which you then call from MainWindow to trigger whatever you need to do.
-
@jsulm First of all.
Thank you for your reply.The problem is that I need this push button to execute a function that can only be called inside the paintGL() method of the class MainWidget.
The paintGL() method render the object and ensure its rotation using the
void QMatrix4x4::rotate(const QQuaternion &quaternion)
I don't see how I can access to that function and execute it using the push button.
-
@appdev As IU wrote: add a public method to your MainWidget class:
class MainWidget... public: void rotate() { localMatrix.rotate(quaternion); }
And then simply call that method in MainWindow:
void MainWindow::on_pushButton_3_clicked() { ui->mainwidget->rotate(); }
You would need to implement MainWidget as a stand-alone widget and promote it to your ui.
-
@appdev
I can't get into a discussion about OpenGl or matrices or quaternions because I know nothing about any of it :)But consider your line
this->ui->mainwidget->localMatrix.rotate(this->ui->mainwidget->quaternion);
Note how both the method call and the parameter start with
this->ui->mainwidget
. So you can factor what this does away into your definition of yourMainWidget
class.EDIT Oh @jsulm has just shown you :)
-
@jsulm @JonB I tried to do that but there is a problem.
To make that public method work, localMatrix should be a member variable of mainwidget. However I want it to be a local variable of the paintGL() function. Otherwise, a problem will occur when it comes to rendering the object and its coordinate system.
The localMatrix here is my modelview matrix. I used it to render an object ( a cube ) and two coordinate systems that are attached to it.
When I declare localMatrix as a member variable, one of the coordinate system becomes detached from the object. -
@appdev said in [Programming a pushbutton to do a certain task]:
localMatrix should be a member variable of mainwidget
It is already according to your code:
this->ui->mainwidget->localMatrix.rotate(this->ui->mainwidget->quaternion);
So, don't know what the problem is...
-
Yes, according to my code, it is a member variable, I changed it so I can use it in the mainwindow.cpp.
But then, I had some problems when rendering the scene ( as I mentioned one of the coordinate system became detached of the object so something went wrong).
But I don't want it to be a member variable. I want it to be a local so that I can avoid the rendering problem. -
Update:
@jsulm @JonB
I declared a boolean variable in my mainwidget.h:Bool ApplyRotation;
Then each time ApplyRotation is true, the object changes its orientation.
In mainwindow.cpp:
void MainWindow::on_pushButton_3_clicked() { this->ui->mainwidget->ApplyRotation = true; }
In my mainwidget.cpp:
if(ApplyRotation == true) { ApplyRotation=False; EulerAngles.append(quaternion.toEulerAngles()); //rotation order is 213. localMatrix.rotate(quaternion); }
However, when I insert quaternion values in the spin boxes and then click on Apply button, the object changes its orientation and then goes back to its initial orientation. I want it to stay at the new position.
So I removed the line
ApplyRotation=False;
Now after inserting the quaternion values in the spin boxes and then clicking on the apply button, the object changes its orientation.
But, when I change again the values in the spin boxes the object keeps rotating. It means I don't need to click on the button anymore. That's the problem.My goal is to make the object rotate each time I click on the push button.
I don't get why it is not working with the first code I posted. However what I did seems so logical. -
@appdev
I don't see anything in your code where anyone could possibly comment on your behaviour. All we see is setting & testing a boolean variable, how can that tell us/you what your issue is?My goal is to make the object rotate each time I click on the push button.
Then you need to call whatever code from your pushbutton clicked slot. Simply setting a variable there won't even make anything hit the
if(ApplyRotation == true)
elsewhere in your code. -
Okay,
I put that code because I thought that the rest of it isn't necessary to show .
Here is my paintGL() method in the class MainWidget:void MainWidget::paintGL() { //qDebug()<<__func__; // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //================Orbital Frame ==========================================// QMatrix4x4 localMatrix; glMatrixMode(GL_PROJECTION); glLoadMatrixf(projection.constData()); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(localMatrix.constData()); gluLookAt(2.0,2.0,0.0,0.0,0.0,-5.0,0.0,1.0,0.0); glTranslatef(0.0,0.0,-5.0); glRotatef(180.0,0.0,1.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glScalef(0.4,0.4,0.4); //glMatrixMode(GL_PROJECTION); DrawOrbitalFrame(); program.bind(); texture->bind(); // Calculate model view transformation //qDebug()<<"modelview before transformation"<<matrix; //qDebug()<<"modelview matrix"<<localMatrix; localMatrix.setToIdentity(); localMatrix.lookAt(QVector3D(2.0, 2.0, 0.0), QVector3D(0.0,0.0,-5.0),QVector3D(0.0,1.0,0.0)); localMatrix.translate(0.0, 0.0, -5.0); localMatrix.scale(0.4,0.4,0.4); quaternion = QQuaternion(quat_w, quat_x, quat_y, quat_z); quaternion.normalize(); // Normalizing my quaternion if(ApplyRotation == true) { EulerAngles.append(quaternion.toEulerAngles()); //rotation order is 213. localMatrix.rotate(quaternion); } program.setUniformValue("mvp_matrix", projection * localMatrix); update(); //! [6] //! // Use texture unit 0 which contains cube.png program.setUniformValue("texture", 0); // Draw cube geometry geometries->drawCubeGeometry(&program); texture->release(); program.release(); }
And in my MainWindow class where I programmed the push button:
void MainWindow::on_pushButton_3_clicked() { this->ui->mainwidget->ApplyRotation = true; }
That's what I actually did, I called the variable applyRotation in my my piantGL() method to rotate the object once the user inserts the quaternion value and click on the push button.