Top.Mail.Ru

Приложения Qt и библиотека Qwt. Построение графиков.

Продолжаем рубрику, посвященную Qt. В этой статье рассмотрим процесс построения графиков с использованием Qt и библиотеки Qwt (напомню, что процесс установки библиотеки описан тут). Для начала запускаем Qt Creator и создаем новый проект:

Новый проект в среде разработки Qt Creator

Как только проект создан, сразу же, пока не забыли, идем в .pro файл проекта и подключаем библиотеку Qwt. То есть дописываем строки:

INCLUDEPATH += D:/Documentation/QWT/include
LIBS += -LD:/Documentation/QWT/lib–lqwt

Соответственно, пути к файлам библиотеки у каждого свои. Как же мы, собственно, будем рисовать графики?

А для этого нам нужно будет создать объект класса QwtPlot, на который мы поместим QwtPlotCurve – это непосредственно кривая. Итак, все в том же файле MainWindow.h пишем:

namespace Ui 
{
	class MainWindow;
}

class MainWindow : public QMainWindow
{
	Q_OBJECT

public:
	explicit MainWindow(QWidget *parent = 0);
	~MainWindow();

private:
	QwtPlot *plot;
	QwtPlotCurve *curve;
	Ui::MainWindow *ui;
	void setGraphData();
};

Мы объявили объекты plot и curve, с которыми и будем работать, а также функцию void setGraphData(), которую будем использовать для того, чтобы задать уравнение кривой. Теперь открываем файл mainwindow.cpp и реализуем конструктор класса MainWindow:

MainWindow::MainWindow(QWidget *parent):
	QMainWindow(parent),
	ui(new Ui::MainWindow)
{
	ui->setupUi(this);
	plot = new QwtPlot();
	plot->setAxisScale(QwtPlot::xBottom, -1, 1);
	plot->setAxisScale(QwtPlot::yLeft, 0, 1);
	curve = new QwtPlotCurve("x(y)");
	curve->setStyle(QwtPlotCurve::Lines);
	curve->setPen(QPen(Qt::blue));
	setGraphData();
	curve->attach(plot);
	plot->replot();
	this->setCentralWidget(plot);
}

Давайте разбираться, что же тут происходит... Создаем объект plot:

plot = new QwtPlot();

Задаем интервалы, которые будут отображаться на осях x и y:

plot->setAxisScale(QwtPlot::xBottom, -1, 1);
plot->setAxisScale(QwtPlot::yLeft, 0, 1);

Теперь нужно создать объект класса QwtPlotCurve:

curve = new QwtPlotCurve("x(y)");

Задаем стиль и цвет графика:

curve->setStyle(QwtPlotCurve::Lines);
curve->setPen(QPen(Qt::blue));

Конечно, есть еще множество параметров кривой, с которыми можно поиграться, но нам пока достаточно этого минимума.

Идем дальше по коду. В следующей строчке вызываем нашу функцию setGraphData(), ее реализацию напишем чуть позже. И, наконец, мы добавляем кривую на "холст", даем ему команду "перерисоваться" и устанавливаем объект plot в качестве центрального объекта главного окна приложения:

curve->attach(plot);
plot->replot();
this->setCentralWidget(plot);

Остается добавить реализацию setGraphData() все в том же файле MainWindow.cpp:

void MainWindow::setGraphData()
{
	const int n = 1000;
	double h = 2.0 / n;
	double x[n];
	double y[n];
	for(int i = 0; i < n; i++)
	{
		x[i] = -1 + i * h;
		y[i] = qAbs(x[i]);
	}
	curve->setSamples(x, y, n);
}

Берем 1000 точек, задаем шаг изменения переменной x, для каждого значения x вычисляем значение y (кстати, тут строим график функции y = |x|), и вызовом функции setSamples() добавляем все полученные точки на график. Осталось почистить все после себя! Дописываем в деструктор класса MainWindow:

MainWindow::~MainWindow()
{
	delete ui;
	delete curve;
	delete plot;
}

И запускаем сборку приложения. Получается такой вот график:

Пример создания графика

Теперь можно добавить интерфейс для работы с графиком, а именно средства для масштабирования. Для этого нам понадобится класс ScrollZoomer, не входящий в библиотеку Qwt. Но не будем сокрушаться из-за его отсутствия, а спокойно возьмем его из примеров, поставляющихся вместе с библиотекой. Находим в папке Qwt (не в той папке, в которую установлена библиотека, а в той, которую изначально скачивали) подпапку Examples. Открываем папку с проектом RealTime и забираем оттуда 4 следующих файла в папку с нашим проектом:

Построение графика в QT

В файле MainWindow.h дописываем:

#include "scrollzoomer.h"
#include "scrollBar.h"

А также объявляем объект класса ScrollZoomer:

private:
	QwtPlot *plot;
	QwtPlotCurve *curve;
	Ui::MainWindow *ui;
	ScrollZoomer *zoomer; //Добавили строку
	void setGraphData();
};

В конструкторе класса MainWindow (файл MainWindow.cpp) добавляем лишь одну строчку:

setGraphData();
curve->attach(plot);
zoomer = new ScrollZoomer(plot->canvas()); //И еще одну строку добавили
plot->replot();
this->setCentralWidget(plot);

Вот и все, всего лишь пара строчек, запускаем приложение и видим, что теперь можно увеличивать любую часть графика, а также возвращать исходный масштаб нажатием правой кнопки мыши:

Изменение масштаба графика

На этом все, спасибо за внимание и до скорого 🤝

Подписаться
Уведомить о
guest

15 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
Иван
Иван
10 лет назад

А удалить zoomer в деструкторе? Ну и plot есть виджет, который добавляется в дерево виджетов, удаление объектов которого берет на себя QT, поэтому удалять его в деструкторе не нужно.
Так ведь?

Сергей
10 лет назад

Я создал форму
Form* form = new Form();
form->showNormal();
и тепер в етой форме хочу вивести етот plot.
Но у формЫ нет метода setCentralWidget();
Как сделать что бЫ при нажатии на кнопку вилетала новая форма/widget с графиком?
Помогите плз!
Зарание Спасибо!

Сергей
Ответ на комментарий  Сергей
10 лет назад

Все, разобрался. Спасибо за статью.

Виктор
Виктор
10 лет назад

Спасибо за статью! =) Только у меня ошибки лезут, и так на каждый вызов всех функций Qwt'а:
D:\Programming\QtProjects\QtDPS\mainwindow.cpp:-1: ошибка: undefined reference to `QwtPlotCurve::setSamples(double const*, double const*, int)'
Подскажите, что может быть? Путь в Path прописал

Виктор
Виктор
Ответ на комментарий  Виктор
10 лет назад

В общем, и студия, и Creator ругаются на эти вызовы, мол, не объявлялись, неразрешённые внешние символы, как любит студия...

Евгений
Евгений
9 лет назад

Только начал изучение Qt. Работаю с Qt 5.3.
Библиотеку qwt поставил. При сборке проекта получаю сообщение :
"QWidget: Must construct a QApplication before a QWidget
Invalid parameter passed to C runtime function."
Прошу помощи.

Евгений
Евгений
9 лет назад

Сделал сборку приложения в release и заработало.
Приложение - пример этой статьи. Получается у меня qwt собрана в release ? Сборку qwt я делал по инструкции на этом же сйте, т.е. https://microtechnics.ru/qt-ustanovka-biblioteki-qwt/
По этой инструкции надо добавить в файл
\..\qwt-6.0.1\designer\designer.pro строку CONFIG += release. В итоге у меня сейчас в этом файле такие строки:
CONFIG -= debug_and_release
CONFIG += release
Получается, если мне надо приложение собрать в debug моде, то надо всю qwt заново пересобирать ?!

Александр
Александр
9 лет назад

При добавлении файлов scrollbar и scrollzoomer вылезает следующая ошибка:
error LNK2001: неразрешенный внешний символ ""public: static struct QMetaObject const QwtPlotZoomer::staticMetaObject" (?staticMetaObject@QwtPlotZoomer@@2UQMetaObject@@B)" moc_scrollzoomer.obj Project 1
Остальные вызовы Qwt работают нормально.

LEV
LEV
7 лет назад

Aveal, "LIBS += -LD:/Documentation/QWT/lib -lqwt" я так полагаю это "косячит движок кода на сайте" :))

LEV
LEV
7 лет назад

Как в методе void MainWindow::setGraphData() не создавать отдельный массив, это возможно? Ну т. е. к примеру в заголовочном файле MainWindow.h объявить указатель, затем передать в объект этого класса адрес на некоторого массива, а уже в место curve->setSamples(x, y, n); писать что то вроде
curve->setSamples(pointer_x, pointer_y n); Что то подобное возможно?

15
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x