code_app/app/scanner/graphicsscene.cpp

299 lines
8.6 KiB
C++
Raw Normal View History

2022-05-03 10:25:52 +00:00
#include "graphicsscene.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
#include <QGraphicsProxyWidget>
#include <QScrollBar>
#include <QPen>
#include <QBrush>
#include <QGraphicsView>
#include <QDebug>
#include <qmath.h>
GraphicsTextEdit::GraphicsTextEdit(QWidget* parent)
: QTextEdit(parent)
{
viewport()->setWindowFlag(Qt::FramelessWindowHint);
viewport()->setAttribute(Qt::WA_TranslucentBackground);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
connect(this, SIGNAL(textChanged()), this, SLOT(on_textChanged()));
}
GraphicsTextEdit::~GraphicsTextEdit()
{
}
#define BORDER_WIDTH 20
void GraphicsTextEdit::on_textChanged()
{
QFontMetrics fm(font());
QSize currentSize = this->size();
QStringList lineText = document()->toPlainText().split("\n", QString::SkipEmptyParts);
int idealWidth = 0;
for (const QString& str : lineText)
{
int width = fm.width(str);
if (width > idealWidth)
idealWidth = width;
}
int idelHeight = document()->lineCount() * fm.lineSpacing();
if (width() < idealWidth + BORDER_WIDTH)
currentSize.setWidth(idealWidth + BORDER_WIDTH);
if (height() < idelHeight + BORDER_WIDTH * 2)
currentSize.setHeight(idelHeight + BORDER_WIDTH * 2);
if (currentSize != this->size())
resize(currentSize);
}
GraphicsScene::GraphicsScene(QObject* parent)
: QGraphicsScene(parent)
, m_status(Normal)
, m_activeItem(nullptr)
, m_btn_pressed(0)
, m_pen(QColor(255, 0, 0, 255))
, m_brush(QColor(255, 255, 255, 255))
, m_font(tr("SongTi"))
{
}
GraphicsScene::~GraphicsScene()
{
}
void GraphicsScene::setColor(const QColor& color)
{
m_pen.setColor(color);
m_brush.setColor(color);
}
void GraphicsScene::setTextSize(int size)
{
m_font.setPointSize(size);
}
void GraphicsScene::setLineWidth(int width)
{
m_pen.setWidth(width);
}
void GraphicsScene::createShape(int flag)
{
if (m_activeItem != nullptr)
{
if (typeid(*m_activeItem) == typeid(QGraphicsProxyWidget))
removeItem(m_activeItem);
m_activeItem = nullptr;
m_status = Normal;
}
switch (flag)
{
case Rect:
m_status = CreateRect;
break;
case Ellipse:
m_status = CreateEllipse;
break;
case Line:
m_status = CreateLine;
break;
case Text:
m_status = CreateText;
break;
case Arrow:
m_status = CreateArrow;
break;
case Pen:
m_status = CreatePen;
break;
default:
break;
}
}
void GraphicsScene::unDo()
{
QList<QGraphicsItem*> items = this->items();
if (items.count() < 2)
return;
removeItem(items.first());
}
#define PI acos(-1)
QPointF rotate(const QPointF& center, const QPointF& p, float angle)
{
float angle_ = angle;
float x = (p.x() - center.x()) * cos(angle_) - (p.y() - center.y()) * sin(angle_) + center.x();
float y = (p.y() - center.y()) * cos(angle_) + (p.x() - center.x()) * sin(angle_) + center.y();
return QPointF(x, y);
}
float lineLength(const QPointF& p1, const QPointF& p2)
{
return sqrt(pow(p1.x() - p2.x(), 2) + pow(p1.y() - p2.y(), 2));
}
QPainterPath GraphicsScene::createArrowPath(const QPointF& p1, const QPointF& p2)
{
float angle;
if (p2.x() == p1.x())
if (p2.y() > p1.y())
angle = PI / 2;
else
angle = -PI / 2;
else
if (p2.x() < p1.x() && std::abs(p1.y() - p2.y()) < 0.000001)
angle = PI;
else
{
angle = atan((p2.y() - p1.y()) / (p2.x() - p1.x()));
if (p2.y() < p1.y() && p2.x() < p1.x())
angle -= PI;
if (p2.y() > p1.y() && p2.x() < p1.x())
angle += PI;
}
float length = lineLength(p1, p2);
QPointF p_1 = rotate(p1, QPointF(p1.x() + length - 25, p1.y() + 15), angle);
QPointF p_2 = rotate(p1, QPointF(p1.x() + length - 25, p1.y() - 15), angle);
QPointF p_1_half = rotate(p1, QPointF(p1.x() + length - 22, p1.y() + 10), angle);
QPointF p_2_half = rotate(p1, QPointF(p1.x() + length - 22, p1.y() - 10), angle);
QPainterPath path;
path.moveTo(p2);
path.lineTo(p_2);
path.lineTo(p_2_half);
path.lineTo(p1);
path.lineTo(p_1_half);
path.lineTo(p_1);
path.lineTo(p2);
return path;
}
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (m_activeItem == nullptr)
return;
if (m_status == CreateRect)
{
QGraphicsRectItem* item = reinterpret_cast<QGraphicsRectItem*>(m_activeItem);
QPointF pos = mouseEvent->scenePos();
float left = qMin(pos.x(), m_startPoint.x());
float top = qMin(pos.y(), m_startPoint.y());
float right = qMax(pos.x(), m_startPoint.x());
float bottom = qMax(pos.y(), m_startPoint.y());
item->setRect(QRectF(QPointF(left, top), QPointF(right, bottom)));
}
else if (m_status == CreateEllipse)
{
QGraphicsEllipseItem* item = reinterpret_cast<QGraphicsEllipseItem*>(m_activeItem);
QPointF pos = mouseEvent->scenePos();
float left = qMin(pos.x(), m_startPoint.x());
float top = qMin(pos.y(), m_startPoint.y());
float right = qMax(pos.x(), m_startPoint.x());
float bottom = qMax(pos.y(), m_startPoint.y());
item->setRect(QRectF(QPointF(left, top), QPointF(right, bottom)));
}
else if (m_status == CreateLine)
{
QGraphicsLineItem* item = reinterpret_cast<QGraphicsLineItem*>(m_activeItem);
item->setLine(QLineF(m_startPoint, mouseEvent->scenePos()));
}
else if (m_status == CreateArrow)
{
QGraphicsPathItem* item = reinterpret_cast<QGraphicsPathItem*>(m_activeItem);
item->setPath(createArrowPath(m_startPoint, mouseEvent->scenePos()));
}
else if (m_status == CreatePen)
{
QGraphicsPathItem* item = reinterpret_cast<QGraphicsPathItem*>(m_activeItem);
QPainterPath path = item->path();
path.lineTo(mouseEvent->scenePos());
item->setPath(path);
}
}
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() == Qt::MouseButton::LeftButton)
m_btn_pressed = 1;
else if (mouseEvent->button() == Qt::MouseButton::RightButton)
m_btn_pressed = 2;
if (m_status == CreateRect)
{
m_activeItem = addRect(QRectF(mouseEvent->scenePos(), QSize(1, 1)), QPen(m_brush.color()), m_brush);
m_startPoint = mouseEvent->scenePos();
}
else if (m_status == CreateEllipse)
{
m_activeItem = addEllipse(QRectF(mouseEvent->scenePos(), QSize(1, 1)), m_pen, QBrush());
m_startPoint = mouseEvent->scenePos();
}
else if (m_status == CreateLine)
{
m_activeItem = addLine(QLineF(mouseEvent->scenePos(), mouseEvent->scenePos()), m_pen);
m_startPoint = mouseEvent->scenePos();
}
else if (m_status == CreateArrow)
{
m_startPoint = mouseEvent->scenePos();
m_activeItem = addPath(createArrowPath(m_startPoint, mouseEvent->scenePos()), m_pen, QBrush(m_pen.color()));
}
else if (m_status == CreatePen)
{
m_startPoint = mouseEvent->scenePos();
QPainterPath path(m_startPoint);
path.lineTo(m_startPoint + QPointF(1, 1));
m_activeItem = addPath(path, m_pen, QBrush());
}
}
void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
m_btn_pressed = 0;
if (m_activeItem != nullptr)
{
if (typeid(*m_activeItem) == typeid(QGraphicsProxyWidget))
{
QRectF r(m_edit->mapToParent(QPoint()), m_edit->size());
if (!r.contains(mouseEvent->scenePos()))
{
QString text = m_edit->document()->toPlainText();
QFont font = m_edit->font();
removeItem(m_activeItem);
QGraphicsTextItem* item = addText(text, font);
item->setPos(m_edit->mapToParent(QPoint()));
item->setDefaultTextColor(m_pen.color());
}
}
m_activeItem = nullptr;
}
if (m_status == CreateText)
{
if (m_activeItem != nullptr)
if (typeid(*m_activeItem) == typeid(QGraphicsProxyWidget))
return;
m_edit = new GraphicsTextEdit();
m_edit->setTextColor(m_pen.color());
m_edit->setFont(m_font);
m_edit->setContextMenuPolicy(Qt::ContextMenuPolicy::NoContextMenu);
m_activeItem = addWidget(m_edit, Qt::Widget);
m_activeItem->setPos(mouseEvent->scenePos());
m_edit->setFocus();
}
}