QT三维图形4

211 阅读2分钟

我们先把基本的功能写上:

`#include <QGroupBox>
#include "qDoubleSlider.hpp"
#include <qlabel.h>
#include <qgridlayout.h>
class My3DCentralPoint : public QGroupBox {
        Q_OBJECT

public:
        My3DCentralPoint(QWidget * parent = Q_NULLPTR);
        ~My3DCentralPoint();

        QDoubleSlider *xSlider4Pos;
        QDoubleSlider *ySlider4Pos;
        QDoubleSlider *zSlider4Pos;
        QLabel *xLabelPos;
        QLabel *yLabelPos;
        QLabel *zLabelPos;

        double xLeft, xRight;
        double yLeft, yRight;
        double zLeft, zRight;
        double xCurrent, yCurrent, zCurrent;

signals:
        void needUpdate(void);

private slots:
        void xBoundaryChanged(double);
        void yBoundaryChanged(double);
        void zBoundaryChanged(double);

        void xPosChanged(double);
        void yPosChanged(double);
        void zPosChanged(double);
};`

里面的xLeft这些分别是中心点在各个方向上可以运动的左右边界。

信号是发送给之前的OpenGL类的,用于其更新显示区。

槽里面有自身使用的三个槽:

`void xPosChanged(double);
void yPosChanged(double);
void zPosChanged(double);`

当该类里面的滑动条运动的时候,要通知我们的类去修改坐标值:

`void My3DCentralPoint::xPosChanged(double Value) {
        xCurrent = Value;
        centralRectPos[0] = xCurrent;
        emit needUpdate();
}
void My3DCentralPoint::yPosChanged(double Value) {
        yCurrent = Value;
        centralRectPos[1] = yCurrent;
        emit needUpdate();
}
void My3DCentralPoint::zPosChanged(double Value) {
        emit needUpdate();
        centralRectPos[2] = zCurrent;
        zCurrent = Value;
}`

而剩下的三个槽,则比较复杂,我们待会再说。

`#include "my3dcentralpoint.hpp"
#include <qopenglwindow.h>
extern GLfloat centralRectPos[3];
extern GLfloat halfBoundaries[3];

My3DCentralPoint::My3DCentralPoint(QWidget * parent) : QGroupBox(parent) {
        setTitle("Central Point Setting");
        QGridLayout *gridlayout = new QGridLayout(this);
        xSlider4Pos = new QDoubleSlider;
        ySlider4Pos = new QDoubleSlider;
        zSlider4Pos = new QDoubleSlider;
        xLabelPos = new QLabel("xPos: ");
        yLabelPos = new QLabel("yPos: ");
        zLabelPos = new QLabel("zPos: ");
        gridlayout->addWidget(xLabelPos, 0, 0);
        gridlayout->addWidget(yLabelPos, 1, 0);
        gridlayout->addWidget(zLabelPos, 2, 0);
        gridlayout->addWidget(xSlider4Pos, 0, 1);
        gridlayout->addWidget(ySlider4Pos, 1, 1);
        gridlayout->addWidget(zSlider4Pos, 2, 1);


        xLeft = halfBoundaries[0] - 0.5;
        xRight =  0.5 - halfBoundaries[0];
        yLeft = halfBoundaries[1] - 0.5;
        yRight = 0.5 - halfBoundaries[1];
        zLeft = halfBoundaries[2] - 0.5;
        zRight = 0.5 - halfBoundaries[2];
        xCurrent = centralRectPos[0];
        yCurrent = centralRectPos[1];
        zCurrent = centralRectPos[2];
        xSlider4Pos->setRange(xLeft, xRight);
        xSlider4Pos->setValue(centralRectPos[0]);
        xSlider4Pos->setRange(yLeft, yRight);
        xSlider4Pos->setValue(centralRectPos[1]);
        xSlider4Pos->setRange(zLeft, zRight);
        xSlider4Pos->setValue(centralRectPos[2]);

        connect(xSlider4Pos, SIGNAL(valueChanged(double)),
                this, SLOT(xPosChanged(double)));
        connect(ySlider4Pos, SIGNAL(valueChanged(double)),
                this, SLOT(yPosChanged(double)));
        connect(zSlider4Pos, SIGNAL(valueChanged(double)),
                this, SLOT(zPosChanged(double)));


}`

在构造函数中,我们首先根据初始值来把滑动条的范围给限定好。然后绑定自己的信号和槽。

在DockWidget中,我们再绑定另外三个槽,以及我们这个类中的信号:

`connect(my3dhalfboundary->xSlider4HalfBnd, SIGNAL(valueChanged(double)),
        my3dcentralpoint, SLOT(xBoundaryChanged(double)));
connect(my3dhalfboundary->ySlider4HalfBnd, SIGNAL(valueChanged(double)),
        my3dcentralpoint, SLOT(yBoundaryChanged(double)));
connect(my3dhalfboundary->zSlider4HalfBnd, SIGNAL(valueChanged(double)),
        my3dcentralpoint, SLOT(zBoundaryChanged(double)));

connect(my3dcentralpoint, SIGNAL(needUpdate(void)),
        my3dDisplayWidget, SLOT(neededUpdate(void)));`

这样相当于边界变化以后,中心点位置类先做调整,把数组更新,然后告诉OpenGL部件需要重新更新一下。

之后再单独拿出来一个轴的槽来讲解:

`void My3DCentralPoint::xBoundaryChanged(double Value) {
        if ((xCurrent - Value) < -0.5) {
                xCurrent =  Value - 0.5;

        }
        else if ((xCurrent + Value)>0.5) {
                xCurrent = 0.5 - Value;
        }
        centralRectPos[0] = xCurrent;
        halfBoundaries[0] = Value;
        xSlider4Pos->setRange(Value - 0.5, 0.5 - Value);
        emit needUpdate();
}`

如果当前中心点位置的值(xCurrent)减去边界值(Value)超过了边界,则我们需要移动中心点,让它往中间移(即令立方体的边贴着大立方体的边)。然后给中心点设置其变化范围。

也就是说,假如我们现在的边界长是0.3了,我们的坐标位置在0.3处,而0.3+0.3是大于0.5的,所以中心点是需要往中间来偏移。

现在各个功能都已经说完了,我们看一下最后的效果:

image.png