Results 1 to 13 of 13

Thread: QSlider Iteration Misses Sample Data on QCustomPlot

  1. #1
    Join Date
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default QSlider Iteration Misses Sample Data on QCustomPlot

    Hi,
    I use QSlider and QCustomPlot widgets together in the project. It works ok generally but when I iterate QSlider once ( single iteration ) after zooming on QCustomPlot a few times( range size decreases), some data missed and can not be examined in detail. Lets say previous x axis range (10:20:000 – 10:20:300), the next range after iteration becomes (10:20:460 - 10:20:760 ). So, 160 miliseconds could not be seen. In this context, my implementation is as follows;
    Qt Code:
    1. connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(horzScrollBarChanged(int)));
    2. connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange)));
    3.  
    4.  
    5. void MainWindow::horzScrollBarChanged(int value)
    6. {
    7. if (qAbs(ui->plot->xAxis->range().center()-value/100.0) > 0.01) // if user is dragging plot, we don't want to replot twice
    8. {
    9. ui->plot->xAxis->setRange(value/100.0, ui->plot->xAxis->range().size(), Qt::AlignCenter);
    10. ui->plot->replot();
    11. }
    12. }
    13.  
    14. void MainWindow::xAxisChanged(QCPRange range)
    15. {
    16. ui->horizontalScrollBar->setValue(qRound(range.center()*100.0)); // adjust position of scroll bar slider
    17. ui->horizontalScrollBar->setPageStep(qRound(range.size()*100.0)); // adjust size of scroll bar slider
    18. }
    To copy to clipboard, switch view to plain text mode 
    Could you please help about this problem ? Thanks in advance for your replies..

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

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Could you please help about this problem ? Thanks in advance for your replies..
    You don't say what the range of your slider is, but you are probably running into round off error when you divide the integer slider "value" by 100. There is also a bug - if the axis range.center() - value / 100 is less than 0.01 at the end of the -last- slider move, then the range doesn't get updated to the final range. So your optimization to avoid repaints is tripping you up.

    Try this instead. A trick to detect when the user is dragging the slider (and to avoid excessive repaints) that works no matter what the axis range is:

    Create a QTimer as a member of your UI class that holds the slider. When the slider changes (your horzScrollBarChanged() slot), record the current position in a member variable, start or restart the timer with a 250 ms timeout, and then exit the slot. Connect the timeout() signal to another slot where you actually set the new axis range.

    As long as the user keeps moving the slider, the timer won't time out (because it is continuously restarted with each move) and the plot won't be repainted. As soon as the slider stops moving for 250 ms, the timeout will trigger the repaint. You can do variations on this - repaint the window every 'n' moves or when the change has become 'large enough' so the plot stays alive. Depends on how fast the plot can repaint. In any case, you never have to check for the size of the change, and the last slider position is always processed.
    <=== 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
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Hi,
    Firstly I would like to thank your for your time. What do you mean by saying " exit the slot when the timer expired "? By the way, it is flickered for some time (in miliseconds ) until setting the new value but can be noticed with eye. Is there any way about removal of flickering ? Another question, axis range missing problem continues with this way of handling if I didn't applied in wrong way. May this problem ( missed range ) be related to sensitivity of numbers. I mean, if I write a new widget which overrides QSlider, with setValue( double ) and valueChanged(double).. Could you please also share your ideas about it ?
    Qt Code:
    1. #ifndef CUSTOMSLIDER_H
    2. #define CUSTOMSLIDER_H
    3.  
    4.  
    5. #include <QApplication>
    6. #include <QtGui>
    7. #include <QVBoxLayout>
    8. #include <QSlider>
    9. #include <QLabel>
    10.  
    11. class CustomSlider : public QSlider {
    12. Q_OBJECT
    13.  
    14. public:
    15. CustomSlider(QWidget *parent = 0) : QSlider(parent) {
    16. }
    17.  
    18. signals:
    19. void doubleValueChanged(double value);
    20.  
    21. public slots:
    22. void setValue(double value)
    23. {
    24. qDebug()<<"Double Slider - setValue - value :" << value;
    25. ?? I suppose the position of slider should be updated according to the value. But I don't know how to do it. I could not find QSlider::setValue function implementation
    26. emit doubleValueChanged(value);
    27.  
    28. }
    29. void notifyValueChanged(double value) {
    30. qDebug()<<"notifyValueChanged - value :" << value;
    31. }
    32. };
    33.  
    34. #endif // CUSTOMSLIDER_H
    To copy to clipboard, switch view to plain text mode 

    Thanks in advance for your reply,
    Last edited by cranberriess89; 19th January 2021 at 11:39.

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

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Rewriting QSlider is not going to fix your problem.

    1. If your slider has a range of 0 - 100, then the best you can do is 1% precision of your full axis range. If you want to do better than that, then you have to use a larger slider range. A 0 - 1000 range with a step size of 1 will give you 0.1% precision (and you divide by 1000, not 100).

    2. There is a logic error in your slider slot: If the difference is < .01 on the last slider move, the if statement will fail, and the new position will not be updated.
    <=== 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.

  5. #5
    Join Date
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Hi,
    As you stated, I removed the check of "diff < 0,01" to handle the last slider correctly. Additionally, 0 - 1000 range setting just worked. But after 5 times zoom, when the range size decreases, data miss problem still exists with one iteration of QSlider.
    I mean, when "the range size" is smaller than "the range which corresponds to one slider move", data miss problem occurs. And this statement emerges when 5-6 times zoom made. Do you have any suggestion to manage this situation ?

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

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Do you have any suggestion to manage this situation ?
    I think you need to look at the calculations you are doing. It sounds to me like you are dividing the unzoomed axis range by 100 or 1000 or whatever. If you do that, you will eventually reach the point you get to - the precision of the slider is less than the current zoom range, so there are areas that get skipped.

    I don't really know how you want this zoom feature to behave so it is hard for me to suggest a solution.
    <=== 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.

  7. #7
    Join Date
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Hi again,

    Lets say our record is 40 seconds.. QSlider range is 0-1000, and I set the range of slider at initialization, not dynamically. So in this case one move of slider is equal to 0,04 seconds. When a lot of zooms are made, the difference btw lower and upper range is smaller than one move size (0.04 seconds). That's why areas are skipped .. Isn't there any way of changing "area size of one qslider move" ? If the area corresponding to the one qslider move decreases, my problem will be resolved. Do you still think DoubleSlider widget is not a solution ?

    Thanks in advance,
    Kind Regards
    Last edited by cranberriess89; 22nd January 2021 at 11:17.

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

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    So in this case one move of slider is equal to 0,04 seconds.
    That's what I suspected - you are using the unzoomed (full) range of your data to set the slider increment.

    Each time you zoom in (or out), you need to reset the mapping between slider value and range so that it matches the current zoomed-in range. So if the initial range is 0 - 40 seconds, and you zoom in by 2x around the center, then the new range is 10 - 30 seconds. The next step halves that again, to 15 - 25 seconds, and so on. You can probably change the slider range to something like 0 - 10 or 0 - 20 steps, so at most you can zoom in by 2^20 if each step zooms by 2x. If a 2x zoom for each step is too much, then use a smaller factor - 1.5 - but not less than 1.0 (which is no zoom at all).
    <=== 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.

  9. #9
    Join Date
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    As you realized, I should update the value of one move of QSlider dynamically when zoomed. As fas as I examined, “One QSlider Move = QCustomPlot Range Size/ QSlider Maximum Width"
    For every zoom, I already update the range of QCustomPlot and value of QSlider but somehow "One QSlider Move" not updated. Is this a bug of QSlider ? I traced logs but after zoom operation, one move iteration width is the same with not zoomed one ( 0.04 seconds ). Do you know the way of updating one move iteration value dynamically ?

    There is a setter of QSlider, setSingleStep(int). I thought I can set it dynamically when zoomed, but it takes only integer values..
    Last edited by cranberriess89; 25th January 2021 at 16:10.

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

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    Is this a bug of QSlider ?
    No, it is a bug in your logic. You need to compute the zoom factor after each step, and use that new factor to scale the plot for the next step. You do not need to change the slider range, ever. What you need to change is how your code translates the current slider value and current plot range into a new width in seconds.

    You probably should post your complete code for how you are doing your zoom operation, and explain in detail what should happen to the plot each time the user moves the slider one step.
    <=== 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.

  11. #11
    Join Date
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    For every zoom, xAxisChanged slot is triggered. So I set new range and values to increase the precision of QSlider, but it didn't work. When range size of QCustomPlot is smaller than one iteration width of QSlider, some areas get skipped.
    Qt Code:
    1. View::View(QWidget *parent) :
    2. AbstractMainWindow(parent),
    3. ui(new Ui::View)
    4. {
    5. precision = 1000.0;
    6. /* ui->horizontalScrollBar = QSlider*/
    7. ui->horizontalScrollBar->setTracking(true);
    8. ui->horizontalScrollBar->setVisible(false);
    9. ui->horizontalScrollBar->setMinimum(0);
    10. ui->horizontalScrollBar->setMaximum(precision);
    11. }
    12.  
    13. void View::horzScrollBarChanged(int value)
    14. {
    15. double ratio = (double)value/(double)(ui->horizontalScrollBar->maximum());
    16. double val = ratio*graphmaxValue;
    17. qDebug()<<"horzScrollBarChanged value : " <<val << "range size:"<< plot->xAxis->range().size();
    18. qDebug()<<"horzScrollBarChanged range : " << plot->xAxis->range();
    19.  
    20. plot->xAxis->setRange(val, plot->xAxis->range().size(), Qt::AlignCenter);
    21. plot->replot();
    22.  
    23. }
    24.  
    25. void View::xAxisChanged(QCPRange range)
    26. {
    27. qDebug()<<"xAxisChanged : range " <<range << "range size:" <<range.size() << "range center:" << range.center();
    28. int value = qRound((range.center()*precision)/graphmaxValue);
    29.  
    30. double currentRangeSize = range.size();
    31. /* initialRangeSize is set when the plot is loaded firstly */
    32. double ratio = currentRangeSize*1000/initialRangeSize;
    33. int newSliderMaximum = (ratio)*1000;
    34.  
    35. ui->horizontalScrollBar->setMaximum(newSliderMaximum);
    36. ui->horizontalScrollBar->adjustSize();
    37.  
    38. qDebug()<<"xAxisChanged horzScrollBar max: " << ui->horizontalScrollBar->maximum();
    39.  
    40. int newRangeValue = (value/1000.0)*(ui->horizontalScrollBar->maximum());
    41. ui->horizontalScrollBar->setValue(newRangeValue);
    42.  
    43. }
    To copy to clipboard, switch view to plain text mode 

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

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    increase the precision of QSlider
    You keep referring to QSlider, but your code indicates a horizontal scrollbar. Which is it?
    <=== 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.

  13. #13
    Join Date
    Jan 2021
    Posts
    8
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSlider Iteration Misses Sample Data on QCustomPlot

    It is QSlider, "ui->horizontalScrollBar" is an instance of QSlider..
    Last edited by cranberriess89; 27th January 2021 at 09:50.

Similar Threads

  1. QSlider Iteration Misses Sample Data on QCustomPlot
    By cranberriess89 in forum Qt Programming
    Replies: 1
    Last Post: 18th January 2021, 18:19
  2. Replies: 1
    Last Post: 2nd March 2020, 18:11
  3. How to implement Warp7 sample as same as sample in QtWS16
    By nntchau in forum Qt for Embedded and Mobile
    Replies: 0
    Last Post: 8th December 2017, 09:06
  4. Serial read misses to read data from the serial port
    By mania in forum Qt for Embedded and Mobile
    Replies: 11
    Last Post: 18th August 2014, 09:49
  5. Replies: 16
    Last Post: 27th March 2013, 07:23

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.