重写QGraphicsItem类,实现了标准渐开线圆柱齿轮的绘制,看代码如下,包含一下文件,在自己的程序中可直接使用
#ifndef GEARITEM_H
#define GEARITEM_H
#include <QObject>
#include<QGraphicsItem>
class GearItem : public QObject,public QGraphicsItem
{
Q_OBJECT
public:
explicit GearItem(QGraphicsItem *parent = nullptr);
protected:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
signals:
void sg_degree(double);
public slots:
void slt_setDegree(double _degree);
private:
double m_width=802.0; //宽度
double m_height=802.0; //高度
double m_z=23;
QLineF m_line;
public:
bool bSend=true;
};
#endif // GEARITEM_H
#include "gearitem.h"
#include<QPainter>
#include<math.h>
#include<QDebug>
GearItem::GearItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
// QTransform trans;
// trans.scale(1,-1);
setFlag(ItemIsMovable);
setFlag(QGraphicsItem::ItemSendsGeometryChanges,true);
m_line.setLine(0,0,10,0);
}
QRectF GearItem::boundingRect() const
{
QRectF rectF(0,0,m_width,m_height);
rectF.moveCenter(QPointF(0,0));
return rectF;
}
void GearItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPainterPath painterPath;
painter->setRenderHint(QPainter::SmoothPixmapTransform );
double m=20;
double r=m*m_z*0.5;
double rb=r*cos(20.0*3.1415926/180.0); //基圆半径
double rf=r-1.25*m; //齿根圆半径
double ra=r+1.0*m; //齿顶圆半径
double tan_alpha1=sqrt(rb*rb-rb*rb)/rb;
// double alpha1=atan(tan_alpha1);
// double theta1=tan_alpha1-alpha1;
double tan_alpha2=sqrt(ra*ra-rb*rb)/rb;
double alpha2=atan(tan_alpha2);
double theta2=tan_alpha2-alpha2;
double angle=(tan_alpha2-tan_alpha1)/30;
double theta=tan_alpha1;
QPolygonF polygonF;
while (theta<=tan_alpha2)
{
double x=rb*cos(theta)+rb*theta*sin(theta);
double y=rb*sin(theta)-rb*theta*cos(theta);
polygonF.append(QPointF(x,y));
theta+=angle;
}
QPen pen(Qt::black);
pen.setStyle(Qt::DashDotLine);
pen.setWidthF(0.5);
painter->setPen(pen);
painter->drawEllipse(QPointF(0,0),r,r);
pen.setStyle(Qt::SolidLine);
painter->setPen(pen);
painter->drawEllipse(QPointF(0,0),10,10);
painter->drawLine(-m_width/2,0,m_width/2,0);
double _angle_20=20.0*3.1415926/180.0;
double tan20=tan(_angle_20);
double rotate_angle=tan20-_angle_20;
//分度圆上渐开线的展开角的2倍
// qDebug()<<2*(rotate_angle)*180/3.1415926;
double rotate_degree=(rotate_angle)*180/3.1415926+360/m_z/4; //对称角度
for(int i=0;i<m_z;i++)
{
//绘制渐开线
painter->drawPolyline(polygonF);
//绘制齿顶圆圆弧
{
double degree=rotate_degree-theta2*180/3.1415926;
QRectF rectF(0,0,2*ra,2*ra);
rectF.moveCenter(QPointF(0,0));
painter->drawArc(rectF,(-theta2*180/3.1415926)*16,(-degree)*16*2);
}
QLineF lineF(polygonF.first(),QPointF(0,0));
lineF.setLength(rb-rf);
painter->drawLine(lineF);
// 绘制齿根圆圆弧
{
double degree=360/m_z-2*rotate_degree;
QRectF rectF(0,0,2*rf,2*rf);
rectF.moveCenter(QPointF(0,0));
painter->drawArc(rectF,(-0)*16,(degree)*16);
}
painter->rotate(360/m_z);
}
//坐标轴对称变换 旋转
painter->scale(1,-1);
painter->rotate(-2*(rotate_degree));
for(int i=0;i<m_z;i++)
{
painter->drawPolyline(polygonF);
painter->rotate(360/m_z);
QLineF lineF(polygonF.first(),QPointF(0,0));
lineF.setLength(rb-rf);
painter->drawLine(lineF);
}
}
QVariant GearItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if(change==ItemRotationChange)
{
if(bSend)
{
emit sg_degree(value.toDouble()-rotation());
}
}
else if(change==ItemPositionChange)
{
QLineF line(QPointF(0,0),mapToItem(this,value.toPointF()));
double degree=(line.angle(m_line));
qDebug()<<"degree"<<degree;
if(degree<0)
{
degree=-degree;
}
setRotation(degree); //旋转相应角度
return pos();
}
return QGraphicsItem::itemChange(change,value);
}
void GearItem::slt_setDegree(double _degree)
{
setRotation(rotation()-_degree);
}