我们先把基本的功能写上:
#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的,所以中心点是需要往中间来偏移。
现在各个功能都已经说完了,我们看一下最后的效果: