Проблема изменения обычной оси значений на логарифмическую ось - PullRequest
0 голосов
/ 11 января 2019

У меня есть диаграмма QT с осями обычного значения. Когда я переключаю флажок, я хочу изменить ось X с QValueAxis на QLogValueAxis. Проблема в том, что когда я это делаю, мои данные больше не отображаются в правильной точке.

Я попробовал два подхода (и несколько вариантов к ним), чтобы заставить масштабирование журнала работать, но не то, что я пробовал, похоже, что сами шкалы данных вписываются в окно линейно и игнорируют журнал ось полностью.

Подход 1 - Заменить старую ось:

QLogValueAxis* xLogAxis = new QLogValueAxis();
xLogAxis->setBase(10);
xLogAxis->setMinorTickCount(10);

dataSeries->attachedAxes()[0] = xLogAxis; //Replace the old X Axis on the series
chart->setAxisX(xLogAxis);

Подход 2 - Создайте совершенно новую диаграмму:

chart->removeSeries(data); //release the data so you don't destroy it
QChart* newChart = new QChart();
ui->graphView->setChart(newChart); //Swap the old chart out then delete it 
delete chart;
chart = newChart;

//get rid of the old axes on the data
for(QAbstractAxis* axis : data->attachedAxes()){
    data->detachAxis(axis);
}

QValueAxis* yAxis = new QValueAxis();

data->attachAxis(xLogAxis);
data->attachAxis(yAxis);
chart->addAxis(xLogAxis, Qt::AlignBottom);
chart->addAxis(yAxis, Qt::AlignLeft);
chart->addSeries(data);
chart->legend()->setVisible(false);

Есть какие-нибудь идеи о том, как выполнить горячую замену оси журнала во время выполнения? Заранее спасибо!

1 Ответ

0 голосов
/ 11 января 2019

В следующем примере, как заменить типы осей:

#include <QtWidgets>
#include <QtCharts>

QT_CHARTS_USE_NAMESPACE

typedef std::function<qreal (const qreal &)> function;

static std::vector<std::pair<function, std::string>> functions{
    {[](const qreal & v){ return v;}, "linear"},
    {[](const qreal & v){ return v*v; }, "quadratic"},
    {[](const qreal & v){ return std::exp(0.01*v);}, "exponential"},
    {[](const qreal & v){ return std::sqrt(1 + std::abs(v));}, "square root"}
};

class Widget: public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent=nullptr):
        QWidget(parent),
        xLogAxis(new QLogValueAxis),
        xLinAxis(new QValueAxis),
        yAxis(new QValueAxis)
    {
        xLogAxis->setBase(10);
        xLogAxis->setMinorTickCount(10);
        view.setChart(&chart);
        checkbox.setText("Log Axis");
        connect(&checkbox, &QCheckBox::stateChanged, this, &Widget::onStateChanged);
        QVBoxLayout *lay = new QVBoxLayout(this);
        lay->addWidget(&checkbox);
        lay->addWidget(&view);

        chart.addAxis(yAxis, Qt::AlignLeft);
        // chart.legend()->hide();

        // create series
        for(const std::pair<function, std::string> & func: functions){
            QLineSeries *serie = new QLineSeries;
            serie->setName(QString::fromStdString(func.second));
            for(int i=0; i< 1000; ++i){
                *serie << QPointF(i+1, func.first(i));
            }
            chart.addSeries(serie);
            serie->attachAxis(yAxis);
        }
        onStateChanged(checkbox.checkState());
    }
private slots:
    void onStateChanged(int state){
        QAbstractAxis *removeaxis, *insertaxis;
        if(state == Qt::Checked){
            removeaxis = xLinAxis;
            insertaxis = xLogAxis;;
        }
        else{
            removeaxis = xLogAxis;
            insertaxis = xLinAxis;
        }
        if(chart.axes(Qt::Horizontal).contains(removeaxis))
            chart.removeAxis(removeaxis);
        chart.addAxis(insertaxis, Qt::AlignBottom);

        for(auto serie: chart.series()){
            if(serie->attachedAxes().contains(removeaxis))
                serie->detachAxis(removeaxis);
            serie->attachAxis(insertaxis);
        }
    }
private:
    QCheckBox checkbox;
    QChartView view;
    QChart chart;

    QLogValueAxis *xLogAxis;
    QValueAxis *xLinAxis;

    QValueAxis *yAxis;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.resize(640, 480);
    w.show();
    return a.exec();
}
#include "main.moc"

enter image description here

enter image description here

...