Столкнулся с такой проблемой, нужно написать программу, которая будет строить определенный график, но в Qt не нашел виджета-плоттера.
Подскажите пожалуйста, есть ли какая-нибудь возможность решить эту проблему? Как отобразить график? Может есть какие-нибудь дополнительные виджеты?
Это? http://qwt.sourceforge.net/class_qwt_plot.html
SABROG, спасибо, пробовал, скачивал, только не получилось его в QtDesigner добавить
AD, отлично, с удовольствием хотел бы попробовать, буду очень благодарен за помощь!
Конечно, все отлично, буду ждать!
++Norton++, про Qwt есть отдельная тема, почитай там было обсуждение проблем со сборкой.
Я тоже свой виджет для построения графиков делал
Первое. Желательно создать новый проект. Основной класс GraphicWidget, для простоты, лучше унаследовать от QWidget! Затем добавить в этот виджет еще один виджет graphWidget и сделать компоновку с помощью QGridLayout!
Далее, следует добавить новые PlotSettings.cpp и PlotSettings.h файлы.
h-файл будет выглядеть так:
#ifndef PLOTSETTINGS_H
#define PLOTSETTINGS_H
#include <QPointF>
#include <cmath>
/// Абстрактный класс для задания диапазона значений по осям x и y
class PlotSettings
{
public:
double minX; ///< минимальное значение по оси абсцисс
double maxX; ///< максимальное значение по оси абсцисс
int numXTicks; ///< количество делений на оси абсцисс
double minY; ///< минимальное значение по оси ординат
double maxY; ///< максимальное значение по оси ординат
int numYTicks; ///< количество делений на оси ординат
protected:
void adjustAxis(double& min, double& max, int& numTicks);
public:
PlotSettings();
void scroll(double dx, double dy);
void scale(double delta_x, double delta_y);
void adjust();
void adjust(QPointF& point);
double spanX() const { return fabs(maxX - minX); }
double spanY() const { return fabs(maxY - minY); }
};
#endif
PlotSettings::PlotSettings(): minX(-50.), minY(-4.), maxX(50.), maxY(45.)
{
numXTicks = 8;
numYTicks = 8;
}
/// Увеличение/уменьшение значения minX, maxX, minY, maxY на интервал между 2-мя отметками
void PlotSettings::scroll(double dx, double dy)
{
double stepX = spanX() / numXTicks;
minX += dx * stepX;
maxX += dx * stepX;
double stepY = spanY() / numYTicks;
minY += dy * stepY;
maxY += dy * stepY;
adjust();
}
/// Увеличение/уменьшение значения minX, maxX, minY, maxY на интервал между 2-мя отметками
void PlotSettings::scale(double delta_x, double delta_y)
{
if((minX == maxX || minY == maxY) && delta_x < 0 && delta_y < 0) return;
double stepX = spanX() / numXTicks;
minX -= delta_x * stepX;
maxX += delta_x * stepX;
double stepY = spanY() / numYTicks;
minY -= delta_y * stepY;
maxY += delta_y * stepY;
}
/// Округление значений minX, minY, maxX, maxY
void PlotSettings::adjust()
{
adjustAxis(minX, maxX, numXTicks);
adjustAxis(minY, maxY, numYTicks);
}
/// Округление значений заданной точки point
void PlotSettings::adjust(QPointF& point)
{
double mn_x = minX, mn_y = minY;
int ticks_x = numXTicks, ticks_y = numYTicks;
double mx_x = point.x(), mx_y = point.y();
adjustAxis(mn_x, mx_x, ticks_x);
adjustAxis(mn_y, mx_y, ticks_y);
point.setX(mx_x);
point.setY(mx_y);
}
/// Преобразование параметров в удобные значения
void PlotSettings::adjustAxis(double& min, double& max, int& numTicks)
{
const int MinTicks = 5;
double grossStep = (max - min) / MinTicks;
double step = pow(10.0, floor(log10(grossStep)));
if(5 * step < grossStep)
step *= 5;
else if(2 * step < grossStep)
step *= 2;
numTicks = int(ceil(max / step) - floor(min / step));
if(numTicks < MinTicks)
numTicks = MinTicks;
min = floor(min / step) * step;
max = ceil(max / step) * step;
}
Спасибо, все понятно кроме некоторых деталей:
1) Виджет graphWidget - это имеется ввиду GraphicsView? Или я что-то путаю?
2) На втором листинге исходник PlotSettings.cpp, правильно?
#ifndef GRAPHICWIDGET_H
#define GRAPHICWIDGET_H
#include "ui_GraphicWidget.h"
#include "PlotSettings.h"
#include <QtGui/QWidget>
class QPaintEvent;
class QPainter;
/// Виджет, где будет отрисовываться график
class GraphicWidget: public QWidget, public Ui::GraphicWidgetClass
{
Q_OBJECT
private:
PlotSettings settings; ///< настройка для различных масштабов
private:
void drawGrid(QPainter *painter);
protected:
void paintEvent(QPaintEvent* event);
public:
GraphicWidget(QWidget *parent = 0, Qt::WFlags flags = 0);
~GraphicWidget();
void setPlotSettings(const PlotSettings& sts) { settings = sts; settings.adjust(); update(); }
};
#endif // GRAPHICWIDGET_H
#include "GraphicWidget.h"
#include <QPainter>
#include <QRect>
#include <QString>
#include <algorithm>
using namespace std;
GraphicWidget::GraphicWidget(QWidget *parent, Qt::WFlags flags): QWidget(parent, flags)
{
setupUi(this);
/// Инициализация необходимых параметров
setPlotSettings(PlotSettings());
}
GraphicWidget::~GraphicWidget()
{}
/// Отрисовка сетки
void GraphicWidget::drawGrid(QPainter *painter)
{
QRect rect(graphWidget -> rect());
if(!rect.isValid()) return;
QRect boundString;
double great_max = max(settings.numXTicks, settings.numYTicks) + 1;
for(register int i=0, j=0, k=0; i<=great_max; ++i, ++j, ++k)
{
if(j <= settings.numXTicks) ///< отрисовка вдоль оси X
{
int x = rect.left() + (j * (rect.width() - 1) / settings.numXTicks);
double label = settings.minX + (j * settings.spanX() / settings.numXTicks);
QString s_label(QString::number(label, 'f', 3));
painter -> setPen(Qt::black);
painter -> drawLine(x, rect.top(), x, rect.bottom());
int flags = Qt::AlignHCenter | Qt::AlignTop;
boundString = painter -> boundingRect(boundString, flags, s_label);
painter -> drawText(x - (boundString.width() + 5), rect.bottom() - (boundString.height() + 5),
boundString.width(), boundString.height(), flags, s_label);
}
if(k <= settings.numYTicks) ///< отрисовка вдоль оси Y
{
int y = rect.bottom() - (k * (rect.height() - 1) / settings.numYTicks);
double label = settings.minY + (k * settings.spanY() / settings.numYTicks);
QString s_label(QString::number(label, 'f', 3));
painter -> setPen(Qt::black);
painter -> drawLine(rect.left(), y, rect.right(), y);
int flags = Qt::AlignRight | Qt::AlignTop;
boundString = painter -> boundingRect(boundString, flags, s_label);
painter -> drawText(rect.left() + 7, y - boundString.height(),
boundString.width(), boundString.height(), flags, s_label);
}
}
painter -> drawRect(rect.adjusted(0, 0, -1, -1));
}
/// Отрисовка графика
void GraphicWidget::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
drawGrid(&painter);
QWidget::paintEvent(event);
}
Вопрос, конечно ламерский, но все же А как можно в QWidget добавить еще один QWidget? (если имеет значение где делаю, то нужно сразу написать, что делаю все в QtCreator'е, хотя если нужно все делать в Designer'e могу и в нем).
Пофигу где. Главное, чтобы ты смог открыть окно, аналогичное дизайнеру. Итак, открываешь окно дизайнер, в нем появляется нужная форма (виджет), в него и вставляешь еще один виджет. Затем нажимаешь на основной виджет, правая клавиша мыши - Lay Out -> Lay Out in Grid. Ну так можно, например.
[attachment=473:disainer.JPG]
Обведенный в овальчик!
Огромное спасибо! Отлично, все получилось!
Если можно, теперь, как строить графики и про масштабирование
И всетаки, как же строить графики?
class QPaintEvent;
class QPainter;
class QRubberBand;
class QKeyEvent;
class QResizeEvent;
class QCloseEvent;
class QShowEvent;
class QWheelEvent;
class QMouseEvent;
/// Виджет, где будет отрисовываться график
class GraphicWidget: public QWidget, public Ui::GraphicWidgetClass
{
Q_OBJECT
private:
PlotSettings settings; ///< настройка для различных масштабов
QRubberBand* rubber; ///< "резиновая лента"
bool rubberBandIsShown; ///< флажок попадания курсора в "резиновую ленту"
QPoint origin; ///< начальные координаты выделяемой области
private:
void drawGrid(QPainter *painter);
protected:
void paintEvent(QPaintEvent* events);
void keyPressEvent(QKeyEvent* events);
void wheelEvent(QWheelEvent* events);
void mousePressEvent(QMouseEvent* events);
void mouseMoveEvent(QMouseEvent* events);
void mouseReleaseEvent(QMouseEvent* events);
void resizeEvent(QResizeEvent* events) { QWidget::resizeEvent(events); update(); }
void closeEvent(QCloseEvent* events) { QWidget::closeEvent(events); }
void showEvent(QShowEvent* events) { QWidget::showEvent(events); }
public:
GraphicWidget(QWidget *parent = 0, Qt::WFlags flags = 0);
~GraphicWidget();
void setPlotSettings(const PlotSettings& sts) { settings = sts; settings.adjust(); update(); }
void zoom(double delta) { settings.scale(delta, delta); settings.adjust(); update(); }
};
#include <QRubberBand>
#include <QKeyEvent>
#include <QWheelEvent>
#include <QMouseEvent>
/// Отрисовка графика
void GraphicWidget::paintEvent(QPaintEvent* events)
{
QPainter painter(this);
drawGrid(&painter);
QWidget::paintEvent(events);
}
/// Нажатие на кнопки клавиатуры
void GraphicWidget::keyPressEvent(QKeyEvent* events)
{
switch(events -> key())
{
case Qt::Key_Plus:
zoom(-1.0);
break;
case Qt::Key_Minus:
zoom(1.0);
break;
case Qt::Key_Left:
settings.scroll(-1.0, 0.0);
update();
break;
case Qt::Key_Right:
settings.scroll(1.0, 0.0);
update();
break;
case Qt::Key_Up:
settings.scroll(0.0, 1.0);
update();
break;
case Qt::Key_Down:
settings.scroll(0.0, -1.0);
update();
break;
case Qt::Key_X:
if(events -> modifiers() & Qt::ALT) close();
break;
case Qt::Key_Return:
if(events -> modifiers() & Qt::ALT)
{
if(!isMaximized()) showMaximized();
else showNormal();
}
break;
default:
QWidget::keyPressEvent(events);
}
}
/// Изменение масштаба при движении колесика
void GraphicWidget::wheelEvent(QWheelEvent* events)
{
int numDegrees = events -> delta() / 8;
double numTicks = numDegrees / 15.0;
zoom(numTicks);
update();
}
/// Нажатие на кнопку - изменение масштаба
void GraphicWidget::mousePressEvent(QMouseEvent* events)
{
QWidget::mousePressEvent(events);
QRect r;
switch(events -> button())
{
case Qt::LeftButton: ///< если нажата левая кнопка мыши
origin = events -> pos();
rubberBandIsShown = true;
setCursor(Qt::CrossCursor);
r = QRect(origin, QSize());
rubber -> setGeometry(r);
rubber -> show();
break;
case Qt::RightButton: ///< если нажата правая кнопка мыши
break;
default:
break;
}
}
/// Переопределение функции передвижения мыши
void GraphicWidget::mouseMoveEvent(QMouseEvent* events)
{
if(rubberBandIsShown)
{
rubber -> setWindowOpacity(0.0);
rubber -> setGeometry(QRect(origin, events -> pos()).normalized());
}
update();
}
/// Возвращение прежнего вида курсору и изменение масштаба
void GraphicWidget::mouseReleaseEvent(QMouseEvent* events)
{
if(events -> button() == Qt::LeftButton && rubberBandIsShown)
{
rubberBandIsShown = false;
unsetCursor();
QRect rect = rubber -> geometry().normalized();
if(rect.width() < 10 || rect.height() < 10)
{
double dx = rect.width() / settings.spanX();
double dy = rect.height() / settings.spanY();
settings.scroll(dx, dy);
update();
return;
}
PlotSettings prevSettings = settings;
double dx = prevSettings.spanX() / width();
double dy = prevSettings.spanY() / height();
settings.minX = prevSettings.minX + dx * rect.left();
settings.maxX = prevSettings.minX + dx * rect.right();
settings.minY = prevSettings.maxY - dy * rect.bottom();
settings.maxY = prevSettings.maxY - dy * rect.top();
settings.adjust();
rubber -> hide();
update();
}
}
Добавить в класс 3 функции:
private:
void drawCurves(QPainter* painter);
QPointF initXY(double sx, double sy);
void initCurves();
/// Заполнения вектора с кривой (кривая y(x) = x)
void GraphicWidget::initCurves()
{
curve_vec.append(QPointF(-100., -100.));
curve_vec.append(QPointF(-10., -10.));
curve_vec.append(QPointF(-1., -1.));
curve_vec.append(QPointF(0., 0.));
curve_vec.append(QPointF(1., 1.));
curve_vec.append(QPointF(1.5, 1.5));
curve_vec.append(QPointF(5., 5.));
curve_vec.append(QPointF(10., 10.));
curve_vec.append(QPointF(100., 100.));
}
/// Инициализация координат - преобразование из координат графика (sx,sy) в экранные (x,y)
QPointF GraphicWidget::initXY(double sx, double sy)
{
QRect rect(graphWidget -> rect());
double dx, dy;
/// Вычисление смещений вдоль осей
dx = sx - settings.maxX;
dy = sy - settings.minY;
/// Вычисление экранных координат
double x = rect.right() + (dx * (rect.width() - 1) / settings.spanX());
double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY());
return QPointF(x, y);
}
/// Отрисовка графика
void GraphicWidget::drawCurves(QPainter* painter)
{
painter -> setPen(Qt::blue);
QPolygonF polyline(curve_vec.size());
for(register int i=0; i<curve_vec.size(); ++i)
polyline[i] = initXY(curve_vec[i].x(), curve_vec[i].y());
painter -> drawPolyline(polyline);
}
drawCurves(&painter);
initCurves();
Напоминает пример из книжки Жасмин Бланшет
AD, Оборачивай длинные портянки кода в тэг http://www.forum.crossplatform.ru/index.php?showtopic=1455
Вроде все сделал так, но при компиляции выдается ошибка :
graphicwidget.cpp:200: error: 'curve_vec' was not declared in this scope
graphicwidget.cpp:200: error: 'curve_vec' was not declared in this scope
private:
QVector<QPointF> curve_vec;
Огромнейшее спасибо! Теперь все отлично работает!
А на счет подучить C++ и вправду надо Просто не так давно занимаюсь программированием на C++
Да, хотел только еще один вопрос задать...
Когда нажимаю левой кнопкой мыши на график, программа прекращает свою работу (закрывается). Вроде бы так не должно быть?
GraphicWidget::GraphicWidget(QWidget *parent, Qt::WFlags flags): QWidget(parent, flags), rubberBandIsShown(false),
rubber(new QRubberBand(QRubberBand::Rectangle, this))
{
setupUi(this);
setPlotSettings(PlotSettings());
initCurves();
}
Спасибо! Теперь все работает! Только лента не вырисовывается, а так масштабирование проходит нормально
а подскажите по этому примеру в чём косяк. при добавлении GraphicWidget.h при сборке вылазит ошибка "GraphicWidget.h:39: ошибка: expected class-name before ‘{’ token" указывает на скобку перед объявлением Q_Object . но она вроде как там корректно стоит. в чём косяк??
class GraphicWidget: public QWidget, public Ui::GraphicWidgetClass
{
Q_OBJECT
private:
PlotSettings settings; ///< настройка для различных масштабов
void drawGrid(QPainter *painter);
protected:
void paintEvent(QPaintEvent* event);
public:
GraphicWidget(QWidget *parent = 0, Qt::WFlags flags = 0);
~GraphicWidget();
void setPlotSettings(const PlotSettings& sts) { settings = sts; settings.adjust(); update(); }
};
обычно такая хрень идет по двум причинам:
1. чет не то компилятор наделал, сделай полный ребилд
2. с инклюдами что-то не то (например "зацикливание")
Думаю, что ребилд должен помочь!
Ну... решил выложить еще раз решение. ПОЛНОСТЬЮ!
#ifndef PLOTSETTINGS_H
#define PLOTSETTINGS_H
#include <QPointF>
#include <cmath>
/// Àáñòðàêòíûé êëàññ äëÿ çàäàíèÿ äèàïàçîíà çíà÷åíèé ïî îñÿì x è y
class PlotSettings
{
public:
double minX; ///< ìèíèìàëüíîå çíà÷åíèå ïî îñè àáñöèññ
double maxX; ///< ìàêñèìàëüíîå çíà÷åíèå ïî îñè àáñöèññ
int numXTicks; ///< êîëè÷åñòâî äåëåíèé íà îñè àáñöèññ
double minY; ///< ìèíèìàëüíîå çíà÷åíèå ïî îñè îðäèíàò
double maxY; ///< ìàêñèìàëüíîå çíà÷åíèå ïî îñè îðäèíàò
int numYTicks; ///< êîëè÷åñòâî äåëåíèé íà îñè îðäèíàò
protected:
void adjustAxis(double& min, double& max, int& numTicks);
public:
PlotSettings();
void scroll(double dx, double dy);
void scale(double delta_x, double delta_y);
void adjust();
void adjust(QPointF& point);
double spanX() const { return fabs(maxX - minX); }
double spanY() const { return fabs(maxY - minY); }
};
#endif
#include "PlotSettings.h"
PlotSettings::PlotSettings(): minX(-50.), minY(-4.), maxX(50.), maxY(45.)
{
numXTicks = 8;
numYTicks = 8;
}
/// Óâåëè÷åíèå/óìåíüøåíèå çíà÷åíèÿ minX, maxX, minY, maxY íà èíòåðâàë ìåæäó 2-ìÿ îòìåòêàìè
void PlotSettings::scroll(double dx, double dy)
{
double stepX = spanX() / numXTicks;
minX += dx * stepX;
maxX += dx * stepX;
double stepY = spanY() / numYTicks;
minY += dy * stepY;
maxY += dy * stepY;
adjust();
}
/// Óâåëè÷åíèå/óìåíüøåíèå çíà÷åíèÿ minX, maxX, minY, maxY íà èíòåðâàë ìåæäó 2-ìÿ îòìåòêàìè
void PlotSettings::scale(double delta_x, double delta_y)
{
if((minX == maxX || minY == maxY) && delta_x < 0 && delta_y < 0) return;
double stepX = spanX() / numXTicks;
minX -= delta_x * stepX;
maxX += delta_x * stepX;
double stepY = spanY() / numYTicks;
minY -= delta_y * stepY;
maxY += delta_y * stepY;
}
/// Îêðóãëåíèå çíà÷åíèé minX, minY, maxX, maxY
void PlotSettings::adjust()
{
adjustAxis(minX, maxX, numXTicks);
adjustAxis(minY, maxY, numYTicks);
}
/// Îêðóãëåíèå çíà÷åíèé çàäàííîé òî÷êè point
void PlotSettings::adjust(QPointF& point)
{
double mn_x = minX, mn_y = minY;
int ticks_x = numXTicks, ticks_y = numYTicks;
double mx_x = point.x(), mx_y = point.y();
adjustAxis(mn_x, mx_x, ticks_x);
adjustAxis(mn_y, mx_y, ticks_y);
point.setX(mx_x);
point.setY(mx_y);
}
/// Ïðåîáðàçîâàíèå ïàðàìåòðîâ â óäîáíûå çíà÷åíèÿ
void PlotSettings::adjustAxis(double& min, double& max, int& numTicks)
{
const int MinTicks = 5;
double grossStep = (max - min) / MinTicks;
double step = pow(10.0, floor(log10(grossStep)));
if(5 * step < grossStep)
step *= 5;
else if(2 * step < grossStep)
step *= 2;
numTicks = int(ceil(max / step) - floor(min / step));
if(numTicks < MinTicks)
numTicks = MinTicks;
min = floor(min / step) * step;
max = ceil(max / step) * step;
}
#ifndef GRAPHICWIDGET_H
#define GRAPHICWIDGET_H
#include "ui_GraphicWidget.h"
#include "PlotSettings.h"
#include <QtGui/QWidget>
#include <QPoint>
class QPaintEvent;
class QPainter;
class QRubberBand;
class QKeyEvent;
class QResizeEvent;
class QCloseEvent;
class QShowEvent;
class QWheelEvent;
class QMouseEvent;
/// Âèäæåò, ãäå áóäåò îòðèñîâûâàòüñÿ ãðàôèê
class GraphicWidget: public QWidget, public Ui::GraphicWidgetClass
{
Q_OBJECT
private:
PlotSettings settings; ///< íàñòðîéêà äëÿ ðàçëè÷íûõ ìàñøòàáîâ
QRubberBand* rubber; ///< "ðåçèíîâàÿ ëåíòà"
bool rubberBandIsShown; ///< ôëàæîê ïîïàäàíèÿ êóðñîðà â "ðåçèíîâóþ ëåíòó"
QPoint origin; ///< íà÷àëüíûå êîîðäèíàòû âûäåëÿåìîé îáëàñòè
QVector<QPointF> curve_vec; ///< âåêòîð òî÷åê êðèâîé
private:
void drawGrid(QPainter *painter);
void drawCurves(QPainter* painter);
QPointF initXY(double sx, double sy);
void initCurves();
protected:
void paintEvent(QPaintEvent* events);
void keyPressEvent(QKeyEvent* events);
void wheelEvent(QWheelEvent* events);
void mousePressEvent(QMouseEvent* events);
void mouseMoveEvent(QMouseEvent* events);
void mouseReleaseEvent(QMouseEvent* events);
void resizeEvent(QResizeEvent* events) { QWidget::resizeEvent(events); update(); }
void closeEvent(QCloseEvent* events) { QWidget::closeEvent(events); }
void showEvent(QShowEvent* events) { QWidget::showEvent(events); }
public:
GraphicWidget(QWidget *parent = 0, Qt::WFlags flags = 0);
~GraphicWidget();
void setPlotSettings(const PlotSettings& sts) { settings = sts; settings.adjust(); update(); }
void zoom(double delta) { settings.scale(delta, delta); settings.adjust(); update(); }
};
#endif // GRAPHICWIDGET_H
#include "GraphicWidget.h"
#include <QPainter>
#include <QRect>
#include <QString>
#include <QRubberBand>
#include <QKeyEvent>
#include <QWheelEvent>
#include <QMouseEvent>
#include <algorithm>
using namespace std;
GraphicWidget::GraphicWidget(QWidget *parent, Qt::WFlags flags): QWidget(parent, flags), rubberBandIsShown(false),
rubber(new QRubberBand(QRubberBand::Rectangle, this))
{
setupUi(this);
/// Èíèöèàëèçàöèÿ íåîáõîäèìûõ ïàðàìåòðîâ
setPlotSettings(PlotSettings());
initCurves();
}
GraphicWidget::~GraphicWidget()
{}
/// Çàïîëíåíèÿ âåêòîðà ñ êðèâîé (êðèâàÿ y(x) = x)
void GraphicWidget::initCurves()
{
curve_vec.append(QPointF(-100., -100.));
curve_vec.append(QPointF(-10., -10.));
curve_vec.append(QPointF(-1., -1.));
curve_vec.append(QPointF(0., 0.));
curve_vec.append(QPointF(1., 1.));
curve_vec.append(QPointF(1.5, 1.5));
curve_vec.append(QPointF(5., 5.));
curve_vec.append(QPointF(10., 10.));
curve_vec.append(QPointF(100., 100.));
}
/// Îòðèñîâêà ñåòêè
void GraphicWidget::drawGrid(QPainter *painter)
{
QRect rect(graphWidget -> rect());
if(!rect.isValid()) return;
QRect boundString;
double great_max = max(settings.numXTicks, settings.numYTicks) + 1;
for(register int i=0, j=0, k=0; i<=great_max; ++i, ++j, ++k)
{
if(j <= settings.numXTicks) ///< îòðèñîâêà âäîëü îñè X
{
int x = rect.left() + (j * (rect.width() - 1) / settings.numXTicks);
double label = settings.minX + (j * settings.spanX() / settings.numXTicks);
QString s_label(QString::number(label, 'f', 3));
painter -> setPen(Qt::black);
painter -> drawLine(x, rect.top(), x, rect.bottom());
int flags = Qt::AlignHCenter | Qt::AlignTop;
boundString = painter -> boundingRect(boundString, flags, s_label);
painter -> drawText(x - (boundString.width() + 5), rect.bottom() - (boundString.height() + 5),
boundString.width(), boundString.height(), flags, s_label);
}
if(k <= settings.numYTicks) ///< îòðèñîâêà âäîëü îñè Y
{
int y = rect.bottom() - (k * (rect.height() - 1) / settings.numYTicks);
double label = settings.minY + (k * settings.spanY() / settings.numYTicks);
QString s_label(QString::number(label, 'f', 3));
painter -> setPen(Qt::black);
painter -> drawLine(rect.left(), y, rect.right(), y);
int flags = Qt::AlignRight | Qt::AlignTop;
boundString = painter -> boundingRect(boundString, flags, s_label);
painter -> drawText(rect.left() + 7, y - boundString.height(),
boundString.width(), boundString.height(), flags, s_label);
}
}
painter -> drawRect(rect.adjusted(0, 0, -1, -1));
}
/// Èíèöèàëèçàöèÿ êîîðäèíàò - ïðåîáðàçîâàíèå èç êîîðäèíàò ãðàôèêà (sx,sy) â ýêðàííûå (x,y)
QPointF GraphicWidget::initXY(double sx, double sy)
{
QRect rect(graphWidget -> rect());
double dx, dy;
/// Âû÷èñëåíèå ñìåùåíèé âäîëü îñåé
dx = sx - settings.maxX;
dy = sy - settings.minY;
/// Âû÷èñëåíèå ýêðàííûõ êîîðäèíàò
double x = rect.right() + (dx * (rect.width() - 1) / settings.spanX());
double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY());
return QPointF(x, y);
}
/// Îòðèñîâêà ãðàôèêà
void GraphicWidget::drawCurves(QPainter* painter)
{
painter -> setPen(Qt::blue);
QPolygonF polyline(curve_vec.size());
for(register int i=0; i<curve_vec.size(); ++i)
polyline[i] = initXY(curve_vec[i].x(), curve_vec[i].y());
painter -> drawPolyline(polyline);
}
/// Îòðèñîâêà ãðàôèêà
void GraphicWidget::paintEvent(QPaintEvent* events)
{
QPainter painter(this);
drawGrid(&painter);
drawCurves(&painter);
QWidget::paintEvent(events);
}
/// Íàæàòèå íà êíîïêè êëàâèàòóðû
void GraphicWidget::keyPressEvent(QKeyEvent* events)
{
switch(events -> key())
{
case Qt::Key_Plus:
zoom(-1.0);
break;
case Qt::Key_Minus:
zoom(1.0);
break;
case Qt::Key_Left:
settings.scroll(-1.0, 0.0);
update();
break;
case Qt::Key_Right:
settings.scroll(1.0, 0.0);
update();
break;
case Qt::Key_Up:
settings.scroll(0.0, 1.0);
update();
break;
case Qt::Key_Down:
settings.scroll(0.0, -1.0);
update();
break;
case Qt::Key_X:
if(events -> modifiers() & Qt::ALT) close();
break;
case Qt::Key_Return:
if(events -> modifiers() & Qt::ALT)
{
if(!isMaximized()) showMaximized();
else showNormal();
}
break;
default:
QWidget::keyPressEvent(events);
}
}
/// Èçìåíåíèå ìàñøòàáà ïðè äâèæåíèè êîëåñèêà
void GraphicWidget::wheelEvent(QWheelEvent* events)
{
int numDegrees = events -> delta() / 8;
double numTicks = numDegrees / 15.0;
zoom(numTicks);
update();
}
/// Íàæàòèå íà êíîïêó - èçìåíåíèå ìàñøòàáà
void GraphicWidget::mousePressEvent(QMouseEvent* events)
{
QWidget::mousePressEvent(events);
QRect r;
switch(events -> button())
{
case Qt::LeftButton: ///< åñëè íàæàòà ëåâàÿ êíîïêà ìûøè
origin = events -> pos();
rubberBandIsShown = true;
setCursor(Qt::CrossCursor);
r = QRect(origin, QSize());
rubber -> setGeometry(r);
rubber -> show();
break;
case Qt::RightButton: ///< åñëè íàæàòà ïðàâàÿ êíîïêà ìûøè
break;
default:
break;
}
}
/// Ïåðåîïðåäåëåíèå ôóíêöèè ïåðåäâèæåíèÿ ìûøè
void GraphicWidget::mouseMoveEvent(QMouseEvent* events)
{
if(rubberBandIsShown)
{
rubber -> setWindowOpacity(0.0);
rubber -> setGeometry(QRect(origin, events -> pos()).normalized());
}
update();
}
/// Âîçâðàùåíèå ïðåæíåãî âèäà êóðñîðó è èçìåíåíèå ìàñøòàáà
void GraphicWidget::mouseReleaseEvent(QMouseEvent* events)
{
if(events -> button() == Qt::LeftButton && rubberBandIsShown)
{
rubberBandIsShown = false;
unsetCursor();
QRect rect = rubber -> geometry().normalized();
if(rect.width() < 10 || rect.height() < 10)
{
double dx = rect.width() / settings.spanX();
double dy = rect.height() / settings.spanY();
settings.scroll(dx, dy);
update();
return;
}
PlotSettings prevSettings = settings;
double dx = prevSettings.spanX() / width();
double dy = prevSettings.spanY() / height();
settings.minX = prevSettings.minX + dx * rect.left();
settings.maxX = prevSettings.minX + dx * rect.right();
settings.minY = prevSettings.maxY - dy * rect.bottom();
settings.maxY = prevSettings.maxY - dy * rect.top();
settings.adjust();
rubber -> hide();
update();
}
}
AD, чёто с русскими коментариями бяка какая-то
rubber(new QRubberBand(QRubberBand::Rectangle, this))
rubber(new QRubberBand(QRubberBand::Rectangle, parent))
Уважаемые, поясните пожалуйста что за файл подключается, ui_GraphicWidget.h, и откуда он должен взяться? (ругается на него компилятор)
ошибка:fatal error C1083: Cannot open include file: 'ui_GraphicWidget.h': No such file or directory
/********************************************************************************
** Form generated from reading ui file 'GraphicWidget.ui'
**
** Created: Thu 5. Mar 12:26:58 2009
** by: Qt User Interface Compiler version 4.3.2
**
** WARNING! All changes made in this file will be lost when recompiling ui file!
********************************************************************************/
#ifndef UI_GRAPHICWIDGET_H
#define UI_GRAPHICWIDGET_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QGridLayout>
#include <QtGui/QWidget>
class Ui_GraphicWidgetClass
{
public:
QGridLayout *gridLayout;
QWidget *graphWidget;
void setupUi(QWidget *GraphicWidgetClass)
{
if (GraphicWidgetClass->objectName().isEmpty())
GraphicWidgetClass->setObjectName(QString::fromUtf8("GraphicWidgetClass"));
GraphicWidgetClass->resize(600, 400);
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(GraphicWidgetClass->sizePolicy().hasHeightForWidth());
GraphicWidgetClass->setSizePolicy(sizePolicy);
gridLayout = new QGridLayout(GraphicWidgetClass);
gridLayout->setSpacing(6);
gridLayout->setMargin(11);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
gridLayout->setHorizontalSpacing(1);
gridLayout->setVerticalSpacing(3);
gridLayout->setContentsMargins(3, 3, 1, 3);
graphWidget = new QWidget(GraphicWidgetClass);
graphWidget->setObjectName(QString::fromUtf8("graphWidget"));
sizePolicy.setHeightForWidth(graphWidget->sizePolicy().hasHeightForWidth());
graphWidget->setSizePolicy(sizePolicy);
gridLayout->addWidget(graphWidget, 0, 0, 1, 1);
retranslateUi(GraphicWidgetClass);
QMetaObject::connectSlotsByName(GraphicWidgetClass);
} // setupUi
void retranslateUi(QWidget *GraphicWidgetClass)
{
GraphicWidgetClass->setWindowTitle(QApplication::translate("GraphicWidgetClass", "GraphicWidget", 0, QApplication::UnicodeUTF8));
Q_UNUSED(GraphicWidgetClass);
} // retranslateUi
};
namespace Ui {
class GraphicWidgetClass: public Ui_GraphicWidgetClass {};
} // namespace Ui
#endif // UI_GRAPHICWIDGET_H
AD, ++Norton++, выложите пожалуйста папку с прогой полностью если сохранилось у кого-нить?
class Ui_GraphicWidget
class Ui_GraphicWidgetClass
/// Инициализация координат - преобразование из координат графика (sx,sy) в экранные (x,y)
QPointF GraphicWidget::initXY(double sx, double sy)
{
QRect rect(graphWidget -> rect());
double dx, dy;
/// Вычисление смещений вдоль осей
dx = sx - settings.maxX;
dy = sy - settings.minY;
/// Вычисление экранных координат
double x = rect.right() + (dx * (rect.width() - 1) / settings.spanX());
double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY());
return QPointF(x, y);
}
dx = sx - settings.minX;
dy = sy - settings.minY;
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)