Results 1 to 6 of 6

Thread: Align standalone QwtScaleWidget with plots

  1. #1
    Join Date
    Jan 2014
    Posts
    36
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Align standalone QwtScaleWidget with plots

    Ok, hopefully this will be my last Qwt question for a little bit!

    I'm still working on having a single QwtScaleWidget that isn't associated with a specific plot and use it to display the x-axis information for a group of vertically aligned plots in that are in a scroll area. The only issue I have remaining is figuring out how to properly align the standalone QwtScaleWidget with the plots.

    Here's an image of where I'm at currently:
    plotRaw.jpg
    Note how the scale widget up in the top white area isn't aligned with the plots/scale widgets in the grey area.

    And here's where I want to get to (photoshopped image!)
    plotDesired.jpg
    Scale widget in white area is lined up with plots. The per plot bottom scale widgets are disabled.

    And here's a breakdown of all the widgets in play
    plotBreakdown.jpg

    So the specific issues I'm having:
    1. Calculating the correct width of the standalone QwtScaleWidget. I'm assuming maybe if I dig down into QwtPlot's code (maybe inside resizeEvent()?) I can copy how Uwe calculates the correct size for the scale widgets that are internal to the QwtPlot class? Right now, I'm emitting a signal in my myPlot's resizeEvent() (after calling QwtPlot::resizeEvent()) that emits the width of the bottom scale widget. This works when the bottom scale widget is enabled, but obviously doesn't work once I disable the bottom scale widget, so my current method clearly isn't going to work.
    2. Calculating the correct x coordinate (in plotContainer coordinates) for where the standalone QwtScaleWidget needs to be placed to be aligned with the plots. This seems to have something to do with the string length of the leftmost tick label.
    3. Locking the x position of the standalone QwtScaleWidget to the position calculated in the previous step. Right now, the QSpacerItem that is between the "Add Plot.." QPushButton and the QwtScaleWidget seems to just be doing whatever it wants, so the scale widget doesn't line up where I need it to. Maybe once I've calculated the correct x-axis coordinate in step 3 (in plotContainer coordinates), I need to subtract off the QPushButton width, plus the various internal margins/spacings, and then set that QSpacertItem to have a fixed width?
    4. When is the correct time to set the width and position? Right now, the plots are in layouts that allow the plots to take up as much space as they can whenever the main window resizes. I want to keep that functionality intact, but I noticed that as I explicitly resize the standalone scale widget, which I'm triggering off from the plot(s) resizeEvent(), it sometimes causes a ripple effect where the plotContainer widget tries to grow wider, which then causes another plot resize, which can get me in an infinite loop

  2. #2
    Join Date
    Dec 2013
    Location
    Toronto, Canada
    Posts
    62
    Thanked 16 Times in 15 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Align standalone QwtScaleWidget with plots

    If I recall correctly, you have a vertical layout..
    The top row is the scale widget by itself and the following rows are QwtPlots (widgets)
    Now QwtPlot is a composite... Thus, I would do the following...

    Use a grid layout..
    The scalewiget at the top would be in row 0, column 1
    and each QwtPlot should spread across column 0 and column 1 (Force the plot to occupy both columns)


    Added after 49 minutes:


    Did you try...
    QLayout::setAlignment ( QWidget * w, Qt::Alignment alignment )


    Added after 17 minutes:


    Correction to earlier post...

    If you are going with the grid layout..., you'll need 3 columns

    row 0, column 0 -- dummy widget with width==left scaleWidget+ spacing
    and height==standAloneScaleWidget + spacing

    row 0, column 1 -- standAloneScaleWidget + spacing

    row 0, column 2 -- dummy widget with width==right scaleWidget+ spacing
    and height==standAloneScaleWidget + spacing

    rows 1, 2, ...n QwtPlot widgets spread accross 3 columns.

    Do... try QLayout::setAlignment ( QWidget * w, Qt::Alignment alignment ) first
    Last edited by Cah; 23rd August 2014 at 11:14.

  3. #3
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Align standalone QwtScaleWidget with plots

    Before wasting too much time on doing it the hard way, I would have a look at the plotmatrix example. It offers a a class PlotMatrix that does most of the nasty layout code for you.

    Uwe

  4. #4
    Join Date
    Jan 2014
    Posts
    36
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Align standalone QwtScaleWidget with plots

    Thanks for both of your suggestions, but I either I'm missing how your suggestions will fit my specific case or I didn't explain my setup clearly enough.

    Cah wrote:
    If I recall correctly, you have a vertical layout..
    The top row is the scale widget by itself and the following rows are QwtPlots (widgets)
    Cah, as you pointed out, I do have the plots in a vertical layout, but you're incorrect that the first row contains the scale widget. My plots are in a vertical layout which itself is in a scroll area because the user could potentially add enough plots to exceed the vertical size of the mainwindow and/or physical monitor. Since the plots are already aligned vertically, I want to have a single x-axis scale widget OUTSIDE the scroll area so that it is always visible, regardless of vertical scroll position. If I can do that, then I could hide the individual x-axis scale widgets on each plot, which would then provide a little more vertical resolution for the plots themselves. But obviously the scale widget ticks need to line up with where the scale widgets would be if they were enabled, otherwise it looks bad. Also even if I didn't have the scroll area, simply letting a grid layout line up a scalewidget with a plot canvas inside the same grid layout column DOESN'T actually line up the tick marks with their respective plots. Inside qwt_plot_layout.cpp class Uwe has this comment:
    Qt Code:
    1. // +---+-----------+---+
    2. // | <- Axis -> |
    3. // +-^-+-----------+-^-+
    4. // | | | | | |
    5. // | | | |
    6. // | A | | A |
    7. // | x | Canvas | x |
    8. // | i | | i |
    9. // | s | | s |
    10. // | | | |
    11. // | | | | | |
    12. // +-V-+-----------+-V-+
    13. // | <- Axis -> |
    14. // +---+-----------+---+
    15.  
    16. // The ticks of the axes - not the labels above - should
    17. // be aligned to the canvas. So we try to use the empty
    18. // corners to extend the axes, so that the label texts
    19. // left/right of the min/max ticks are moved into them.
    To copy to clipboard, switch view to plain text mode 
    So you can see where the xBottom axis WIDGET can actually be positioned to the left of the plot canvas widget (which happens based on the number of characters in the tick labels), so that the plot ticks line up on with the plot.

    Uwe wrote:
    have a look at the plotmatrix example
    Uwe, I'm not sure the plotmatrix example helps me for the same reason? I think the plotmatrix example would work great for getting all my plots lined up inside the scroll area, but I don't see how it helps me get that standalone scale widget, which is parented by a different widget and is OUTSIDE the scroll area, lined up with the plots themselves? Or did I misunderstand what part of the plot matrix example you wanted me to use?

  5. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Align standalone QwtScaleWidget with plots

    Quote Originally Posted by SeanM View Post
    Uwe, I'm not sure the plotmatrix example helps me for the same reason? I think the plotmatrix example would work great for getting all my plots lined up inside the scroll area, but I don't see how it helps me get that standalone scale widget, which is parented by a different widget and is OUTSIDE the scroll area, lined up with the plots themselves? Or did I misunderstand what part of the plot matrix example you wanted me to use?
    Well at least ( according to your screenshot ) you need the code that finds/sets the maximum extent of the vertical axes to align the canvases.
    Assuming that your scale widget is vertically aligned to the plots you also need this extent to calculate the alignment of the scales inside of your extra scale widget ( see QwtScaleWidget::setBorderDist() ).

    Uwe

  6. #6
    Join Date
    Jan 2014
    Posts
    36
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Align standalone QwtScaleWidget with plots

    I'm still working on applying your last suggestion Uwe, but in the meantime I created a minimal example that replicates where I am currently.

    mainwindow.h
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QMainWindow>
    5. #include <qwt_scale_widget.h>
    6. #include <qwt_plot.h>
    7. #include <QVBoxLayout>
    8. #include <QScrollArea>
    9.  
    10. namespace Ui {
    11. class MainWindow;
    12. }
    13.  
    14. class MainWindow : public QMainWindow
    15. {
    16. Q_OBJECT
    17.  
    18. public:
    19. explicit MainWindow(QWidget *parent = 0);
    20. ~MainWindow();
    21.  
    22. public slots:
    23. void addPlot();
    24.  
    25. private:
    26. Ui::MainWindow *ui;
    27. QwtScaleWidget* scaleWidget; // standalone scale widget
    28. QVBoxLayout* scrollVBox; // vboxlayout inside scroll area to align plots
    29. QScrollArea* scroll;
    30. };
    31.  
    32. #endif // MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 
    mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3. #include <qwt_scale_engine.h>
    4. #include <qwt_date_scale_draw.h>
    5. #include <qwt_scale_widget.h>
    6. #include <qwt_plot_grid.h>
    7. #include <QPushButton>
    8. #include <QLabel>
    9. #include <QHBoxLayout>
    10. #include <QScrollArea>
    11.  
    12. MainWindow::MainWindow(QWidget *parent) :
    13. QMainWindow(parent),
    14. ui(new Ui::MainWindow)
    15. {
    16. ui->setupUi(this);
    17.  
    18. // create horizontal layout above scroll area, with:
    19. // QPushButton QwtScaleWidget QLabel
    20. QPushButton* pbAddPlot = new QPushButton("Add Plot", this);
    21. connect(pbAddPlot, SIGNAL(clicked()),
    22. this, SLOT(addPlot()));
    23. scaleWidget = new QwtScaleWidget(this);
    24. scaleWidget->setAutoFillBackground(true);
    25. scaleWidget->setBorderDist(20,20);
    26. scaleWidget->setAlignment(QwtScaleDraw::BottomScale);
    27. QwtDateScaleDraw* dateScale = new QwtDateScaleDraw();
    28. dateScale->setDateFormat(QwtDate::Millisecond, "ss.zzz");
    29. dateScale->setDateFormat(QwtDate::Second, "mm:ss.zzz");
    30. dateScale->setDateFormat(QwtDate::Minute, "hh:mm:ss.zzz");
    31. dateScale->setDateFormat(QwtDate::Hour, "hh:mm:ss.zzz");
    32. scaleWidget->setScaleDraw(dateScale);
    33. QPalette pal = scaleWidget->palette();
    34. pal.setColor(QPalette::Window, QColor(0,255,255));
    35. scaleWidget->setPalette(pal);
    36. QHBoxLayout* hbox = new QHBoxLayout();
    37. hbox->addWidget(pbAddPlot);
    38. hbox->addWidget(scaleWidget);
    39. hbox->addWidget(new QLabel("Text Label", this));
    40.  
    41. // create the scroll area to hold the vertically aligned plots
    42. scroll = new QScrollArea(this);
    43. scroll->setWidgetResizable(true);
    44. scroll->setSizeAdjustPolicy(QScrollArea::AdjustToContents);
    45. scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    46. QWidget* widget = new QWidget(this);
    47. scroll->setWidget(widget);
    48. scrollVBox = new QVBoxLayout(widget);
    49. widget->setLayout(scrollVBox);
    50.  
    51. QVBoxLayout* vbox = new QVBoxLayout();
    52. vbox->addLayout(hbox);
    53. vbox->addWidget(scroll);
    54.  
    55. centralWidget()->setLayout(vbox);
    56. }
    57.  
    58. MainWindow::~MainWindow()
    59. {
    60. delete ui;
    61. }
    62.  
    63. void MainWindow::addPlot()
    64. {
    65. QPalette pal;
    66. QwtPlot* plot;
    67. plot = new QwtPlot(scroll);
    68. plot->setMinimumHeight(250);
    69. plot->enableAxis(QwtPlot::yRight,true);
    70. //plot->enableAxis(QwtPlot::xBottom, false); // <- this needs to be enabled in the real code
    71. plot->setAutoFillBackground(true);
    72. pal = plot->palette();
    73. pal.setColor(QPalette::Window, QColor(255,255,0));
    74. plot->setPalette(pal);
    75. plot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    76.  
    77. QwtPlotGrid* grid = new QwtPlotGrid();
    78. grid->attach(plot);
    79. QwtScaleWidget* bottomScale = plot->axisWidget(QwtPlot::xBottom);
    80.  
    81. QwtDateScaleDraw* dateScale2 = new QwtDateScaleDraw();
    82. dateScale2->setDateFormat(QwtDate::Millisecond, "ss.zzz");
    83. dateScale2->setDateFormat(QwtDate::Second, "mm:ss.zzz");
    84. dateScale2->setDateFormat(QwtDate::Minute, "hh:mm:ss.zzz");
    85. dateScale2->setDateFormat(QwtDate::Hour, "hh:mm:ss.zzz");
    86. bottomScale->setScaleDraw(dateScale2);
    87. bottomScale->setAutoFillBackground(true);
    88. pal = bottomScale->palette();
    89. pal.setColor(QPalette::Window, QColor(0,255,255));
    90. bottomScale->setPalette(pal);
    91. bottomScale->repaint();
    92.  
    93. QwtScaleWidget* leftScale = plot->axisWidget(QwtPlot::yLeft);
    94. QwtScaleWidget* rightScale = plot->axisWidget(QwtPlot::yRight);
    95.  
    96. leftScale->setAutoFillBackground(true);
    97. rightScale->setAutoFillBackground(true);
    98. pal = leftScale->palette();
    99. pal.setColor(QPalette::Window, QColor(0,255,0));
    100. leftScale->setPalette(pal);
    101. leftScale->repaint();
    102. rightScale->setPalette(pal);
    103. rightScale->repaint();
    104.  
    105. QHBoxLayout* hbox = new QHBoxLayout();
    106. QLabel* label;
    107. label = new QLabel("Custom Legend\nLeft", scroll);
    108. label->setAutoFillBackground(true);
    109. label->setAlignment(Qt::AlignCenter);
    110. label->setFixedWidth(100);
    111. label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
    112. hbox->addWidget(label,0);
    113. hbox->addWidget(plot,10);
    114. label = new QLabel("Custom Legend\nRight", scroll);
    115. label->setAutoFillBackground(true);
    116. label->setAlignment(Qt::AlignCenter);
    117. label->setFixedWidth(100);
    118. label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
    119. hbox->addWidget(label,0);
    120. QWidget* widget = new QWidget(scroll->widget());
    121. widget->setLayout(hbox);
    122. scrollVBox->addWidget(widget);
    123. }
    To copy to clipboard, switch view to plain text mode 
    Here's what the screen looks like after you add a couple plots (via the Add Plot button) and resize and scroll it a little:
    colorPlotsActual.jpg
    And then I again marked it up a little to show what I need to accomplish:
    colorPlotsMarkup.jpg

Similar Threads

  1. Replies: 5
    Last Post: 20th August 2014, 15:42
  2. How to align QwtScaleWidget with QwtPlot
    By mirrorrorrim in forum Qwt
    Replies: 6
    Last Post: 27th May 2013, 08:05
  3. Replies: 3
    Last Post: 8th April 2013, 08:06
  4. QGraphicsView & QwtScaleWidget
    By fruzzo in forum Qwt
    Replies: 1
    Last Post: 28th September 2011, 19:50
  5. Replies: 1
    Last Post: 19th July 2011, 08:32

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.