我需要强制在视图内重新绘制QGraphicsScene
- 整个视图
我在下面解释为什么我不能重新绘制具体项目,以及我尝试过的内容。
我有一个QGraphicsScene
子类,用于绘制项目的“实际画布矩形” - 但是项目可以放在这个矩形之外,或者更大。
“实际画布矩形”可以调整大小,我也会在调整大小时调整它,因此(0,0)
始终是(0,0)
中QGraphicsScene
坐标的点。
我使调整大小足够重新绘制旧画布和新画布之间的最大矩形
我没有考虑在整个QGraphicsScene
或画布外的任何项目上进行重绘,因为它是巨大的 - 并且项目可能遍布整个地方 - 并且因为初始应用程序也在视图中重新定位画布
此类是从QWidget
旁边创建的QScrollArea
引用的,该QGraphicsView
已提升为包含该场景的 QList<QGraphicsView*> views = m_canvas->views();
if(views.size() > 0)
{
m_canvas->update(views.at(0)->rect());
// or
QWidget* viewport = views.at(0)->viewport();
viewport->update();
// or
QRectF r = views.at(0)->mapToScene(views.at(0)->rect()).boundingRect();
m_canvas->update(r);
}
子类。
如果我在场景上放置一个大文本项目,并且我调整画布大小,我可以在左侧或右侧留下剩余的文本(取决于项目是否大于旧画布或新画布)。由于“移动”,通常增加画布大小会在左侧留下一个神器。
在画布上进行移动或缩放会进行重新绘制 - 但即使在场景中也不会显示。
我需要在重新调整后强制重新显示旧项,然后从技术上移动它。
我对视口更新感到满意,但我无法理解:尝试了几次:
#ifndef MYVIEW_H
#define MYVIEW_H
#include <QGraphicsView>
#include <QGraphicsScene>
class MyView : public QGraphicsView
{
public:
MyView(QWidget *parent = 0) : QGraphicsView(parent) {
setRenderHints(QPainter::Antialiasing |
QPainter::SmoothPixmapTransform);
setCacheMode(CacheNone); // to avoid smear when panning very far
setAutoFillBackground(true);
setBackgroundRole(QPalette::Window);
setViewportUpdateMode(SmartViewportUpdate);
setTransformationAnchor(AnchorUnderMouse);
setDragMode(ScrollHandDrag);
}
};
class MyScene : public QGraphicsScene
{
public:
explicit MyScene(const qreal sceneW, const qreal sceneH,
const qreal canvasW, const qreal canvasH,
QObject *parent = 0) : QGraphicsScene(parent) {
m_actualCanvasRect = QRectF(0, 0, canvasW, canvasH);
setSceneRect(0.5*(canvasW - sceneW), 0.5*(canvasH - sceneH), sceneW, sceneH);
}
void setCanvasSize(const qreal canvasW, const qreal canvasH) {
setSceneRect(0.5*(canvasW - sceneRect().width()),
0.5*(canvasH - sceneRect().height()),
sceneRect().width(), sceneRect().height());
qreal oldW = m_actualCanvasRect.width(),
oldH = m_actualCanvasRect.height();
m_actualCanvasRect = QRectF(0, 0, canvasW, canvasH);
qreal updateW = qMax(oldW, canvasW);
qreal updateH = qMax(oldH, canvasH);
QRectF updateRect(0, 0, updateW, updateH);
update(updateRect);
}
protected:
virtual void drawBackground(QPainter *painter, const QRectF &rect) {
QGraphicsScene::drawBackground(painter, rect);
QPen p(Qt::green);
p.setWidth(5); // this creates artifacts but lucky in my code i don't use a width
painter->setPen(p);
painter->setBrush(Qt::red);
painter->drawRect(m_actualCanvasRect);
}
private:
QRectF m_actualCanvasRect;
};
#endif // MYVIEW_H
这些都不起作用。
由于坐标已经改变,我甚至不知道如何将项目的旧边界矩形映射到场景的新坐标。
这就是为什么我的想法,更新视图更简单
但是我必须做错事,因为剩下的画仍然存在。
我真正想要的是强制在整个视口上重绘场景 我怎么能这样做?
编辑 - 添加一个可以重现问题的程序。
myview.h
#ifndef TESTSCENE_H
#define TESTSCENE_H
#include <QWidget>
#include "myview.h"
namespace Ui {
class TestScene;
class MyScene;
class QGraphicsTextItem;
}
class TestScene : public QWidget
{
Q_OBJECT
public:
explicit TestScene(QWidget *parent = 0);
~TestScene();
private slots:
void on_btnResize_clicked();
private:
Ui::TestScene *ui;
MyScene* s;
QGraphicsTextItem* yyy;
};
#endif // TESTSCENE_H
testscene.h
#include "testscene.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TestScene w;
w.show();
return a.exec();
}
的main.cpp
#include "testscene.h"
#include "ui_testscene.h"
#include <QGraphicsTextItem>
TestScene::TestScene(QWidget *parent) :
QWidget(parent),
ui(new Ui::TestScene)
{
ui->setupUi(this);
qreal w = 300, h = 200;
s = new MyScene(1000000, 1000000, w, h);
ui->myView->setScene(s);
yyy = new QGraphicsTextItem("Hello Great World");
QFont fff("Arial", 34);
yyy->setFont(fff);
QSizeF sz = yyy->boundingRect().size();
qreal cx = (w - sz.width())/2;
qreal cy = (h - sz.height())/2;
yyy->setPos(cx, cy);
s->addItem(yyy);
}
TestScene::~TestScene()
{
delete ui;
}
void TestScene::on_btnResize_clicked()
{
bool ok;
qreal w = ui->linWidth->text().toDouble(&ok);
if(!ok || w <= 0) return;
qreal h = ui->linHeight->text().toDouble(&ok);
if(!ok || h <= 0) return;
s->setCanvasSize(w, h);
QSizeF sz = yyy->boundingRect().size();
qreal cx = (w - sz.width())/2;
qreal cy = (h - sz.height())/2;
yyy->setPos(cx, cy);
}
testscene.cpp
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TestScene</class>
<widget class="QWidget" name="TestScene">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>649</width>
<height>307</height>
</rect>
</property>
<property name="windowTitle">
<string>TestScene</string>
</property>
<widget class="QScrollArea" name="scrlArea">
<property name="geometry">
<rect>
<x>60</x>
<y>40</y>
<width>471</width>
<height>231</height>
</rect>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>469</width>
<height>229</height>
</rect>
</property>
<widget class="MyView" name="myView">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>451</width>
<height>211</height>
</rect>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
</widget>
</widget>
</widget>
<widget class="QPushButton" name="btnResize">
<property name="geometry">
<rect>
<x>550</x>
<y>50</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Resize</string>
</property>
</widget>
<widget class="QLineEdit" name="linWidth">
<property name="geometry">
<rect>
<x>540</x>
<y>90</y>
<width>113</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="linHeight">
<property name="geometry">
<rect>
<x>540</x>
<y>130</y>
<width>113</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>MyView</class>
<extends>QGraphicsView</extends>
<header location="global">myview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
testscene.ui
setPos
要测试 - 启动后,设置大小40,30并查看工件。移动程序后设置更大的尺寸,工件将再次显示。
我已经意识到我可以在重新定位项目之后进行调整大小 - 并且由于某些奇怪的原因而处理工件(即使调整大小中调用的更新不包括整个项目边界矩形)。这与其他一些操作有冲突,但我可以让它发挥作用。
所以 - 我不再急于寻求解决方案,只是理解。为什么/如何在当前情况下强制重绘 - 在调整大小后使用项CREATE p1=(m:Movie {title:'M'})<-[:ACTED_IN {role:'R1'}]-(:Actor {name:'A1'}),
p2 = (m)<-[:ACTED_IN {role:'R2'}]-(:Actor {name:'A2'}) WITH [p1,p2] as paths
CALL apoc.convert.toTree(paths) YIELD value RETURN value
->
{_id=0, _type=Movie, title=M,
acted_in=[
{_id=1, _type=Actor, name=A1, acted_in.role=R1},
{_id=2, _type=Actor, name=A2, acted_in.role=R2}]}
。