在NodeGraphicsItem小圆点类里面加入新的成员:
double lastPos;
double currentPos;
double nextPos;
double opacity;
void setMargin(int x,int y,int w,int h);
int xStart;
int yStart;
int widthRe;
int heightRe;
int currentX;
int currentY;
void NodeGraphicsItem::setMargin(int x, int y, int w, int h)
{
xStart = x;
yStart = y;
widthRe = w;
heightRe = h;
}
其中,下面设置区域的,就是设置它的起始位置以及宽度。暂时我们先不管它怎么用。说一下其他变量,lastPos是上一个点的位置,这里是小数形式(范围0——1),currentPos是当前位置,以及nextPos是表示下个位置。然后是不透明度(纵轴数据高度)。
在该类中继续添加 NodeXmlItem *nodeXmlItemInGraphics;用来指向一个节点。注意我们用指针类型,直接指向数据本身(而不是其拷贝)
然后在移动函数中:
QVariant NodeGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionChange && scene())
{
QPointF newPos = value.toPointF();
QRectF rect(xStart + widthRe*lastPos,yStart, widthRe*(nextPos-lastPos),heightRe );
if (!rect.contains(newPos))
{
newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
currentPos = (double)(newPos.x() - xStart) / (double)(widthRe);
nodeXmlItemInGraphics->setNormalizedIntensity(currentPos);
opacity = (double)(yStart + heightRe - newPos.y()) / (double)(heightRe);
nodeXmlItemInGraphics->setOpacity(opacity);
//DebugText::getDebugText()->addContents(QString::number(currentPos));
//DebugText::getDebugText()->addContents(QString::number(opacity));
return newPos;
}
currentPos = (double)(newPos.x() - xStart) / (double)(widthRe);
nodeXmlItemInGraphics->setNormalizedIntensity(currentPos);
opacity = (double)(yStart + heightRe - newPos.y()) / (double)(heightRe);
nodeXmlItemInGraphics->setOpacity(opacity);
//DebugText::getDebugText()->addContents(QString::number(currentPos));
//DebugText::getDebugText()->addContents(QString::number(opacity));
}
return QGraphicsItem::itemChange(change, value);
}
这里的移动范围是根据我们设置的前后位置来设置的。这样,我们只需要在每次绘制点的时候把所有的坐标的前面的一个坐标位置,和后面的一个坐标位置设置进去,就能得到最后我们想要的值。
然后我们再继承一个类,继承自线段图形项
class LigatureForNodesGraItem : public QGraphicsLineItem
里面你可以自己随便设置线宽和粗细,因为没有什么自带的函数,这里就不把程序列入了。
之后在我们的矩形图形项中,我们需要能够添加并且使用这些小圆点。我们在矩形图形项中添加如下成员:
TsfunXmlItem *tsfunXmlItemInView;
NodeGraphicsItem *item;
NodeGraphicsItemList NdGraItemlist;
LigatureForNodesGraItem *ligatureitem;
LigatureItemList ligatureitemlist;
Margin tfgraItemMargin;
void initializeLigature();
void itemsUpdate();
void ligatureUpdate();
void setWidthHeight(int, int);
void setPaintable(int, int);
int width;
int height;
int paintWidth;
int paintHeight;
首先我们有一个指针,指向xml文件读出以后的数据结构(指向其本身)。然后是NodeGraphicsItem的指针和列表。注意这个列表里面的元素也是指针类型的。然后定义了画线的类。以及画线的列表(注意这个列表你可以用typedef别名,也可以直接QList<T>创建,这里不再赘述)。
之后设置显示区域Margin。
然后设置更新图形项的函数,以及更新线段项的函数,设置宽高,设置可画线区域。关于区域后面再说。(其实如果你有其他想法完全可以按自己的想法设置区域)
初始化函数里我们这么定义:
TsfunGraphicsItem::TsfunGraphicsItem(QGraphicsRectItem * parent) : QGraphicsRectItem(parent),
tfgraItemMargin(0,0,0,0)
{
setBrush(QBrush(QColor(100, 200, 100, 50)));
setZValue(0);
//指针指向原始数据
tsfunXmlItemInView = tsfunxmlitem;
//显示并添加item
double lastPosn = 0, currentPosn = 0, nextPosn = 0;
int i = 0;
for (i = 0;i < tsfunXmlItemInView->nodeXmlItemList.count() - 1;i++) {
item = new NodeGraphicsItem();
item->index = i;
item->nodeXmlItemInGraphics = &(tsfunXmlItemInView->nodeXmlItemList[i]);
item->currentPos = tsfunXmlItemInView->nodeXmlItemList[i].returnNormalizedIntensity();
item->opacity = tsfunXmlItemInView->nodeXmlItemList[i].returnOpacity();
item->lastPos = lastPosn;
item->nextPos = tsfunXmlItemInView->nodeXmlItemList[i + 1].returnNormalizedIntensity();
lastPosn = item->currentPos;
if (i == 0) {
item->nextPos = 0;
}
NdGraItemlist.append(item);//一定要注意传入实体
}
item = new NodeGraphicsItem;
item->nodeXmlItemInGraphics = &(tsfunXmlItemInView->nodeXmlItemList[i]);
item->index = i;
item->lastPos = 1;item->currentPos = 1;item->nextPos = 1;
item->opacity = tsfunXmlItemInView->nodeXmlItemList[i].returnOpacity();
NdGraItemlist.append(item);
}
这里的tsfunXmlItemInView = tsfunxmlitem;中的tsfunxmlitem是总程序一开始就创建的指针,指向读入的xml文件中的某一个tsfunxmlitem(之前讲过xml文件里有一个根节点group,group里面有两个子节点item)。
显示并添加NodeGraItem,根据里面的原始值来设置rgb和不透明度。这里我比较懒,就没有设置rgb,只读出了位置和不透明度opacity。初始点的前后都是0,让它不能移动。结尾点前后都是1,也让它不能移动。
同时我们让nodeXmlItemInGraphics指向了原始数据的一个NodeXmlItem,这样,当我们运动的时候,原始数据(非拷贝值)就被修改了,根据原始数据生成的新的NodeGraItem的坐标就是你移动后的坐标了。
这样初始化就完成了。