Results 1 to 4 of 4

Thread: Draw a line over a central widget

  1. #1
    Join Date
    Nov 2019
    Location
    Lyon, France
    Posts
    18
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Draw a line over a central widget

    Hi!

    I'm creating an application for data visualization.
    To keep it simple, I have multiple plots (I'm using QCustomPlot), organized in a VLayout. I put this layout in a QWidget and set this widget as the Central Widget of the main window.

    Now, I want to be able to draw a vertical line all over the central widget on the mouse position when I click it. Then I will compute the average of the data that are on this line.

    I can't find a way to make it. Do you have any advice ?
    I read that I may use QPainter but I can't figure out how it works...

  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: Draw a line over a central widget

    First, you cannot use QWidget as the central widget if you want to do this. You must derive a class from QWidget and override the paintEvent() (and probably mouse events as well), which is where you will draw your line after calling the base class QWidget paintEvent.

    Second, presumably the user can click in any of the stacked plots to initiate the averaging action. So you will need to implement a handler for these events in your plots. Those events are probably going to return values in plot (i.e. data) coordinates, not window (pixel) coordinates, so you will have to map from plot coordinate to window coordinates, since that is what you will use to draw your line.

    While the user is moving the line to the final position, you will probably want to use QRubberBand to draw it. After the user has released the mouse, you would then use QPainter in the paintEvent to draw the permanent line.

    You could also do this the other way around - capture the mouse events in pixel coordinates in the QWidget-based class, then map those to data coordinates for your averaging.

    In any case, this is not a particularly easy problem to solve, especially if you want to also continue to use other mouse actions in the plots.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Nov 2019
    Location
    Lyon, France
    Posts
    18
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Draw a line over a central widget

    Thanks !
    I did some research on the side too.

    If I understand this correctly, I should derive a class from QWidget, CustomWidget1, to use it for the overlay (drawing and mouse event management), and another class, CustomWidget2, for the display of the plot.
    Then I could make another QWidget, a wrapper, and set it to be the parent to the two previous ones.

    Is it the correct way ?
    I'm not sure if it's clear... I don't have access to my code now, I will post it if it doesn't work.

  4. #4
    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: Draw a line over a central widget

    I suppose you could use a transparent overlay widget to handle the mouse events and line overlay. You would need to override the resizeEvent() in the parent widget to ensure that both the overlay and plot widget holder were resized to exactly the same size and position. This could be a bit tricky due to margins and other padding that gets added to composite widgets with layouts. You would not have to derive a custom widget as your plot widget holder if you use an overlay widget. This could remain as a plain QWidget since you no longer would have any need to override events there.

    In the resizeEvent() handler, check the isVisible() value for each child widget and don't do anything if visible is false. The resizeEvent() might be called several times before the window is first shown as Qt does the initial layout, and the sizes at this point are generally not valid. Once the showEvent() occurs, the sizes in the resizeEvent() are then valid and can be used to resize the child windows.

    Using an overlay also has the advantage that you can simply turn it off (hide()) when not needed.

    A trick: If you find that you get excessive redraws of the plot widget when you are interacting with the overlay widget, when the mouse first gets pressed make a QImage snapshot (render()) of the plot widget, hide the plot widget, and use that snapshot as the background of your overlay. When the interaction stops (mouse released), remove the background image and show the original plot widget again.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Replies: 1
    Last Post: 10th August 2014, 22:06
  2. Replies: 0
    Last Post: 28th March 2013, 01:22
  3. Replies: 8
    Last Post: 28th June 2011, 15:57
  4. Draw a line between widget and mouse?
    By AyaKoshigaya in forum Qt Programming
    Replies: 6
    Last Post: 26th April 2010, 07:32
  5. QDockWidgets without central widget
    By JoeMerchant in forum Qt Programming
    Replies: 17
    Last Post: 8th August 2007, 15:52

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.