#ifndef LISTGRAPHICSPIXMAPITEM_H
#define LISTGRAPHICSPIXMAPITEM_H
#include <QGraphicsObject>
//列表图形项
class listGraphicsPixmapItem : public QGraphicsObject
{
Q_OBJECT
public:
listGraphicsPixmapItem(QString uuid,QGraphicsItem *parent = nullptr);
void setTitle(QString title)
{
this->title = title;
}
void setContentList(const QStringList & list)
{
this->contentList = list;
}
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value)override;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)override;
virtual QRectF boundingRect()const override;
void mousePressEvent(QGraphicsSceneMouseEvent *event)override;
void hoverMoveEvent(QGraphicsSceneHoverEvent* event)override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* event)override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)override;
private:
bool IsInResizeArea(const QPointF& pos);
QSizeF itemSize;
bool isResizing; //是否正在改变大小的过程中
QString uuid;
QString title{"测试标题"};
QStringList contentList;
enum class pressBtnType //按下的是哪个按钮
{
previousPage = 0,
nextPage,
None
};
QRect pressedBtnRect[2];
pressBtnType pressThisBtnType{pressBtnType::None};
QVector<QRect> textListVector;
int pressedTextRectIndex{-1};
void onBtnPressed();
int paintShowContentIndex{0};//当前绘制的首个列表项是contentList的第几个
int nowPaintSize;//当前每页绘制的数目
int nowPage{0};//当前页数
int fullPages{0};//总页数
};
#endif // LISTGRAPHICSPIXMAPITEM_H
#include "listgraphicspixmapitem.h"
#include <QGraphicsScene>
#include <QDebug>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
const qreal g_cResizePos[] = {9, 6, 3};
listGraphicsPixmapItem::listGraphicsPixmapItem(QString uuid, QGraphicsItem *parent)
:QGraphicsObject(parent)
{
setAcceptHoverEvents(true);
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemSendsScenePositionChanges);//图形项可发送位置变化信号
setFlag(QGraphicsItem::ItemIsSelectable);
setFlag(QGraphicsItem::ItemIsFocusable);
this->uuid = uuid;
this->itemSize = QSizeF(160,200);
isResizing = false;
setZValue(1);
for (int i = 0;i < 100;++i)
{
contentList << QString("测试内容%1").arg(i);
}
paintShowContentIndex = 0;
}
QRectF listGraphicsPixmapItem::boundingRect() const
{
return QRectF(0, 0, itemSize.width() + 10, itemSize.height() + 10);
}
void listGraphicsPixmapItem::onBtnPressed()
{
if(pressThisBtnType == pressBtnType::previousPage)
{
--nowPage;
if(nowPage < 0)
nowPage = 0;
paintShowContentIndex = paintShowContentIndex - nowPaintSize;
}
else if(pressThisBtnType == pressBtnType::nextPage)
{
++nowPage;
if(nowPage > fullPages)
nowPage = fullPages;
paintShowContentIndex = paintShowContentIndex + nowPaintSize;
}
if(paintShowContentIndex > contentList.size() - 1)
paintShowContentIndex = contentList.size() - 1;
if(nowPage == 0)
paintShowContentIndex = 0;
qDebug()<<"当前页:"<<nowPage<<"当前绘制个数:"<<nowPaintSize<<"首个index"<<paintShowContentIndex;
update();
}
void listGraphicsPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
if(IsInResizeArea(event->pos()))
isResizing = true;
QGraphicsObject::mousePressEvent(event);
QPoint position = event->pos().toPoint();
for (int i = 0;i < 2;++i)
{
if(pressedBtnRect[i].contains(position))
{
pressThisBtnType = static_cast<pressBtnType>(i);
onBtnPressed();
update();
return;
}
}
for (int i = 0;i < textListVector.size();++i)
{
if(textListVector[i].contains(position))
{
pressedTextRectIndex = i;
update();
return;
}
}
return;
}
else if(event->button() == Qt::RightButton)
{
return;
}
return QGraphicsObject::mousePressEvent(event);
}
void listGraphicsPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if(pressThisBtnType != pressBtnType::None)
{
pressThisBtnType = pressBtnType::None;
update();
}
if(pressedTextRectIndex != -1)
{
pressedTextRectIndex = -1;
update();
}
if (event->button() == Qt::LeftButton && isResizing)
isResizing = false;
else
QGraphicsObject::mouseReleaseEvent(event);
}
QVariant listGraphicsPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if ((change == ItemPositionChange || change == ItemPositionHasChanged) && scene()) // 控件发生移动
{
QPointF newPos = value.toPointF();
QRectF rect(0, 0, scene()->width(), scene()->height());
if (!rect.contains(newPos))//左上角
{
newPos.setX(qMin(rect.width(), qMax(newPos.x(), 0.0)));
newPos.setY(qMin(rect.height(), qMax(newPos.y(), 0.0)));
// newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
// newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
return newPos;
}
QRectF thisRectF = boundingRect();
QPointF nowPos = QPointF(newPos.x() + thisRectF.width(),newPos.y());
if(!rect.contains(nowPos))//右上角
{
newPos.setX(rect.width() - thisRectF.width());
this->setPos(newPos);
return newPos;
}
nowPos = QPointF(newPos.x(),newPos.y() + thisRectF.height());
if(!rect.contains(nowPos))//左下角
{
newPos.setY(rect.height() - thisRectF.height());
this->setPos(newPos);
return newPos;
}
}
return QGraphicsItem::itemChange(change, value);
}
void listGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
painter->save();
painter->setRenderHint(QPainter::Antialiasing,true);
painter->setRenderHint(QPainter::SmoothPixmapTransform,true);
painter->setRenderHint(QPainter::TextAntialiasing,true);
QRectF thisRectF = boundingRect();
if(option->state & QStyle::State_Selected)
{
painter->setPen(QColor("#D8D8D8"));
painter->drawRect(thisRectF);
setZValue(2);
}
else
{
setZValue(1);
painter->fillRect(thisRectF, QBrush(Qt::transparent));
}
QRect rect = thisRectF.toRect();
int titleHeight = rect.height()*0.15;
QRect titleRect = QRect(0,0,rect.width(),titleHeight);
painter->save();
painter->drawRoundRect(thisRectF.adjusted(5,5,-5,-5));
painter->restore();
painter->save();
if(!title.isEmpty())
{
painter->setPen(QColor("#333333"));
QFont font = painter->font();
font.setPixelSize(24);
painter->setFont(font);
painter->drawText(titleRect, Qt::AlignCenter, title);//在此区域的中间位置绘制文字
}
painter->restore();
painter->save();
QPen p;
p.setWidth(2);
p.setColor(QColor("#555555"));
painter->setPen(p);
painter->drawLine(QPoint(15,titleRect.bottomLeft().y()),
QPoint(titleRect.width() - 15,titleRect.bottomLeft().y()));
painter->restore();
painter->save();
p.setWidth(1);
p.setColor(QColor("#888888"));
QFont font = painter->font();
font.setPixelSize(20);
painter->setFont(font);
painter->setPen(p);
int textListHeight = rect.height() * 0.65;//绘制区域的高度
nowPaintSize = textListHeight / 40/* - 1*/; //每一项高40 当前绘制的个数
fullPages = contentList.size() / nowPaintSize;// 总页数
// if(contentList.size() % nowPaintSize != 0)//不能整除有余数
// {
// ++fullPages;
// }
QRect pressedTextRect;
if(pressedTextRectIndex != -1)
{
pressedTextRect = textListVector[pressedTextRectIndex];
}
textListVector.clear();
if(paintShowContentIndex <= contentList.size())
{
for (int i = paintShowContentIndex,j = 0;j < nowPaintSize && i < contentList.size();++i,++j)
{
QRect listRect = QRect(0,titleHeight + j * 40,rect.width(),40);
painter->drawText(listRect, Qt::AlignCenter, contentList[i]);//在此区域的中间位置绘制文字
painter->drawLine(QPoint(15,listRect.bottomLeft().y()),QPoint(listRect.width() - 15,listRect.bottomLeft().y()));
textListVector << listRect;
}
}
painter->restore();
//拖动的时候nowPage 也要变化
//前面的个数paintShowContentIndex,每页nowPaintSize个,
nowPage = paintShowContentIndex / nowPaintSize;
if(paintShowContentIndex % nowPaintSize != 0)
{
++nowPage;
}
painter->save();
QRect btnRect = QRect(0,rect.height() * 0.80,rect.width(),rect.height() * 0.2);
int btnWidth = btnRect.width() * 0.15;
int btnHeight = btnRect.height() * 0.5;
int btnY = (btnRect.height() - btnHeight) / 2 + rect.height() * 0.80;
pressedBtnRect[0] = QRect(btnRect.width() * 0.08 * 2 + btnWidth,btnY,btnWidth,btnHeight);
pressedBtnRect[1] = QRect(btnRect.width() * 0.08 * 3 + btnWidth * 2,btnY,btnWidth,btnHeight);
painter->setPen(QColor("#888888"));
painter->drawRoundRect(pressedBtnRect[0],30,30);
painter->drawRoundRect(pressedBtnRect[1],30,30);
painter->setPen(QColor("#555555"));
painter->drawText(pressedBtnRect[0],Qt::AlignCenter,QStringLiteral("<<"));
painter->drawText(pressedBtnRect[1],Qt::AlignCenter,QStringLiteral(">>"));
painter->restore();
if(pressThisBtnType != pressBtnType::None)
{
painter->save();
QColor slightlyOpaqueBlack(0, 0, 0, 63);
painter->setBrush(slightlyOpaqueBlack);
painter->setPen(Qt::transparent);
painter->drawRoundRect(pressedBtnRect[static_cast<int>(pressThisBtnType)],30,30);
painter->restore();
}
if(pressedTextRectIndex != -1)
{
painter->save();
QColor slightlyOpaqueBlack(0, 0, 0, 63);
painter->setBrush(slightlyOpaqueBlack);
painter->setPen(Qt::transparent);
painter->drawRect(pressedTextRect.adjusted(15,0,-15,0));
painter->restore();
}
if(option->state & QStyle::State_Selected)
{
qreal w = thisRectF.width();
qreal h = thisRectF.height();
painter->setPen(Qt::red);
for (int i = 0; i < 3; ++i)//三角形
painter->drawLine(static_cast<int>(w - g_cResizePos[i]) , static_cast<int>(h), static_cast<int>(w), static_cast<int>(h - g_cResizePos[i]));
}
painter->restore();
}
void listGraphicsPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
{
if (isResizing || (IsInResizeArea(event->pos()) && isSelected()))
setCursor(Qt::SizeFDiagCursor);
else
setCursor(Qt::ArrowCursor);
QGraphicsObject::hoverMoveEvent(event);
}
void listGraphicsPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (isResizing)
{
qreal w = event->pos().x();
qreal h = event->pos().y();
if (w > 150)
itemSize.setWidth(w);
if (h > 150)
itemSize.setHeight(h);
prepareGeometryChange();
}
else
{
QGraphicsObject::mouseMoveEvent(event);
}
}
bool listGraphicsPixmapItem::IsInResizeArea(const QPointF& pos)
{
return (pos.x() - itemSize.width() + g_cResizePos[0]) > (itemSize.height() - pos.y());
}
效果: