As you noticed, setScaleRatio only establishes the ratio once, and not permanently. This will be changed in future versions of QCustomPlot which will provide a new way to permanently connect axis ranges with defined scale factors.
For now, one solution is to use the rangeChanged signals. Due to floating point precision, you'll have to temporarily disconnect and re-connect the signals while setting the scales, to not cause infinite recursion.
For example
// Connect to rangeChanged signal for both the x and y axes
connect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(fixAxisRatioSlot(QCPRange)));
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(fixAxisRatioSlot(QCPRange)));
// Slot to rescale both axes to maintain a 1:1 aspect ratio
void MyWidget::fixAxisRatioSlot(const QCPRange &newRange)
{
// Disconnect rangeChanged signals for the axes being rescaled
disconnect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(fixAxisRatioSlot(QCPRange)));
disconnect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(fixAxisRatioSlot(QCPRange)));
ui->customPlot->xAxis->setScaleRatio(ui->customPlot->yAxis, 1.0);
// Reconnect rangeChanged signals for the axes being rescaled
connect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(fixAxisRatioSlot(QCPRange)));
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(fixAxisRatioSlot(QCPRange)));
}