qtqcustomplot

How to resize qt dock widget to fit qCustomPlot widget?


A qDockWidget containing a qCustomPlot always starts with zero height. I am able to catch the qDockWidget resize event and change the qCustomPlot geometry using these answers, but the qCustomPlot is always hidden until it is manually stretched. Should this happen automatically, or do I need to calculate and set the dock height at startup?

This sample code creates a new qCustomPlot widget, places it in a layout, places that layout in another widget, and sets it to the dock. I have also tried placing the qCustomPlot widget directly into the dock. qCustomPlot setGeometry, setMinimumSize, and setSizePolicy seem to have no effect on the dock height.

#include <QMainWindow>
#include "qcustomplot.h"


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(){
        QCustomPlot *m_customPlot;
        QDockWidget *dock;

        resize(1200, 600);

        //create the plot
        QWidget *plot_frame_temp= new QWidget();
        plot_frame_temp->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
        m_customPlot = new QCustomPlot(plot_frame_temp);
        m_customPlot->axisRect()->setupFullAxesBox(true);
        m_customPlot->setBackground(Qt::black);
        //size and margin settings
        m_customPlot->setGeometry(QRect(0, 0, 500, 400));
        m_customPlot->axisRect()->setMinimumSize(500,400);
        m_customPlot->axisRect()->setAutoMargins(QCP::msLeft|QCP::msBottom|QCP::msRight|QCP::msTop);
        // zoom and drag only on horrizontal axis
        m_customPlot->axisRect()->setRangeZoomAxes(m_customPlot->xAxis,nullptr);
        m_customPlot->axisRect()->setRangeDragAxes(m_customPlot->xAxis,nullptr);
        //setup the top axis and labels
        m_customPlot->xAxis->setVisible(false);
        m_customPlot->xAxis2->setVisible(true);
        m_customPlot->xAxis2->setTicks(true);
        m_customPlot->xAxis2->setTickLabels(true);
        m_customPlot->xAxis2->setTickPen(QColor(136, 136, 136));
        m_customPlot->xAxis2->setTickLength(0,10);
        m_customPlot->xAxis2->setTickLabelColor(QColor(136, 136, 136));
        m_customPlot->xAxis2->setSubTickPen(Qt::NoPen);
        m_customPlot->xAxis2->setBasePen(Qt::NoPen);
        QFont font;
        font.setStyleStrategy(QFont::PreferOutline);
        m_customPlot->xAxis2->setTickLabelFont(font);
        //setup the left axis and hide
        m_customPlot->yAxis->setVisible(false);
        m_customPlot->yAxis->setRangeReversed(true);
        m_customPlot->yAxis2->setVisible(false);
        //first graph
        m_customPlot->addGraph();
        m_customPlot->graph()->setPen(QPen(QColor(165, 165, 165)));
        m_customPlot->graph()->setLineStyle((QCPGraph::lsStepLeft));
        //second graph
        m_customPlot->addGraph();
        m_customPlot->graph()->setPen(QPen(QColor(165, 165, 165)));
        m_customPlot->graph()->setLineStyle((QCPGraph::lsStepLeft));
        // make some data
        QVector<double> x(500), y0(500), y1(500);
        for (int i=0; i<500; ++i)
        {
        x[i] = i;
        y0[i] = (rand() % 2 + 0.2)/2;
        y1[i] = (rand() % 2 + 1.4)/2;
        }
        //add data to graph
        m_customPlot->graph(0)->setData(x, y0);
        m_customPlot->graph(1)->setData(x, y1);
        // set some options
        m_customPlot->setNotAntialiasedElements(QCP::aeAll);
        m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

        //add plot widget to layout
        QHBoxLayout *laLayout = new  QHBoxLayout();
        laLayout->addWidget(plot_frame_temp);

        //add layout to another widget
        QWidget *laWidget=new QWidget();
        laWidget->setLayout(laLayout);

        //add second widget to dock
        dock = new QDockWidget(tr("qcustomplot"), this);
        dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
        dock->setWidget(laWidget);

        addDockWidget(Qt::BottomDockWidgetArea, dock);

        QWidget *centralWidget=new QWidget();
        setCentralWidget(centralWidget);
    }

};

Here is a minimum example done directly in mainwindow.h. A dock with a central widget and a QDockWidget with a qCustomPlot. I am using the compiled DLL version of qCustomPlot

Image: dock starts with zero height:

enter image description here

Initially the dock looks like this. The plot is hidden and the dock is claiming no height in an otherwise empty layout.

Image: dock stretched to show the plot

enter image description here

The plot is visible when the user stretches the dock.

I strongly suspect there is a way for the dock to adjust to the height of the qCustomPlot automatically. I can set the dock height from code, but that seems like a hack.


Solution

  • The most direct approach to solve your issue might be to define a minimum size for your QCustomPlot Widget. This can easily achieved with the following reduced example. Actually, the problems has nothing to do with QCustomPlot at all. It could have been any kind of widget with minimum size (0,0).

    #include <QMainWindow>
    #include "qcustomplot.h"
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(){
            auto m_customPlot = new QCustomPlot();
            m_customPlot->axisRect()->setupFullAxesBox(true);
    
            auto dock = new QDockWidget(tr("qcustomplot"), this);
            dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
            dock->setWidget(m_customPlot);
            m_customPlot->setMinimumSize(QSize(500,500));
            dock->setMinimumSize(m_customPlot->minimumSize());
            addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, dock);
    
            setCentralWidget(new QWidget);
        }
    
    };
    

    A better solution might to save and to restore the geometry of your dock widget configuration in the registry. This leaves the user with just the dock widget configuration that he finds desirable.

    void MainWindow::closeEvent(QCloseEvent *event)
    {
        QSettings settings("MyCompany", "MyApp");
        settings.setValue("geometry", saveGeometry());
        QMainWindow::closeEvent(event);
    }
    
    QSettings settings("MyCompany", "MyApp");
    dock->restoreGeometry(settings.value("myWidget/geometry").toByteArray());