在 QLineEdit::editingFinished 循环中访问 QBarDataItem 时发生读取访问冲突

问题描述 投票:0回答:1

我目前正在尝试使用 Qt DataVisualization。

目标是我有一个

QLineEdit
,当我退出它时,我使用
QLineEdit::editingFinished
信号。然后我将输入的值设置为所选的
Bar

当我尝试访问

for
时启动第二个
QBarDataItem
循环时,我在第 46 行收到错误。我在那里遇到了读取访问冲突,并且在 Qt 的
qarraydatapointer.h
文件的这一行上收到了错误:

bool needsDetach() const noexcept { return !d || d->needsDetach(); }

这是我的代码:

主文件:

#include <QApplication>
#include <QFile>
#include "Window.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    
    // creates a window
    Window window;
    QFile file(app.applicationDirPath() + "/Test.txt");

    // Writes the x and y position of the selected Bar
    QObject::connect(window.getSeries(), &QBar3DSeries::selectedBarChanged, [&]() {
        if (!file.open(QIODevice::ReadWrite)) {
            QTextStream stream(&file);
            stream << window.getSeries()->selectedBar().x() << ", "
                   << window.getSeries()->selectedBar().y() << ", "
                   << window.getSeries()->dataProxy()->rowAt(window.getSeries()->selectedBar().x())->data()->value() << "\n";
        }
    });

    QFile file1(app.applicationDirPath() + "/Data.txt");
    if (file1.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QTextStream in(&file1);
        QBarDataRow *data = new QBarDataRow;
        while (!in.atEnd()) {
            QString line = in.readLine();
            *data << line.toFloat();
        }
        window.getSeries()->dataProxy()->addRow(data);
    }  
    
    window.show();
    file.close();
    file1.close();
    return app.exec();
}

窗口.h:

#ifndef WINDOW_H
#define WINDOW_H

#include <QMainWindow>
#include <QtDataVisualization>

#define WIDTH 1400
#define HEIGHT 800

struct Data {
    Data() {
        data1 = new QBarDataRow;
        data2 = new QBarDataRow;
        data3 = new QBarDataRow;
        data4 = new QBarDataRow;
        data5 = new QBarDataRow;
    }
    ~Data() {
        delete data1;
        delete data2;
        delete data3;
        delete data4;
        delete data5;
    }

public:
    QList<QBarDataRow *> data{ data1, data2, data3, data4, data5 };
    QBarDataRow *data1;
    QBarDataRow *data2;
    QBarDataRow *data3;
    QBarDataRow *data4;
    QBarDataRow *data5;
};

class Window : public QMainWindow {
    Q_OBJECT

public:
    Window(QWidget *parent = nullptr);
    ~Window();
    QBar3DSeries *getSeries();

protected:
    void resizeEvent(QResizeEvent *event) override;

private:
    Q3DBars *m_bars;
    QBar3DSeries *m_series;
    Data *m_data;
    QWidget *m_graph;
};

#endif // WINDOW_H

窗口.cpp:

#include "Window.h"
#include <QLineEdit>

static void setData(Data *data, QBar3DSeries *series) {
    *data->data1 << 1.0f << 3.0f << 6.5f << 5.0f << 2.2f;
    *data->data2 << 2.0f << 1.5f << 5.0f << 2.0f << 2.4f;
    *data->data3 << 3.0f << 2.5f << 4.0f << 1.0f << 3.4f;
    *data->data4 << 2.9f << 2.5f << 2.3f << 3.1f << 1.7f;
    //*data->data5 << 1.6f << 1.1f << 1.8f << 4.8f << 3.4f;

    series->dataProxy()->addRow(data->data1);
    series->dataProxy()->addRow(data->data2);
    series->dataProxy()->addRow(data->data3);
    series->dataProxy()->addRow(data->data4);
    //series->dataProxy()->addRow(data->data5);
}

Window::Window(QWidget *parent) : QMainWindow(parent) {
    // Initialising variables
    m_bars = new Q3DBars;
    m_series = new QBar3DSeries;
    m_data = new Data;

    setWindowTitle("Physik");
    resize(WIDTH, HEIGHT);

    m_bars->rowAxis()->setRange(0, 4);
    m_bars->columnAxis()->setRange(0, 4);
    m_bars->scene()->activeCamera()->setCameraPosition(30, 30);

    // set values which can then be seen
    setData(m_data, m_series);
    m_bars->addSeries(m_series);

    // Creates a QWidget, which is a child of the QMainWindow (this)
    m_graph = QWidget::createWindowContainer(m_bars, this);
    m_graph->setGeometry(0, 0, WIDTH * 0.7, HEIGHT);
    //--------------------------------------------------------------
    QLineEdit *lineEdit = new QLineEdit(this);
    lineEdit->setGeometry(WIDTH * 0.75, HEIGHT * 0.1, WIDTH * 0.85, HEIGHT * 0.15);
    connect(lineEdit, &QLineEdit::editingFinished, [&]() {
        QPoint position = m_series->selectedBar();
        for (size_t i{}; i < m_data->data.size(); ++i) {
            if (i == position.x()) {
                size_t j{};
                for (auto &value : *m_data->data[i]) {
                    if (j == position.y()) {
                        value.setValue(lineEdit->text().toFloat());
                    }
                    ++j;
                }
                break;
            }
        }
    });
}

Window::~Window() {}

QBar3DSeries *Window::getSeries() {
    return m_series;
}

void Window::resizeEvent(QResizeEvent *event) {
    QMainWindow::resizeEvent(event);
    if (m_graph) {
        m_graph->resize(event->size().width() * 0.7, event->size().height());
    }
}

我尝试编写自己的

QBarDataItem
QBarDataRow
,它们继承了公共的两个类,并尝试重写函数,但没有成功,我真的尝试了很多不同的东西。但没有任何效果,所以我希望你能帮助我。

我知道这个问题最好不要太具体,这样很多人都可以提供帮助。最后,我只是尝试选择一个

Bar
,当我退出
QLineEdit
时,该值将被设置为所选的
Bar
enter code here

c++ qt widget physics qwidget
1个回答
0
投票

当构造

m_data
对象时,其构造函数首先将 data1..data5 成员的
copy
添加到
data
列表中 before 这些成员尚未初始化。然后在填充
data
列表后初始化这些成员,并且
data
列表内的指针永远不会更新。因此,当您的循环稍后从
m_data->data[i]
检索指针并尝试取消引用它时,您会遇到 未定义的行为,从而导致运行时崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.