算法原理:鼠标放在图形区域的某一块位置,得到鼠标的点坐标,将图形以该点为中心缩放图形。
1、先指定一块图形显示区域。
QRect updateArea = QRect(388, 31, 812, 729);
2、得到鼠标坐标位置,以及设置鼠标上滑放大,下滑缩小函数。
protected:
void wheelEvent(QWheelEvent* event) override {
this->initX = event->scenePosition().x();
this->initY = event->scenePosition().y();
if (this->initX >= 400 && this->initX <= 1200 && this->initY >= 40 && this->initY <= 760)
{
int numDegrees = event->angleDelta().y() / 8;
int numSteps = numDegrees / 15;
// 根据滚轮滚动方向调用放大或缩小的函数
if (numSteps > 0) {
zoomOut();
}
else {
zoomIn();
}
event->accept();
}
}
private:
void zoomIn();
void zoomOut();
void BRPA::zoomIn() {
// 缩小到 80%
//scale *= 0.8;
this->scale = 0.8;
this->needToUpdateArea = true;
update(updateArea); // 重新绘制界面
}
void BRPA::zoomOut() {
// 放大到 120%
//scale *= 1.2;
this->scale = 1.2;
this->needToUpdateArea = true;
update(updateArea); // 重新绘制界面
}
3、我的图形和线段的数据结构
struct Point2
{
float x = 0;
float y = 0;
};
struct Segment2
{
Point2 source;
Point2 target;
};
struct Polygon2
{
std::vector<Point2> poly;
};
struct PointData
{
std::vector<Polygon2> support;
std::vector<Segment2> fill;
std::vector<Polygon2> polys;
};
4、重写绘制图形函数
void paintEvent(QPaintEvent* event) override;(.h 函数声明)
void BRPA::paintEvent(QPaintEvent* event){
Q_UNUSED(event);
if (this->needToUpdateArea)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.fillRect(this->updateArea, Qt::white);
painter.setPen(QPen(Qt::red, 1));
//this->drawData 为 PointData drawData;
for (auto it = this->drawData.fill.begin(); it != this->drawData.fill.end(); it++)
{
//std::cout << it->source.x << " " << it->source.y << " " << it->target.x << " " << it->target.y << std::endl;
//this->initX this->initY 为鼠标点的位置
it->source.x = (it->source.x - this->initX) * this->scale + this->initX;
it->source.y = (it->source.y - this->initY) * this->scale + this->initY;
it->target.x = (it->target.x - this->initX) * this->scale + this->initX;
it->target.y = (it->target.y - this->initY) * this->scale + this->initY;
//std::cout<<it->source.x<<" "<<it->source.y<<" "<<it->target.x<<" "<<it->target.y<<std::endl;
//painter.drawLine(QPointF((it->source.x - this->initX)*this->scale + this->initX, (it->source.y - this->initY) * this->scale + this->initY), QPointF((it->target.x - this->initX) * this->scale + this->initX, (it->target.y - this->initY) * this->scale + this->initY));
painter.drawLine(QPointF(it->source.x, it->source.y), QPointF(it->target.x , it->target.y ));
}
painter.setPen(QPen(Qt::black));
for (auto polyIt = this->drawData.polys.begin(); polyIt != this->drawData.polys.end(); polyIt++)
{
polyIt->poly.front().x = (polyIt->poly.front().x - this->initX) * this->scale + this->initX;
polyIt->poly.front().y = (polyIt->poly.front().y - this->initY) * this->scale + this->initY;
for (auto vert = polyIt->poly.begin(); vert != (--polyIt->poly.end()); vert++)
{
(vert+1)->x = ((vert+1)->x - this->initX) * this->scale + this->initX;
(vert+1)->y = ((vert+1)->y - this->initY) * this->scale + this->initY;
painter.drawLine(QPointF(vert->x, vert->y), QPointF((vert+1)->x, (vert+1)->y));
}
//painter.drawLine(QPointF(polyIt->poly.back().x, polyIt->poly.back().y), QPointF(polyIt->poly.front().x, polyIt->poly.front().y));
}
painter.setPen(QPen(Qt::green));
for (auto supIt = this->drawData.support.begin(); supIt != this->drawData.support.end(); supIt++)
{
supIt->poly.front().x = (supIt->poly.front().x - this->initX) * this->scale + this->initX;
supIt->poly.front().y = (supIt->poly.front().y - this->initY) * this->scale + this->initY;
for (auto supVer = supIt->poly.begin(); supVer != (--supIt->poly.end()); supVer++)
{
(supVer+1)->x = ((supVer+1)->x - this->initX) * this->scale + this->initX;
(supVer+1)->y = ((supVer+1)->y - this->initY) * this->scale + this->initY;
painter.drawLine(QPointF(supVer->x, supVer->y), QPointF((supVer+1)->x, (supVer+1)->y));
}
}
this->needToUpdateArea = false;
}
}
其中QPainter有直接绘制poly的drawPolygon等函数,但最终都殊途同归。
如有误,请指出,谢谢!