如何在QT中实现可以擦除路径的涂鸦?
How to implement scribble drawing with possibility to erase paths in QT?
在 QT 中实现像绘图一样涂鸦但又能够擦除一些绘制路径的正确方法是什么?
我见过一些示例,其中通过将椭圆作为点添加到图像 (QImage) 来实现绘图,但据我了解,您将无法删除任何绘制的线条?我一直在考虑的一件事是实施 QPainterPaths。在鼠标按下时,开始一条新路径,在鼠标移动时在鼠标位置向路径添加点,在鼠标释放时完成此路径。在绘制事件中,我将遍历 QPainterPaths 数组并绘制它们中的每一个。在擦除时,我会遍历数组中的每个 QPainterPath 并检查是否有任何点发生碰撞,如果是,则从数组中删除整个路径,有效地擦除它。
这是某种有效的方法还是 QPaths 无法实现的方法?
是否有更好、更智能的方法?
这似乎确实是一种有效的方法,或者至少是一种可行的方法,尽管我的问题有点宽泛,但最终有人会发现有用的答案:
/*
* QList<QGraphicsPathItem *> mList;
* bool mErase;
* QPainterPath * mCurrentPath;
* QPainterPathStroker mStroker;
*/
void ScribbleArea::mousePressEvent ( QGraphicsSceneMouseEvent* event)
{
if(!mErase)
{
mCurrentPath = new QPainterPath();
mCurrentPath->moveTo(event->lastScenePos());
mList.append(addPath(mStroker.createStroke(*mCurrentPath), QPen(Qt::red), QBrush(Qt::red)));
}
QGraphicsScene::mousePressEvent(event);
}
void ScribbleArea::mouseMoveEvent ( QGraphicsSceneMouseEvent* event)
{
if(!mErase)
{
mCurrentPath->lineTo(event->lastScenePos());
mList[mList.count()-1]->setPath(mStroker.createStroke(*mCurrentPath));
}
else
{
for(int i=0; i < mList.count(); i++)
{
if(mList[i]->isUnderMouse())
{
removeItem(mList[i]);
delete mList[i];
mList.removeAt(i);
}
}
}
QGraphicsScene::mouseMoveEvent(event);
}
这是两个关键函数,在 mousePressEvent 上我开始一个新路径并将其移动到当前鼠标位置,接下来,我将路径添加到 QGraphicsScene 以获得指向 QGraphicsPathItem 的指针,我将在 mouseMoveEvent 中使用它功能。
在 mouseMoveEvent 函数中,我首先检查我们当前是在擦除还是在绘图。在绘图的情况下,我从路径最后一点到当前鼠标位置添加一条线,然后再次将路径添加到 QGraphicsScene,否则它不会显示这些新线(也许有更好的方法,我愿意改进),这就是它的绘图。
如果我们要删除,我会查看所有路径的列表并检查当前是否有任何路径在鼠标下,如果是,请将其删除。
这目前只是一个草稿,更多的改进即将到来。
drawing/scribbling的一些很棒的例子:
在 QT 中实现像绘图一样涂鸦但又能够擦除一些绘制路径的正确方法是什么?
我见过一些示例,其中通过将椭圆作为点添加到图像 (QImage) 来实现绘图,但据我了解,您将无法删除任何绘制的线条?我一直在考虑的一件事是实施 QPainterPaths。在鼠标按下时,开始一条新路径,在鼠标移动时在鼠标位置向路径添加点,在鼠标释放时完成此路径。在绘制事件中,我将遍历 QPainterPaths 数组并绘制它们中的每一个。在擦除时,我会遍历数组中的每个 QPainterPath 并检查是否有任何点发生碰撞,如果是,则从数组中删除整个路径,有效地擦除它。
这是某种有效的方法还是 QPaths 无法实现的方法?
是否有更好、更智能的方法?
这似乎确实是一种有效的方法,或者至少是一种可行的方法,尽管我的问题有点宽泛,但最终有人会发现有用的答案:
/*
* QList<QGraphicsPathItem *> mList;
* bool mErase;
* QPainterPath * mCurrentPath;
* QPainterPathStroker mStroker;
*/
void ScribbleArea::mousePressEvent ( QGraphicsSceneMouseEvent* event)
{
if(!mErase)
{
mCurrentPath = new QPainterPath();
mCurrentPath->moveTo(event->lastScenePos());
mList.append(addPath(mStroker.createStroke(*mCurrentPath), QPen(Qt::red), QBrush(Qt::red)));
}
QGraphicsScene::mousePressEvent(event);
}
void ScribbleArea::mouseMoveEvent ( QGraphicsSceneMouseEvent* event)
{
if(!mErase)
{
mCurrentPath->lineTo(event->lastScenePos());
mList[mList.count()-1]->setPath(mStroker.createStroke(*mCurrentPath));
}
else
{
for(int i=0; i < mList.count(); i++)
{
if(mList[i]->isUnderMouse())
{
removeItem(mList[i]);
delete mList[i];
mList.removeAt(i);
}
}
}
QGraphicsScene::mouseMoveEvent(event);
}
这是两个关键函数,在 mousePressEvent 上我开始一个新路径并将其移动到当前鼠标位置,接下来,我将路径添加到 QGraphicsScene 以获得指向 QGraphicsPathItem 的指针,我将在 mouseMoveEvent 中使用它功能。
在 mouseMoveEvent 函数中,我首先检查我们当前是在擦除还是在绘图。在绘图的情况下,我从路径最后一点到当前鼠标位置添加一条线,然后再次将路径添加到 QGraphicsScene,否则它不会显示这些新线(也许有更好的方法,我愿意改进),这就是它的绘图。 如果我们要删除,我会查看所有路径的列表并检查当前是否有任何路径在鼠标下,如果是,请将其删除。
这目前只是一个草稿,更多的改进即将到来。
drawing/scribbling的一些很棒的例子: