Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在相对于QGraphicsView的静态位置绘制项目_C++_Qt_Qgraphicsview_Qgraphicsitem_Qgraphicsscene - Fatal编程技术网

C++ 在相对于QGraphicsView的静态位置绘制项目

C++ 在相对于QGraphicsView的静态位置绘制项目,c++,qt,qgraphicsview,qgraphicsitem,qgraphicsscene,C++,Qt,Qgraphicsview,Qgraphicsitem,Qgraphicsscene,我想画一个总是出现在我的QGraphicsView右上角的通知。但是,QGraphicsItems位置是在场景坐标中指定的,因此如果用户平移/缩放以查看场景的不同部分,此通知将移出屏幕 我已经发现,只要当前视图发生更改,我就可以通过移动和缩放通知来模拟这种行为。但这似乎非常无效,而且一点也不优雅 似乎QGraphicsView应该支持这种行为。文档中提到了一个听起来充满希望的标志ItemIsPanel,但没有提到视图中的静态位置ItemIgnorestTransformations也有助于缩放/

我想画一个总是出现在我的
QGraphicsView
右上角的通知。但是,
QGraphicsItems
位置是在场景坐标中指定的,因此如果用户平移/缩放以查看场景的不同部分,此通知将移出屏幕

我已经发现,只要当前视图发生更改,我就可以通过移动和缩放通知来模拟这种行为。但这似乎非常无效,而且一点也不优雅

似乎
QGraphicsView
应该支持这种行为。文档中提到了一个听起来充满希望的标志
ItemIsPanel
,但没有提到视图中的静态位置
ItemIgnorestTransformations
也有助于缩放/缩放,但不能平移


是否有任何内置的Qt功能支持此行为?

将通知作为原始场景的一部分的天真解决方案是不好的-它打破了模型-视图分离。您可以有多个视图,所有视图都显示一个场景,但通常只能在其中一个视图上显示所需的通知

另一个简单的方法是在视图顶部覆盖QWidget通知。问题是,在某些架构上,将常规QWidget覆盖在加速QGLWidget之上会使前者消失。请注意,QGraphicsView的视口可能是QGLWidget

因此,唯一的可移植解决方案是在QGraphicsSceneView的
viewport()
中,显式地在所有其他内容之上进行绘制

下面是一个完整的例子

// main.cpp
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>

qreal rnd() { return qrand() / (float)RAND_MAX; }

class OverlaidGraphicsView : public QGraphicsView
{
    Q_OBJECT
    QGraphicsScene * m_overlayScene;
public:
    explicit OverlaidGraphicsView(QWidget* parent = 0) :
        QGraphicsView(parent), m_overlayScene(NULL) {}
    explicit OverlaidGraphicsView(QGraphicsScene * scene = 0, QWidget * parent = 0) :
        QGraphicsView(scene, parent), m_overlayScene(NULL) {}
    void setOverlayScene(QGraphicsScene * scene) {
        if (scene == m_overlayScene) return;
        m_overlayScene = scene;
        connect(scene, SIGNAL(changed(QList<QRectF>)), SLOT(overlayChanged()));
        update();
    }
    QGraphicsScene * overlayScene() const { return m_overlayScene; }
    void paintEvent(QPaintEvent *ev) {
        QGraphicsView::paintEvent(ev);
        if (m_overlayScene) paintOverlay();
    }
    virtual void paintOverlay() {
        QPainter p(viewport());
        p.setRenderHints(renderHints());
        m_overlayScene->render(&p, viewport()->rect());
    }
    Q_SLOT void overlayChanged() { update(); }
};

class Window : public QWidget
{
    QGraphicsScene scene, notification;
    OverlaidGraphicsView * view;
    QGraphicsSimpleTextItem * item;
    int timerId;
    int time;
public:
    Window() :
        view(new OverlaidGraphicsView(&scene, this)),
        timerId(-1), time(0)
    {
        for (int i = 0; i < 20; ++ i) {
            qreal w = rnd()*0.3, h = rnd()*0.3;
            scene.addEllipse(rnd()*(1-w), rnd()*(1-h), w, h, QPen(Qt::red), QBrush(Qt::lightGray));
        }
        view->fitInView(0, 0, 1, 1);
        view->setResizeAnchor(QGraphicsView::AnchorViewCenter);
        view->setRenderHint(QPainter::Antialiasing);
        view->setOverlayScene(&notification);
        item = new QGraphicsSimpleTextItem();
        item->setPen(QPen(Qt::blue));
        item->setBrush(Qt::NoBrush);
        item->setPos(95, 0);
        notification.addItem(item);
        notification.addRect(0, 0, 100, 0, Qt::NoPen, Qt::NoBrush); // strut
        timerId = startTimer(1000);
        QTimerEvent ev(timerId);
        timerEvent(&ev);
    }
    void resizeEvent(QResizeEvent * ev) {
        view->resize(size());
        view->fitInView(0, 0, 1, 1, Qt::KeepAspectRatio);
        QWidget::resizeEvent(ev);
    }
    void timerEvent(QTimerEvent * ev) {
        if (ev->timerId() != timerId) return;
        item->setText(QString::number(time++));
    }
};

int main(int argc, char ** argv)
{
    QApplication a(argc, argv);

    Window window;
    window.show();
    a.exec();
}

#include "main.moc"

//main.cpp
#包括
#包括
#包括
#包括
qreal rnd(){return qrand()/(float)RAND_MAX;}
类OverlaidGraphicsView:公共QGraphicsView
{
Q_对象
第四纪-第四纪*m_上新统;
公众:
显式覆盖图形视图(QWidget*parent=0):
QGraphicsView(父),m_OverlyScene(NULL){}
显式OverlaidGraphicsView(QGraphicscene*场景=0,QWidget*父视图=0):
QGraphicsView(场景,父对象),m_覆盖场景(空){}
void setOverlayScene(QGraphicscene*场景){
if(scene==m_overlyscene)返回;
m_overlyscene=场景;
连接(场景、信号(已更改(QList))、插槽(OverlyChanged());
更新();
}
qgraphicscene*overlayScene()常量{return m_overlayScene;}
无效油漆事件(QPaintEvent*ev){
QGraphicsView::paintEvent(ev);
如果(m_overlayScene)paintOverlay();
}
虚拟void paintOverlay(){
QPainter p(viewport());
p、 setRenderInts(renderInts());
m_OverlyScene->渲染(&p,viewport()->rect());
}
Q_插槽void overlychanged(){update();}
};
类窗口:公共QWidget
{
QG现场,通知;
覆盖图形视图*视图;
QGraphicsSimpleTextItem*项;
int-timerId;
整数时间;
公众:
窗口():
视图(新的重叠图形视图(&场景,此)),
timerId(-1),时间(0)
{
对于(int i=0;i<20;++i){
qreal w=rnd()*0.3,h=rnd()*0.3;
addEllipse(rnd()*(1-w),rnd()*(1-h),w,h,QPen(Qt::red),QBrush(Qt::lightGray));
}
查看->fitInView(0,0,1,1);
view->setResizeAnchor(QGraphicsView::AnchorViewCenter);
视图->SetRenderInt(QPaint::抗锯齿);
查看->设置覆盖场景(&通知);
item=新的QGraphicsSimpleTextItem();
项目->设置笔(QPen(Qt::蓝色));
项目->退刀(Qt::NoBrush);
项目->设置位置(95,0);
通知.增补项(项目);
notification.addRect(0,0,100,0,Qt::NoPen,Qt::NoBrush);//struct
timerId=startTimer(1000);
QTimerEvent ev(timerId);
时间预警(ev);
}
void resizeEvent(QResizeEvent*ev){
查看->调整大小(大小());
视图->fitInView(0,0,1,1,Qt::keepasspectratio);
QWidget::resizeEvent(ev);
}
无效时间预览(QTimerEvent*ev){
如果(ev->timerId()!=timerId)返回;
item->setText(QString::number(time++));
}
};
int main(int argc,字符**argv)
{
质量保证申请a(argc、argv);
窗口窗口;
window.show();
a、 exec();
}
#包括“main.moc”

您是否尝试过在视口上工作,类似于graphicsView.mapToScene(graphicsView.view.viewport()->rect().topRight())的可能重复请参见注意:使用
drawForeground
会更简单*待办事项