橘猫掸子 2021-05-08 16:35 采纳率: 25%
浏览 181

QGraphicsView中QGraphicsItem显示残缺不完整

问题前提描述:

自定义了BlockItem类(继承至QGraphicsItem);
自定义了BlockWindowScene(继承至QGraphicsScene);
自定义了BlockWindow(继承至QMainWindow);
问题描述:
当把BlockItem放进BlockWindowScene后,必须要调用”ui->graphicsView->viewport()->update()“刷新一下,BlockItem的paint才会被调用,才会显示正常矩形。但是将view的滚动条滚动,把BlockItem滚动到view以外再滚动回来,此时BlockItem又显示不完整了,如下图所示。必须在调用一次”ui->graphicsView->viewport()->update()“刷新一下view才行。
 

BlockItem.h

#pragma once

#include <QGraphicsItem>
#include <qdebug.h>
#include "publicheader.h"
#include <qpainter.h>
#include <QRectF>
#include <QSizeF>
#include <qpoint.h>
class BlockItem :public QObject, public QGraphicsItem
{
	Q_OBJECT
public:
	explicit BlockItem(QGraphicsItem *parent = nullptr);
	BlockItem(QString itemType);
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
	~BlockItem();

	//将item页面中配置的内容存放到item的map容器中
	void setKeyValue_Map(QString key,QString value);
	void setKeyValue_Map(QMap<QString, QString> map);

	//设置四边形的坐标
	void setPos(QPointF curPos);
	//测试keyValue_Map
	void initKeyValue_Map();
protected:
	//鼠标按压事件
	void mousePressEvent(QGraphicsSceneMouseEvent* event);
	//鼠标双击事件
	void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event);
private:
	//存Item的类别
	QString itemType;
	//存放配置的key和value
	QMap<QString, QString> keyValue_Map;
	//存来自Scene中的鼠标坐标
	QPointF pos; 

};

BlockItem.cpp
 

#include "blockitem.h"
#include <qmimedata.h>

BlockItem::BlockItem(QGraphicsItem *parent)
	: QGraphicsItem(parent)
{
	setFlag(QGraphicsItem::ItemIsFocusable);
	setFlag(QGraphicsItem::ItemIsMovable);
	setFlag(QGraphicsItem::ItemIsSelectable);
}

BlockItem::BlockItem(QString itemType)
{
	setFlag(QGraphicsItem::ItemIsFocusable);
	setFlag(QGraphicsItem::ItemIsMovable);
	setFlag(QGraphicsItem::ItemIsSelectable);
	//接收看item是什么类型
	this->itemType = itemType;
}

//item在Scene中的边界大小
QRectF BlockItem::boundingRect() const
{
	qreal adjust = 1;
	return QRectF(0 - adjust, 0 - adjust, 150 + adjust, 80 + adjust);
}


//将item页面中配置的内容存放到item的map容器中
void BlockItem::setKeyValue_Map(QString key, QString value)
{
	this->keyValue_Map.insert(key, value);
}


//将item页面中配置的内容存放到item的map容器中
void BlockItem::setKeyValue_Map(QMap<QString, QString> map)
{
	this->keyValue_Map.clear();
	this->keyValue_Map = QMap<QString, QString>(map);
}

//被QGraphicsView调用
void BlockItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //画个矩形
	painter->drawRect(this->pos.x(),this->pos.y(),110,70);

}


//Item鼠标按压事件
void BlockItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    //鼠标按压时设置其为焦点图元
	setFocus();
}
//鼠标双击事件
void BlockItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
{
	
}

//设置四边形的坐标
void BlockItem::setPos(QPointF curPos)
{
	this->pos = curPos;
	
}

BlockItem::~BlockItem()
{
	keyValue_Map.clear();
}

//测试KeyValue_Map
void BlockItem::initKeyValue_Map()
{
	setKeyValue_Map("Kp", "1");
	setKeyValue_Map("Ki", "20");
	setKeyValue_Map("Kd", "0.01");
}

BlockWindowScene.h
 

#pragma once

#include <QGraphicsScene>
#include <qgraphicsitem.h>
#include <qmap.h>
#include <qlist.h>
#include <qdebug.h>
#include "publicheader.h"
#include "itemtypeenum.h"
#include "blockitem.h"
#include <QGraphicsSceneMouseEvent>
class BlockWindowScene :public QGraphicsScene
{
	Q_OBJECT
public:
	explicit BlockWindowScene(QObject *parent = nullptr);
	~BlockWindowScene();

	static BlockWindowScene* getIntance();
	
	//将item绘画在Scene中
	void itemPaint(QString itemType,QPointF pos);
private slots:
	void slot_ReceiveData(QString data);
protected:
	//鼠标进入场景
	void dragEnterEvent(QGraphicsSceneDragDropEvent *event);

	//鼠标释放
	void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
	//单例
	static BlockWindowScene* blockWindowScene;
	//存放每个图元(QGraphicsItem)的对应的输入框
	QMap<QGraphicsItem*, QGraphicsTextItem*> itemToText_Map;
	//存放图元(QGraphicsItem)的指针
	QList<QGraphicsItem*> item_List;
	//当前BlockItem的类别名称
	QString currentItemName;

	
};

BlockWindowScene.cpp
 

#include "blockwindowscene.h"
#include <QMetaEnum> 
BlockWindowScene::BlockWindowScene(QObject *parent)
	: QGraphicsScene(parent)
{

	
}


BlockWindowScene::~BlockWindowScene()
{	
	//delete掉blockWindowScene所有的Item
	blockWindowScene->clear();
	blockWindowScene = nullptr;
}
//鼠标进入场景
void BlockWindowScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
	QGraphicsScene::dragEnterEvent(event);
	qDebug() << "dragEnterEvent鼠标进去了";
}

//鼠标释放
void BlockWindowScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
	if (mouseEvent->button() == Qt::RightButton)
	{
	//运行父类的鼠标按压事件
	QGraphicsScene::mousePressEvent(mouseEvent);
	qDebug() << "mouseReleaseEvent鼠标释放了";
	//记录场景中鼠标的坐标位置
	QPointF pos = mouseEvent->scenePos();
	itemPaint(this->currentItemName, pos);
	}
}

//使用信号和槽机制获取信息值
void BlockWindowScene::slot_ReceiveData(QString data)
{
	//正则表达式,为了去掉data非字母和数字的字符
	QRegExp ex("[^a-zA-Z0-9]");
	currentItemName = data.replace(ex, "");
}
//获取单例
BlockWindowScene* BlockWindowScene::blockWindowScene = nullptr;
BlockWindowScene* BlockWindowScene::getIntance()
{
	if (blockWindowScene == nullptr)
	{
		blockWindowScene = new BlockWindowScene();
	}
	return blockWindowScene;
}
//将item绘画在Scene中
void BlockWindowScene::itemPaint(QString itemType,QPointF pos)
{
	if (itemType == "BusSelector")
	{
		
	} 
	else if (itemType == "Subsystem")
	{
	
	}
	else if (itemType == "DataTypeConversion")
	{

	}
	else if (itemType == "Derivative")
	{
		
		BlockItem* blockItem = new BlockItem;
		QGraphicsSimpleTextItem* textItem = new QGraphicsSimpleTextItem;
		textItem->setText("Derivative");  // 纯文本
		QFont font = textItem->font();
		font.setPixelSize(20);  // 像素大小
		//font.setItalic(true);  // 斜体
		//font.setUnderline(true);  // 下划线
		textItem->setFont(font);	//
		textItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
		//设置此item在场景中的位置,pos为鼠标的位置
		blockItem->setPos(pos);
		//根据blockItem位置将textitem放置在其下方
		int textItem_X = (pos.x() + 0.5*(blockItem->boundingRect().width())) - (0.5*(textItem->boundingRect().width()));
		textItem_X = (textItem_X < 0 ? 0 : textItem_X);
		textItem->setPos(textItem_X, blockItem->boundingRect().height() + pos.y());
		//设置此Item可以被鼠标点击选中,选中后周围会有矩形的虚线
		blockItem->setFlag(QGraphicsItem::ItemIsSelectable);
		//设置此item是活动的
		blockItem->setEnabled(true);
		//使得pixmapItem只接受左键按钮事件
		blockItem->setAcceptedMouseButtons(Qt::LeftButton);
		blockItem->setEnabled(true);
		blockItem->setVisible(true);

		this->addItem(blockItem);
		this->addItem(textItem);
		qDebug() << "pos:" << pos;
	}
	else if (itemType == "DescriptorStateSpace")
	{

	}
	else if (itemType == "EntityTransportDelay")
	{

	}
	else if (itemType == "CallbackButton")
	{

	}
	else if (itemType == "CheckBox")
	{

	}
	else if (itemType == "CircularGauge")
	{

	}
}

BlockWindow.h
 

#pragma once

#include <QMainWindow>
#include <blockwindowscene.h>
#include <QWheelEvent>
namespace Ui { class BlockWindow; };
class BlockWindow : public QMainWindow
{
	Q_OBJECT
public:
	explicit BlockWindow(QWidget *parent = nullptr);
	//获取单例的公有函数
	static BlockWindow* getIntance();
	~BlockWindow();

	BlockWindowScene* blockWindowScene;
protected:
	void enterEvent(QEvent* event);
private:
	Ui::BlockWindow *ui;
	//静态成员,存放单例
	static BlockWindow* blockWindow;
};

BlockWindow.cpp
 

#include "blockwindow.h"
#include "ui_blockwindow.h"
#include "publicheader.h"
#include <qdebug.h>

BlockWindow::BlockWindow(QWidget *parent)
	: QMainWindow(parent)
{
	ui = new Ui::BlockWindow();
	ui->setupUi(this);
	blockWindowScene = BlockWindowScene::getIntance();
	blockWindowScene->setSceneRect(0, 0, 6000, 1200);
	ui->graphicsView->setScene(blockWindowScene);
	//初始化时,让view显示scene(0,0)处
	ui->graphicsView->centerOn(0, 0);
	//graphicsView开启鼠标跟踪:鼠标没有按下也会接收鼠标移动事件
	ui->graphicsView->setMouseTracking(true);
}

//获取单例
BlockWindow* BlockWindow::blockWindow = nullptr;
BlockWindow* BlockWindow::getIntance()
{
	if (blockWindow == nullptr)
	{
		blockWindow = new BlockWindow();
	}
	return blockWindow;
}

//鼠标进入事件
void BlockWindow::enterEvent(QEvent* event)
{
	qDebug() << "lockWindow::enterEvent-鼠标进来了";
	//更新view
	ui->graphicsView->viewport()->update();
}



BlockWindow::~BlockWindow()
{
	delete blockWindowScene;
	delete ui;

	blockWindowScene = nullptr;
	ui = nullptr;
}
  • 写回答

1条回答 默认 最新

  • 源代码大师 博客专家认证 2021-05-08 17:46
    关注

      希望对你有帮助:https://blog.csdn.net/it_xiangqiang/category_10794527.html

    评论

报告相同问题?

悬赏问题

  • ¥15 curl 命令调用正常,程序调用报 java.net.ConnectException: connection refused
  • ¥20 关于web前端如何播放二次加密m3u8视频的问题
  • ¥20 spring boot集成mqtt的使用问题
  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络
  • ¥66 关于川崎机器人调速问题
  • ¥15 winFrom界面无法打开
  • ¥30 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入
  • ¥15 mmo能不能做客户端怪物