Results 1 to 11 of 11

Thread: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

  1. #1
    Join Date
    Oct 2011
    Posts
    14
    Qt products
    Platforms
    Windows

    Default Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Hi,

    I’m planning to write a little application (mainly Windows compatible) using PyQt and need some help to find the right approach. The app shall contain a QLabel to show an image, a frameless window with some QPushButtons and a QListView. Now the problem is, that both the QLabel and the QListView shall be rotated by a fixed angle around the Z-Axis. The idea is to make the whole app look like a photograph and a notepad laying underneath some sort of technical device (the main widget in the center). All three widgets shall form a compound, that has a fixed size and can be moved as one window, however I want to preserve the “clattered” look and make it frameless, the main widget shall have minimize/close buttons.

    I managed to make the notepad look like somebody had just thrown it on the desktop by using a transformed QGraphicsProxyWidget inside a frameless, transparent QGraphicsView, which is pretty satisfying as I didn’t have to bother about rotating the area receiving mouse events. Now I’m wondering, how to connect this part with the rest. The possibilities I could think of are:


    • Putting all three widgets in QGraphicsProxyWidgets and use the hidden QGraphicsView to keep everything together
    • Combining my current notepad-setup with a single frameless QWidget for the center part and a QLabel showing a rotated image with alpha channel (the image is going to be altered with PIL* anyway)
    • Using my QGraphicsProxyWidget approach on both QLabel and QListView independently and combine them with the main widget.
    • Something completely different?



    Two “features” I’d like to have are a drop-shadow for the whole app (I can recall having problems to get a QGraphicsEffect to work simultaneously on different widgets in the past) and a mask for the whole app, so the parts that are inside the bounds of a widget but invisible don’t receive mouse events. I’d also like the app to open up without much delay, but I have no idea if showing a rotated image in a QLabel would be faster or slower than rotating the whole QLabel inside a QGraphicsView (the image is going to be swapped a few times at runtime).

    I hope someone can clarify which way to take or point out the pros and cons of the different approaches. Thanks in advance.

    *Python Image Library

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    It is difficult for me to visualize what you intend your app to look like, other than a "notepad thrown on a desktop" with "some sort of technical device" on top of it. What the heck is a "technical device"? A miniaturized tactical nuclear weapon? An iPhone? A slide rule? The possibilities are endless.

    However, if all of these things need to be manipulated as a single unit (as well as being individually moved around), I think I would take the first approach of putting the widgets inside of proxies and embedding them into the graphics scene / view. Otherwise, you'll have to do all the work of calculating and propagating the transformations yourself. But it also depends on what your application is to do. Can you interactively write on the notepad (after moving the nuclear weapon / iPhone / slide rule out of the way)?

    I don't think there will be much performance difference between showing a rotated image in a QLabel vs. showing the QLabel rotated. I think it boils down to going through the same QPainter transformation in either case.

    Edit - and I think you could dispense with your QLabel / proxy pair altogether. There are QGraphicsItem classes designed for displaying images.

  3. #3
    Join Date
    Oct 2011
    Posts
    14
    Qt products
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    First of all, thanks for your answer d_stranz.

    It was never my intention to give you headaches about how my app might look, but how could you possibly find out about my nuclear weapon based doomsday device plan?
    Actually it's just a frameless window with some buttons, and two slightly rotated widgets stacked behind it on either side (image and notepad). The notepad cannot be written on, it's just there for the user to select entries and rearrange their order.
    The whole app should move as one and the single parts aren't supposed to be movable individually.
    Since my main widget in the center is frameless, I overwrote the mousePress-, mouseRelease- and mouseMoveEvents to make it movable by clicking and dragging on any empty space. I started with the "putting-everything-in-proxies" approach, and wanted to call QGraphicsView's move(), whenever those events are fired on the main widget, so that it would look like all three embedded widgets would move as one, but it seems that QGraphicsProxy doesn't pass the mouseReleaseEvent down to the embedded widget (I also had to setMouseTracking(True) on the widget to make the mouseMoveEvent fire, which wasn't necessary when I first tried my widget's mouse move functionality outside the whole Proxy-View stuff).
    EDIT2: Solved the mouseReleaseEvent problem: I just had to add event.accept() to the mousePressEvent, as explained here

    So I can move the whole app, but since the mouseReleaseEvent is never fired, it doesn't stop following the cursor. How should I go about making the whole GraphicsView (i.e. all three widgets as one) move when the user clicks and drags the center widget?

    Another strange thing is, that python crashes after I close the application. I could narrow it down to QGraphicsProxyWidget, so that even if I just run this "pythonified" example from the docs, python still crashes, but only after I close the perfectly functional GrapicsView window:

    Qt Code:
    1. if __name__ == '__main__':
    2.  
    3. app = QApplication(sys.argv)
    4.  
    5. scene = QGraphicsScene()
    6. proxy = scene.addWidget(QListView())
    7. view = QGraphicsView(scene)
    8. view.show()
    9.  
    10. sys.exit(app.exec_())
    To copy to clipboard, switch view to plain text mode 
    What am I missing here? And I apologize if this should go into a new thread, just notify me.
    EDIT: The embedded dialogs demo from the PyQt example works like a charm.

    I think you could dispense with your QLabel / proxy pair altogether. There are QGraphicsItem classes designed for displaying images.
    That of course sounds way better and I'm ashamed I didn't think of it myself. Thanks.
    Last edited by Jay-D; 1st April 2013 at 10:31. Reason: Found the solution for one of my problems

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Hmm... maybe you should use QtQuick?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Oct 2011
    Posts
    14
    Qt products
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Well, aside from the mysterious crash, everything is working pretty fine right now, so I don't think I should switch to QtQuick, which I never used before. Seeing how the embedded dialogs example works without the crash after closing it, there MUST be a way to overcome that last obstacle.

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    I am guessing that the crash is due to the widget wrapped by the graphics proxy being deleted (and thus left as a dangling invalid pointer inside the proxy) prior to the proxy being deleted. When the proxy tries to delete the wrapped pointer, it blows up. Just conjecture, because I have no idea how you've implemented it or how it maps into Python. But in my experience, crashes on apps closing tend to be due to something holding a pointer and trying to delete it when it already has been somewhere else.

    So, I would check the use scenario for QGraphicsProxyWidget to see if it takes ownership of the QWidget; if it does, make sure that you are not deleting the QWidget elsewhere (either directly, or giving it another QWidget as parent).

    Edit: note this, from the QGraphicsProxyWidget description:

    Alternatively, you can start by creating a new QGraphicsProxyWidget item, and then call setWidget() to embed a QWidget later. The widget() function returns a pointer to the embedded widget. QGraphicsProxyWidget shares ownership with QWidget, so if either of the two widgets are destroyed, the other widget will be automatically destroyed as well.
    So, if this is what's happening, then the scene could be trying to destroy the graphics proxy after it has already been destroyed. Try connecting a slot to the QGraphicProxyWidget's destroyed() signal; in that slot, remove the proxy from the scene and see if that fixes the crash.
    Last edited by d_stranz; 1st April 2013 at 23:29.

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Giving a widget as a parent is safe because when an object is deleted, it is being detached from the parent so the parent will not delete it again.

    @Jay-D: about switching to Qt Quick -- it's a matter of doing things in a more convenient way. It's only a suggestion to take a closer look at a technology that might give you additional abilities to what you're doing right now.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Giving a widget as a parent is safe because when an object is deleted, it is being detached from the parent so the parent will not delete it again.
    Yes, I knew that. Since your post and my edit crossed in the aether, what about my conjecture concerning the proxy / widget / scene interaction? One would think that if a QWidget deletion resulted in the deletion of its graphics proxy, that would also clean up the scene.

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    I don't think the widget deletes its proxy. Unless of course you reparent it to the widget. This is just my guess, of course. As for the original problem it seems to me it is enough to see the debugger backtrace from the crash. All should be obvious then.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Oct 2011
    Posts
    14
    Qt products
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Thanks for the answers, I managed to get rid of the error. Instead of letting my center widget call qApp.quit(), I now let it call another function, that loops through the QGraphicsProxyWidgets and close()s them and finally close the QGraphicsView. I'm really not an expert in PyQt's parent relationship, right now I'm creating my widgets without parents and then put them into QGraphicProxyWidgets (setWidget()), which seems to work fine. Should I reparent them somehow?

    Anyways, everything works just the way I want it right now, and looking at my original question, I think it's the best approach, as I don't have to worry much about propagating events between the three embedded widgets and everything is wrapped up inside the QGraphicsView, which means I have only one entry in the taskbar.

    And I think I should really give QtQuick a try, the summary sounds nice, thanks for pointing me to it, wysota.

  11. #11
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Putting all widgets in QGraphicsView using QGraphicsProxyWidgets - Good idea?

    Should I reparent them somehow?
    Doesn't seem like it, although if Qt is doing the parenting properly in the first place, you shouldn't have to loop through anything to destroy objects manually. Simply deleting the scene (if it is heap allocated) or allowing it to go out of scope (if stack allocated) should result in all items in the scene being cleanly destroyed and all views being disconnected from the scene. I have never had need to use QGraphicsProxyWidget, so I don't know what happens in that case. Probably would help to comment out your manual cleanup code and see what happens (using the debugger) when Qt goes through its normal shutdown.

Similar Threads

  1. Exception handling in external library - good or bad idea
    By kornicameister in forum Qt Programming
    Replies: 0
    Last Post: 20th February 2012, 14:25
  2. Replies: 2
    Last Post: 4th July 2010, 22:49
  3. Is creating yet another IDE a good idea?
    By piotr.dobrogost in forum Qt Tools
    Replies: 20
    Last Post: 31st July 2009, 07:38
  4. Replies: 1
    Last Post: 16th July 2009, 02:25

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.