Add QWidgets movable to QGraphicsView



  • Hi,
    I want to place QGraphicsItems in my QGraphicsScene with some little widgets like a spin box or a color dialog (like this:
    https://bitbucket-assetroot.s3.amazonaws.com/repository/Radzbd/4008374530-Capture.PNG?Signature=8VGhdzlYxNVYU0uoLL3x2oQIXH0%3D&Expires=1517141176&AWSAccessKeyId=AKIAIQWXW6WLXMB5QZAQ&versionId=P9veTjLXRJSEYq9lCji1zTidPNk5aXQL)
    So I first tried to place a widget into the scene without any QGraphicsItems.
    The problem is, every answer, I found in the forums, just creates a new window (when trying with QColorDialog) (it closes instatly, but it is there) and I can't set the color in a color dialog f.ex. When I click on it, the mousePress-call just goes to the QgraphicsView, so I can not interact with the widget, except with the mouse wheel.
    I tried this code:

    void GraphWidget::mousePressEvent(QMouseEvent *event){ // class GraphWidget : public QGraphicsView
        QColorDialog *_dialog = new QColorDialog;
        _dialog->setOption(QColorDialog::NoButtons, true);
        _dialog->show();
        QGraphicsProxyWidget *proxyWidget = scene()->addWidget(_dialog);
    
        QGraphicsView::mouseMoveEvent(event);
    }
    

    but as I said, I can't interact with the dialog.

    Is there any example or sth. showing, how to do what I want to? I cound not find one. I am missing something, but every answer in every forum is diferent, but actually no one works for me so far.
    Thanks for answers!


  • Qt Champions 2017

    Hi
    you are not giving the dialog a parent and it will show as window then.
    ColorDialog *_dialog = new QColorDialog; (no parent)
    so when you call show() it will show shortly
    But you are using
    QGraphicsProxyWidget so not sure why you cant interact with it.



  • @mrjj
    Ok, thanks!
    So what should be the parent? When I give the QGraphicsView as parent, it still opens that window and I can't give the scene(), or the mainwindow as parent.


  • Qt Champions 2017

    @Niagarer
    Hi
    I think you are supposed to insert the proxy, not the dialog to scene.
    like

    QColorDialog *_dialog = new QColorDialog;
    _dialog->setOption(QColorDialog::NoButtons, true);
    QGraphicsProxyWidget *proxyWidget = new QGraphicsProxyWidget;
    proxyWidget->setWidget(_dialog);
    scene()->addItem(proxyWidget);
    _dialog->show();
    


  • I just found the solution for the problem with the interaction with the widget. I forgot to ask

    if(!itemAt(event->pos()){
        // place dialog ...
    }
    

    in the MousePressEvent in GraphWidget (so every time I clicked, it placed a new one, before I was able to modify the old one).
    Now the dialog receives everything.
    But well still with a short opening window...

    @mrjj
    Hm, doesn't work here. When I do it this way and call _dialog->show(); before I set it to the proxy's widget, I have the short opening and closing window. When I do it like in your example (calling it after setting it to the proxy's widget), it opens a blank new window, that even does not close automatically


  • Qt Champions 2017

    Hi
    Try
    _dialog-> setWindowFlags(Qt::Widget);



  • @mrjj
    Hi
    It unfortunately still opens that window :/


  • Qt Champions 2017

    Hi
    try to give it a parent on creation then

    QGraphicsProxyWidget *proxyWidget = new QGraphicsProxyWidget; // make first
    QColorDialog *_dialog = new QColorDialog(proxyWidget);
    _dialog-> setWindowFlags(Qt::Widget);
    ....



  • Ok, thanks.
    But I can't use a QGraphicsProxywidget* as a QWidget* (because QGraphicsProxyWidget is not a QWidget class).
    That causes this error, when I try to use a QGraphicsProxyWidget as parent for the QColorDialog:

    error: invalid user-defined conversion from 'QGraphicsProxyWidget*' to 'const QColor&' [-fpermissive]
                 QColorDialog *_dialog = new QColorDialog(proxyWidget);
                                                                     ^
    
     error: invalid conversion from 'QGraphicsProxyWidget*' to 'QRgb {aka unsigned int}' [-fpermissive]
                 QColorDialog *_dialog = new QColorDialog(proxyWidget);
                                                                     ^
    

    Because QColorDialog() expects a QWidget as parent



  • @Niagarer said in Add QWidgets movable to QGraphicsView:

    It unfortunately still opens that window :/

    I have a tricky method for that problem. like this:

    auto    widget = new QWidget;
    auto    dialog = new QColorDialog;
    
    dialog->setOption(QColorDialog::NoButtons, true);
    widget->setLayout(new QHBoxLayout);
    widget->layout()->addWidget(dialog);
    scene()->addWidget(widget);
    

    Tested by Qt 5.10/Windows 7



  • Works perfectly fine
    Thank you!

    So, with this code you can place any QWidget independent in a QGraphicsScene:
    (with a QGraphicsProxyWidget, because usually you want to scale the widget and change the position of it in the scene)

                auto widget = new QWidget;
                auto dialog = new QColorDialog;
                auto proxy = new QGraphicsProxyWidget;
    
                dialog->setOption(QColorDialog::NoButtons, true);
                widget->setLayout(new QHBoxLayout);
                widget->layout()->addWidget(dialog);
                proxy->setWidget(widget);
                scene()->addItem(proxy); // important: if you want to use a proxy, use scene()->addItem() not addWidget()
    

    I will update later, because I have a version of a program here, where I actually don't add the widget with the specific scene()->addSth()-command to the scene, but it actually works. I will update this post once, I got time to understand it :)
    update
    I found two ways of adding proxies to a QGraphicsScene. You can either create a proxy, set its widget (like above) and add it to the scene, or you create a proxy with a QGraphicsItem as parent! Very often, the widgets placed in the scene are attached to QGraphicsItems placed in the scene. If this is your case, create the proxy like this

    MyItemClass::MyItemClass()
    {
        QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
        //                                                  ^^^^^^^^^^
        QLineEdit *widget = new QLineEdit
        proxy->setWidget(widget);
    
        width = widget->width()*proxy->scale();
        height = widget->height()*proxy->scale();
    
        myProxy->setPos(-width/2, -height/2); // place it centered over the item
    }
    

    This does things for you: You don't have to add the proxy to the scene yourself, Qt does it for you here. And another important (and nice) thing here is, that the position of the proxy now is related to the QGraphicsItem's. So when you call

    proxy->setPos(0, 0);
    

    the proxy with the widget will always be with the top left corner at the center of the item, no matter where you drag the item at.

    One little ugly thing here is, that you will get in trouble with a QColorDialog, because the QColorDialog normally opens a new window. You can use the same feature here, but you should create it like áDevopia53 wrote:

    @Devopia53 said in Add QWidgets movable to QGraphicsView:

    I have a tricky method for that problem. like this:

    auto    widget = new QWidget;
    auto    dialog = new QColorDialog;
    
    dialog->setOption(QColorDialog::NoButtons, true);
    widget->setLayout(new QHBoxLayout);
    widget->layout()->addWidget(dialog);
    // ( scene()->addWidget(widget); ) not if you do: 
    //     auto proxy = new QGraphicsProxyWidget(myQGraphicsItem);
    //     proxy->setWidget(widget);
    

    Tested by Qt 5.10/Windows 7


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.