一个QT新手,记录学习历程
在qt官方文档没有找到搜索功能,每次都是一个个找函数位置,如果你知道方便的查找某个函数的文档,欢迎评论告诉我
其他
这个弄完之后长这样
特别说明:界面参考@GeeeekExplorer(应该是我上一届的学长),图片来源也是从这位同学项目资源(https://github.com/GeeeekExplorer/NJU-Computer-Graphics/tree/master/rc,并不是自己制作!非常感谢学长,如果您不希望我使用这些图片,可以联系我剔除。我的邮箱是[email protected]
其他图片,我也没想到啥好方法,就用procreate自己画(又是procreate大材小用的一天)
UI界面不更新
一个无情的文档搬运工
槽机制
文档-鼠标事件
文档-Qwidget-鼠标移动,按下,释放函数都在同页面
文档-绘图事件
文档-Qwidget-绘图函数
文档-Qwidget-窗口大小
文档-画笔
文档-笔刷
文档-qlist
文档-qvector
void MainWindow::paintEvent(QPaintEvent *event){
Q_UNUSED(event);
m_image.fill(Qt::white);
m_painter.begin(&m_image);
for(Shape* p:m_shapes){
m_painter.setPen(p->pen());
m_painter.drawPoints(p->points());
}
m_painter.end();
ui->label->setPixmap(QPixmap::fromImage(m_image));
}
void MainWindow::resizeEvent(QResizeEvent *event){
Q_UNUSED(event);
ui->label->resize(ui->centralwidget->size());
m_image = QImage(ui->label->size(), QImage::Format_RGB32);
}
嗯,只能水平竖直线,而且位置也不对
原因是坐标没有转换:QT获取鼠标位置
现在位置对了,但是只有水平竖直线
改着改着就疯狂未响应,我整个电脑都卡了
原因是我合并情况写错了,所以死循环了,嗯。。。内心复杂
至于为什么只有水平竖直,因为这里我把初始点写了int,所以算增量的时候截断成0了
现在可以了,检查的时候可以一个点按下然后转一圈看各种形态的直线
//用的是DDA
if (m_args.size()!=2)
return {};
double x0 = m_args[0].x(),y0 = m_args[0].y();
double x1 = m_args[1].x(),y1 = m_args[1].y();
QVector<QPoint>points_tmp;
points_tmp.append(QPoint(x0,y0));
if (x0 == x1 || y0==y1){//水平、竖直
int dx= x0==x1?0:(x0<x1?1:-1);
int dy= y0==y1?0:(y0<y1?1:-1);
while(x0!=x1 || y0!=y1){
x0+=dx;
y0+=dy;
points_tmp.append(QPoint(x0,y0));
}
return points_tmp;
}
double dx = 0,dy = 0;
double px = qAbs(x0-x1),py = qAbs(y0-y1);
if ( px > py ){
dx = x0<x1?1:-1;
dy = (y1-y0)/px;
while(x0 != x1){
x0+=dx;
y0+=dy;
points_tmp.append(QPoint(x0,y0));
}
}
else{
dy = y0<y1?1:-1;
dx = (x1-x0)/py;
while(y0 != y1){
x0+=dx;
y0+=dy;
points_tmp.append(QPoint(x0,y0));
}
}
return points_tmp;
合并了下其他形态的直线
//其他直线
double dx = 0,dy = 0;
double px = qAbs(x0-x1),py = qAbs(y0-y1);
dx = px>py?(x0<x1?1:-1):(x1-x0)/py;
dy = px>py?(y1-y0)/px:(y0<y1?1:-1);
while( (px>=py &&x0 != x1) || (px<py && y0 != y1)){
x0+=dx;
y0+=dy;
points_tmp.append(QPoint(x0,y0));
}
然后合并全形态直线。
总结起来就是先看增长方向,增长方向是增量0,1,-1,另一个方向是斜率/斜率倒数
循环条件是增长方向
assert(m_args.size() == 2);
double x0 = m_args[0].x(),y0 = m_args[0].y();
double x1 = m_args[1].x(),y1 = m_args[1].y();
QVector<QPoint>points_tmp;
points_tmp.append(QPoint(x0,y0));
double dx = 0,dy = 0;
double px = qAbs(x0-x1),py = qAbs(y0-y1);
dx = px>=py?(x0==x1?0:(x0<x1?1:-1)):(x1-x0)/py;
dy = px>py?(y1-y0)/px:(y0==y1?0:(y0<y1?1:-1));
while( (px>=py &&x0 != x1) || (px<py && y0 != y1)){
x0+=dx;
y0+=dy;
points_tmp.append(QPoint(x0,y0));
}
文档-append-追加一个vector
我一开始是想这样有三个点之后加入集合,后来想到如果大小是1,2的时候创建了对象又换了状态,这个对象没放到shapes里面,不好删除。所以就还是改成创建的时候就加入
别忘记首尾相连啊
int sz = m_args.size();
if (sz<2)
return {};
Line* tmp_line = new Line({m_args[0],m_args[1]},m_pen);
QVector<QPoint>points_tmp;
for(int i=1;i<sz;++i){
tmp_line->setArgs({m_args[i-1],m_args[i]});
points_tmp.append(tmp_line->points());
}
tmp_line->setArgs({m_args[sz-1],m_args[0]});
points_tmp.append(tmp_line->points());
delete tmp_line;
return points_tmp;
等腰三角形,按下点为顶点,移动鼠标另一点与顶点构成腰,另一边对称计算点坐标
矩形,按下点和移动点作为左上和右下点,其他点对称计算
按下一个点然后转一圈看各种形态的三角形,矩形
连接线:首尾不闭合的多边形
中点圆生成算法
按下一个点作为圆形,拖动鼠标确定半径
按下以及拖动形成边框,在边框内绘制椭圆
按下一个点然后转一圈看各种形态的圆,椭圆
def draw_ellipse(p_list):
"""绘制椭圆(采用中点圆生成算法)
:param p_list: (list of list of int: [[x0, y0], [x1, y1]]) 椭圆的矩形包围框左上角和右下角顶点坐标;
:return: (list of list of int: [[x_0, y_0], [x_1, y_1], [x_2, y_2], ...]) 绘制结果的像素点坐标列表
"""
#计算椭圆中心和rx,ry
x0, y0 = p_list[0]
x1, y1 = p_list[1]
result = []
xc = (x0 + x1) / 2
yc = (y0 + y1) / 2
rx = abs(x1 - xc)
ry = abs(y1 - yc)
rx2 = pow(rx, 2)
ry2 = pow(ry, 2)
x = 0
y = ry
pk = ry2 - rx2 * ry + rx2 / 4
#####区域1,+1和-0.5是两个区域连接部分有些缺口,自调的
while ry2 * (x + 1) < rx2 * (y - 0.5):
if pk < 0:
pk += ry2 * (2 * x + 3)
x += 1
result.append([x, y])
else:
pk += ry2 * (2 * x + 3) + rx2 * (2 - 2 * y)
x += 1
y -= 1
result.append([x, y])
pk = ry * (x + 0.5) * 2 + rx * 2 * (y - 1) - rx * 2 * ry
###区域2
while y > 0:
if pk < 0:
x += 1
y -= 1
pk += 2 * ry2 * x - 2 * rx2 * y + rx2
result.append([x, y])
else:
y -= 1
pk += rx2 - 2 * rx2 * y
result.append([x, y])
###加入对称点
length = len(result)
for i in range(length):
basex, basey = result[i]
result.append([-basex + xc, basey + yc])
result.append([-basex + xc, -basey + yc])
result.append([basex + xc, -basey + yc])
result[i] = [basex + xc, basey + yc]
return result
圆是八分图,取一份然后做对称
中点圆生成算法
椭圆是四分图,每一分里按xy分为两个部分绘制(圆是xy对换,椭圆得分别算)
首先确定怎么选中图形
确定鼠标落点
图形是空心的,所以用区域contain不太好,我写的是判断点集
因为很难精确选中,所以给了容错空间
把所有参数平移,再绘制
RE: 重新绘制增加计算量,还是把所有point都平移了
。。。。。。。。。。。。。。。。。。
项目写完了,博客不想写了【lazy】