LINUX.ORG.RU

Как правильно работать с QList?

 , ,


0

2

Имеем классическую шаблонную программу на Qt5, то есть есть файлы main.cpp, name.h, name.cpp. В файле name.h есть класс app от qmainwindow, в нём

private:
    ...
    QList<QwtPlotCurve> *graph;

В конструкторе класса есть

graph = new QList<QwtPlotCurve>[10];
for(int i=0; i < graph->size(); i++)
{

}

QwtPlotCurve имеет свои методы, и мне нужно перекрасить каждую кривую в свой цвет, привязать их к виджету через attach, и потом обновлять с периодом 1/25 сек. Отдельно с кривым, когда они не члены QList, я работать умею, но тут затык. Например на

graph[i].attach(ui->graphWidget);

ругаются No member named 'attach' in 'QList<QwtPlotCurve>', хотя такой метод у QwtPlotCurve есть.

graph->at(i).attach(m_ui->graphWidget);

выплёвывает 'this' argument to member function 'attach' has type 'const QwtPlotCurve', but function is not marked const.

Как правильно обращаться к элементами QList?

PS. выхлоп читать умею, откуда ноги растут понимаю, не понимаю что делать.


UPD

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

Ссылка на тот же вопрос на хабре.



Последнее исправление: nikitalol (всего исправлений: 4)

Дело не в том, как правильно работать с QList, а в том как правильно работать с указателями.

graph = new QList<QwtPlotCurve>;
// ...
(*graph)[i].attach(ui->graphWidget);

И зачем вообще делать указатель на QList? Он все равно хранит непосредственные данные в куче, а не на стеке. А, это ты видимо пытаешься создать десять элементов внутри QList - ну-ну. Нужно создать QList и далее методом append() или push_back() вставлять элементы.

Далее. Метод at() ведь описан как константный и при этом возвращающий ссылку на константу https://doc.qt.io/qt-5/qlist.html#at. Чего ж тут удивляться?

Поэтому я всегда советую: прежде всего нужно почитать что-нибудь по основам C++, а потом уже браться за Qt.

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 11)

Видимо дело вот в этой строке?

graph = new QList<QwtPlotCurve>[10];

Которую читать нужно как

Создать указатель на массив из 10 QList<QwtPlotCurve>

А по хорошему нужно

QList<QwtPlotCurve*> graph;

Хотя пусть C++-ники поправят, хорошая ли идея хранить экземпляр компонента в контейнере

anonymous
()

может конечно не к месту…но в современном cpp, использование указателя, значит недоделанность/неправильность конструктива.

объявление «QList< QwtPlotCurve > *graph» хреновый знак….

плюсы работают пока не трогают указатели

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от rumgot

Да, в целом вы правы.

Нужно создать QList и далее методом append() или push_back() вставлять элементы.

Можно ту по подробнее объяснить?

И вопрос такой:

А не будет ли проще просто создать массив указателей на QwtPlotCurve, что нибудь типа QwtPlotCurve *cruve[10];, или я совсем туплю?

nikitalol
() автор топика

private:

QList *graph;

Зачем указатель? Положи на стек.

graph[i].

Ты сейчас итерируешься по массиву QList’ов, а не по его содержимому. У тебя здесь выход за границу памяти. Тогда уж так (*graph)[i]. Но лучше избавится от указателя, как я в начале написал.

Не знаешь семантику цепепе.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

Не очень понятно к чему вы пишете. Похоже у вас тут два акка, и вы запутались.

Про

Ты сейчас итерируешься по массиву QList’ов, а не по его содержимому. У тебя здесь выход за границу памяти. Тогда уж так (*graph)[i].

я уже понял.

Вопрос встал немного шире:

А не будет ли проще просто создать массив указателей на QwtPlotCurve, что нибудь типа QwtPlotCurve *cruve[10];, или я совсем туплю?

И вообще избавится от QList.

nikitalol
() автор топика
Последнее исправление: nikitalol (всего исправлений: 2)

Ты зачем то создал не список, а массив списков.

anonymous
()

для Qlist нет конструктора, в котором бы сразу происходил resize, за исключением случая создания из другого объекта и потому выходит в две команды:

graph = new QList<QwtPlotCurve>;
graph.reserve(10);
Silerus ★★★★
()
Последнее исправление: Silerus (всего исправлений: 1)
Ответ на: комментарий от Silerus

При этом ты не устанавливаешь размер листа. Это резервирование памяти.

rumgot ★★★★★
()
Ответ на: комментарий от nikitalol

А не будет ли проще просто создать массив указателей на QwtPlotCurve, что нибудь типа QwtPlotCurve *cruve[10];, или я совсем туплю?

Можно и так, но по мне проще через QList, т.к. не нужно вручную заниматься выделением/освобождением памяти (что способствует возникновению утечек памяти и т.п.).

Вообще QList и подобные высокоуровневые контейнеры как раз и нужны для того, чтобы избавится от головной боли и удобно работать.

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 2)

сам qlist всегда аллоцируется в heap, делай проще вроде как:

private:
    ...
    QList<QwtPlotCurve *> graph;

cpp:
for(int i=0; i < 10; i++)
{
    QwtPlotCurve *curve = new QwtPlotCurve();
    graph.insert(i, curve);
    graph.at(i)->attach(m_ui->graphWidget);
}

bhfq ★★★★★
()
Ответ на: комментарий от nikitalol

А не будет ли проще просто создать массив указателей на QwtPlotCurve, что нибудь типа QwtPlotCurve *cruve[10];, или я совсем туплю?

QList обычный контейнер который не будет решать проблему с освобождением памяти точно также как ее не будет решать твой массив указателей.

напишешь в деструкторе

qDeleteAll(grapth);
grapth.clear();
bhfq ★★★★★
()
Ответ на: комментарий от MKuznetsov

плюсы работают пока не трогают указатели

Просто руки должны быть достаточно прямыми, иначе да, лучше писать на похапэ, и С++ обходить за километр.

CrossFire ★★★★★
()
Ответ на: комментарий от CrossFire

Есть подходящие инструменты, такие как умные указатели или контейнеры. Какого хера ими не пользоваться? Чтобы сказать, что ТЫЖПI$ДАTЫЙПРОГРАММИСТ С ПРЯМЫМИ РУКАМИ?

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

а) Где я возражал против использования контейнеров?

б) Говорить, что в Qt, где свой подсчет ссылок работает через parent уже 20 лет, и не особо совместим с умными указателями,

использование указателя, значит недоделанность/неправильность конструктива

это просто расписаться в непонимании того, как всё устроено.

CrossFire ★★★★★
()
Ответ на: комментарий от CrossFire

использование указателя, значит недоделанность/неправильность конструктива

Ну как я понял, он имел ввиду не конкретно Qt, а в принципе использование указателей без нужды.

rumgot ★★★★★
()

graph.attach(ui->graphWidget);

graph->attach(ui->graphWidget);

graph->at(i).attach(m_ui->graphWidget);

graph.at(i)->attach(m_ui->graphWidget);

anonymous
()
Ответ на: комментарий от CrossFire

А разве подсчет ссылок/указателей в Qt (тот что через parent у класса QObject) каким-то боком касается контейнера QList? Так он мог таким же образом написать:

std::vector<int>* cont;

Поэтому я бы сказал, что это касается не только Qt-шных контейнеров.

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.