crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

5 страниц V  < 1 2 3 4 > »   
Ответить в данную темуНачать новую тему
> Дополнительный виджет, Плоттер
++Norton++
  опции профиля:
сообщение 5.3.2009, 12:21
Сообщение #11


Студент
*

Группа: Участник
Сообщений: 98
Регистрация: 5.10.2008
Пользователь №: 380

Спасибо сказали: 0 раз(а)




Репутация:   1  


Спасибо, все понятно кроме некоторых деталей:
1) Виджет graphWidget - это имеется ввиду GraphicsView? Или я что-то путаю?
2) На втором листинге исходник PlotSettings.cpp, правильно?

Сообщение отредактировал ++Norton++ - 5.3.2009, 12:22
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.3.2009, 12:32
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(++Norton++ @ 5.3.2009, 12:21) *
Спасибо, все понятно кроме некоторых деталей:
1) Виджет graphWidget - это имеется ввиду GraphicsView? Или я что-то путаю?
2) На втором листинге исходник PlotSettings.cpp, правильно?

1) Нет. Зачем же? :) Обычный QWidget!
2) Да.

Продолжим. :)
Вот так приблизительно будет выглядеть исходники основного окна:
#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);
}


В итоге должна появиться сетка графика. В данном случае выглядеть будет так:
[attachment=472:graphic.JPG]


Позже расскажу про масштабирование и попробуем построить простейший график (y(x) = x)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
++Norton++
  опции профиля:
сообщение 5.3.2009, 12:47
Сообщение #13


Студент
*

Группа: Участник
Сообщений: 98
Регистрация: 5.10.2008
Пользователь №: 380

Спасибо сказали: 0 раз(а)




Репутация:   1  


Вопрос, конечно ламерский, но все же :blush: А как можно в QWidget добавить еще один QWidget? (если имеет значение где делаю, то нужно сразу написать, что делаю все в QtCreator'е, хотя если нужно все делать в Designer'e могу и в нем).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.3.2009, 12:55
Сообщение #14


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Пофигу где. Главное, чтобы ты смог открыть окно, аналогичное дизайнеру. Итак, открываешь окно дизайнер, в нем появляется нужная форма (виджет), в него и вставляешь еще один виджет. Затем нажимаешь на основной виджет, правая клавиша мыши - Lay Out -> Lay Out in Grid. Ну так можно, например.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
++Norton++
  опции профиля:
сообщение 5.3.2009, 13:05
Сообщение #15


Студент
*

Группа: Участник
Сообщений: 98
Регистрация: 5.10.2008
Пользователь №: 380

Спасибо сказали: 0 раз(а)




Репутация:   1  


Цитата(AD @ 5.3.2009, 13:55) *
нужная форма (виджет), в него и вставляешь еще один виджет.

Вот как раз в этом то и проблема :) Каким образом его вставить? Открываю окно дизайнера, с левой стороны виджеты все стандартные (ListWidget, ListView и т.д.) и нигде QWidget просто нет. Знаю, что наверное туплю, но никак найти не могу :(
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.3.2009, 13:19
Сообщение #16


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


[attachment=473:disainer.JPG]

Обведенный в овальчик!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
++Norton++
  опции профиля:
сообщение 6.3.2009, 11:15
Сообщение #17


Студент
*

Группа: Участник
Сообщений: 98
Регистрация: 5.10.2008
Пользователь №: 380

Спасибо сказали: 0 раз(а)




Репутация:   1  


Огромное спасибо! Отлично, все получилось!
Если можно, теперь, как строить графики и про масштабирование :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
++Norton++
  опции профиля:
сообщение 7.3.2009, 11:02
Сообщение #18


Студент
*

Группа: Участник
Сообщений: 98
Регистрация: 5.10.2008
Пользователь №: 380

Спасибо сказали: 0 раз(а)




Репутация:   1  


И всетаки, как же строить графики? :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 7.3.2009, 13:11
Сообщение #19


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(++Norton++ @ 7.3.2009, 11:02) *
И всетаки, как же строить графики? :)

Сегодня вечером. Впринципе, уже практически все есть. Вечером покажу!

Вот сделал масштабирование. И нажатие на некоторые кнопки:
+ - масштаб +
- - масштаб -
ALT+X - выход
ALT+Enter - показ на весь экран (и обратно).
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(); }
};


Source
#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();
    }
}


Сообщение отредактировал AD - 7.3.2009, 14:53
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 7.3.2009, 14:00
Сообщение #20


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Добавить в класс 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);
}


А затем в paintEvent() добавить следующее:
drawCurves(&painter);


В конструкторе добавить:
initCurves();


Вуаля. График нарисован. Все сделано! :))))
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

5 страниц V  < 1 2 3 4 > » 
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.11.2024, 18:54