crossplatform.ru

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


  Ответ в Масштабирование с помощью колесика мышки
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
ViGOur Дата 11.7.2008, 13:06
 
Цитата(AD @ 11.7.2008, 13:04) *
Может упорства?
И его тоже. ;)
AD Дата 11.7.2008, 12:04
 
Цитата(ViGOur @ 11.7.2008, 12:54) *
Молодец, осилил наконец. :)

Упрямства тебе не занимать, так держать!

Может упорства? ;) :blush2:
ViGOur Дата 11.7.2008, 11:54
  Молодец, осилил наконец. :)

Упрямства тебе не занимать, так держать!
AD Дата 11.7.2008, 11:50
  Век живи, век учись! Вот так выглядит код, который заставляет правильно работать масштабирование: :)
class PlotSettings
{
public:
    double minX;
    double maxX;
    int numXTicks;
    double minY;
    double maxY;
    int numYTicks;

protected:
    static void adjustAxis(double& min, double& max, int& numTicks);

public:
    PlotSettings();
    void scroll(int dx, int dy);
    void scale(double delta_x, double delta_y);
    void adjust();
    double spanX() const { return fabs(maxX - minX); }
    double spanY() const { return fabs(maxY - minY); }
};


/// Увеличение/уменьшение значения 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;
}



/// Класс для отображения параметров по времени или по расстоянию
class GraphicDisplay : public QDialog, public Ui::GraphicDisplayClass
{
    Q_OBJECT

private:
    QMap<int, QVector<QPointF>> curveMap;       ///< список всех изображаемых кривых
    ParamPlotSettings settings;                    ///< настройка для определения масштаба
    QRubberBand* rubber;                        ///< "резиновая лента"
    QPoint origin;                                ///< начальные координаты выделяемой области
    bool rubberBandIsShown;                        ///< флажок попадания курсора в "резиновую ленту"
    QPen myPen;                                    ///< карандаш для рисования линий определенной жирности и цвета
    enum { MARGIN = 10 };

    QPainter painter;                            ///< рисовальщик
    QVector<QPointF> data;                        ///< вектор загружаемой кривой

private:
    void drawGrid(QPainter* painter);
    void drawCurves(QPainter* painter);
    void drawLegend(QPainter* painter, QRect& rect, int& k, int id);
    QPointF initXY(double& sx, double& sy);

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) { QDialog::resizeEvent(events); update(); }
    void closeEvent(QCloseEvent* events) { QDialog::closeEvent(events); }
    void showEvent(QShowEvent* events) { QDialog::showEvent(events); }

public:
    GraphicDisplay(QWidget *parent = 0);
    GraphicDisplay(QWidget *parent, ParamPlotSettings& st);
    ~GraphicDisplay();
    void zoom(double delta) { settings.scale(delta, delta); settings.adjust(); update(); }
    void setPlotSettings(const ParamPlotSettings& sts) { settings = sts; settings.adjust(); update(); }


/// Изменение масштаба при движении колесика
void GraphicDisplay::wheelEvent(QWheelEvent* events)
{
    int numDegrees = events -> delta() / 8;
    double numTicks = numDegrees / 15.0;

    zoom(numTicks);
    update();
}

/// Нажатие на кнопки клавиатуры
void GraphicDisplay::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);
        update();
    break;
    case Qt::Key_Right:
        settings.scroll(1, 0);
        update();
    break;
    case Qt::Key_Up:
        settings.scroll(0, 1);
        update();
    break;
    case Qt::Key_Down:
        settings.scroll(0, -1);
        update();
    break;
    default:
        QWidget::keyPressEvent(events);
    }
}

/// Отрисовка сетки
void GraphicDisplay::drawGrid(QPainter* painter)
{
    QRect rect(paramsDisplay -> rect());
    if(!rect.isValid()) return;
    
    QRect boundString;
    int _max = max(settings.numXTicks, settings.numYTicks);
    for(int i=0, j=0, k=0; i<=_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 = round(label);

            painter -> setPen(Qt::black);
            painter -> drawLine(x, rect.top(), x, rect.bottom());
            if(j != settings.numXTicks)
            {
                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 = round(label);

            painter -> setPen(Qt::black);
            painter -> drawLine(rect.left(), y, rect.right(), y);
            if(k != settings.numYTicks)
            {
                int flags = Qt::AlignRight | Qt::AlignTop;
                boundString = painter -> boundingRect(boundString, flags, s_label);
                painter -> drawText(rect.left() + 5, y - boundString.height(),
                            boundString.width(), boundString.height(), flags, s_label);
            }
        }
    }
    painter -> drawRect(rect.adjusted(0, 0, -1, -1));
}

/// Отрисовка легенды
void GraphicDisplay::drawLegend(QPainter* painter, QRect& rect, int& k, int id)
{
    QString pname = fact_prm[id].param_name;
    QString dimension = fact_prm[id].dimension;
    myPen.setWidth(1);
    painter -> drawLine(QLineF(QPointF(rect.right()  - 45, rect.top() + 25 * k),
                               QPointF(rect.right()  - 65, rect.top() + 25 * k)));
    painter -> setPen(Qt::black);
    int flags = Qt::AlignCenter;
    QRect boundString = painter -> boundingRect(boundString, flags, pname);
    painter -> drawText(QPointF(rect.right() - (boundString.width() + 7), rect.top() + 25 * k), pname);
    boundString = painter -> boundingRect(boundString, flags, dimension);
    painter -> drawText(QPointF(rect.right() - (boundString.width() + 7),
                        rect.bottom() - 2 * boundString.height()), dimension);
    ++k;
}

/// Инициализация координат
QPointF GraphicDisplay::initXY(double& sx, double& sy)
{
    QRect rect(paramsDisplay -> rect());
    double dx, dy;
    dx = sx - settings.minX;
    dy = sy - settings.minY;
    double x = rect.left() + (dx * (rect.width() - 1) / settings.spanX());;
    double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY());

    return QPointF(x, y);
}

/// Отрисовка графика
void GraphicDisplay::drawCurves(QPainter* painter)
{
    QRect rect(paramsDisplay -> rect());
    if(!rect.isValid())    return;

    painter -> setClipRect(rect.adjusted(1, 1, -1, -1));
    QMapIterator<int, QVector<QPointF>> iter(curveMap);
    int k = 1;
    while(iter.hasNext())
    {
        iter.next();

        int id = iter.key();
        TP_PARAM ty = fact_prm[id].type;
        if(settings.win_type != ty) continue;

        const QVector<QPointF> &data = iter.value();
        QPolygonF polyline(data.count());
        for(int j=0; j<data.count(); ++j)
        {
            double x = data[j].x();
            double y = data[j].y();
            polyline[j] = initXY(x, y);
        }
        QString color = fact_prm[id].param_color.name();
        QPen oldPen = painter -> pen();
        myPen.setColor(fact_prm[id].param_color);
        painter -> setPen(myPen);
        painter -> drawPolyline(polyline);
        int width = myPen.width();
        
        drawLegend(painter, rect, k, id);

        painter -> setPen(oldPen);
    }
}


Практически месяц я парился с этим - но в итоге решение проблемы есть! УРА, уряяяяяяяяяя...
Можете поздравить! :))))
AD Дата 9.7.2008, 15:40
  Вот так вот :) Искал пример использования двоичных файлов, а натолкнулся на пример, который может помочь решить проблему масштабироваиия! :)
%QTDIR%examples\threads\mandelbrot
Red Devil Дата 30.6.2008, 11:16
  Нарисуй все на бумаге, напиши формулы, выложи их здесь. Я именно так и делал, когда решал аналогичную задачу, но с использованием другой библиотеки.
Исходный код тут не поможет.
AD Дата 30.6.2008, 10:22
  Это опять я. Короче, проблема пока еще не решена. Сделаны кое-какие существенные изменения в приведенном выше коде. Если кто-то сможет помочь в решении, то могу их выложить. Заранее спасибо!
AD Дата 18.6.2008, 10:12
  Можно задавать маленькие конкретные вопросы? Возможно, походу пойму, где ошибка.
Вот функция, которую я использую для масштаба.

/// Увеличение/уменьшение значения minX, maxX, minY, maxY на интервал между 2-мя отметками
void PlotSettings::scroll(double mn_dx, double mn_dy, double mx_dx, double mx_dy)
{
    double stepX = spanX() / numXTicks;
    minX += mn_dx * stepX;
    maxX += mx_dx * stepX;

    double stepY = spanY() / numYTicks;
    minY += mn_dy * stepY;
    maxY += mx_dy * stepY;
}


Опять же ее использование.
/// Увеличение масштаба
void QModeGraphics::zoomIn()
{
    settings.scroll(-0.5, -0.5, 0.5, 0.5);
    refreshPixmap();
}
/// Уменьшение масштаба
void QModeGraphics::zoomOut()
{
    settings.scroll(0.5, 0.5, -0.5, -0.5);
    refreshPixmap();
}

При этом мне бы хотелось, чтобы при увеличении колесиком мыши масштаба:
координаты осей, которые были
0, 5, 10, 15, 20...
стали бы
-5, 0, 5, 10, 15, 20, 25....
Ну и т.д.

Зона и график при этом приближались пропорционально своим размерам. А у меня происходит следующее:
координаты приблизительно так и изменяются, а вот график и зоны растягиваются при приближении, а при отдалении уходят за экран видимости! Как мне это поправить? В чем ошибка приведенного выше кода?
ViGOur Дата 17.6.2008, 11:10
  :)

Ты на бумаге попробуй все разрисуй, это помогает, когда не можешь нормально сконцентрироваться. ;)
AD Дата 17.6.2008, 11:09
  Блин совсем мозги плавятся от правильного определения координат этих точек. Помогите, пожалуйста. Я запутался с этим масштабированием! :(
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2024, 3:48