LINUX.ORG.RU

История изменений

Исправление kamre, (текущая версия) :

Для Ъ: начиная с 4.8 Qt криво рисует линии.

В целочисленных действительно стал криво рисовать. А вот в qreal - наоборот получше вроде. Чем не подходит преобразовывать в qreal и рисовать?

Вроде нормально рисуется:

#include <QApplication>
#include <QLabel>
#include <QCheckBox>
#include <QPainter>
#include <QMouseEvent>
#include <QLayout>

class DrawLine: public QWidget {
Q_OBJECT
public:
    DrawLine() : size(11), scale(60), radius(5), active(-1), hover(-1),
                 image(size, size, QImage::Format_RGB32), round(false) {
        int sz = size*scale;
        setMinimumSize(sz, sz);
        int half = sz/2;
        pts[0] = QPoint(half/2, half);
        pts[1] = QPoint(half*3/2, half);
        renderLine();
        setMouseTracking(true);
    }
    void emitCoords() {
        QString str;
        if (round) {
            QPoint p0 = roundCoords(0);
            QPoint p1 = roundCoords(1);
            str.sprintf("P0: (%d, %d) P1: (%d, %d)", p0.x(), p0.y(), p1.x(), p1.y());
        } else {
            QPointF p0 = coords(0);
            QPointF p1 = coords(1);
            str.sprintf("P0: (%.2f, %.2f) P1: (%.2f, %.2f)", p0.x(), p0.y(), p1.x(), p1.y());
        }
        emit coordsUpdated(str);
    }
public slots:
    void setRound(bool round) {
        this->round = round;
        renderLine();
    }
signals:
    void coordsUpdated(QString coords);
protected:
    virtual void paintEvent(QPaintEvent*) {
        QPainter p(this);
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < size; ++j) {
                QRgb cur = image.pixel(i, j);
                p.fillRect(i*scale, j*scale, scale, scale, QColor(cur));
            }
        }
        p.setPen(Qt::lightGray);
        int sz = size*scale;
        for (int i = 0; i < size; ++i) {
            int x = i*scale;
            p.drawLine(x, 0, x, sz);
            p.drawLine(0, x, sz, x);
        }
        p.setRenderHint(QPainter::Antialiasing);
        p.setPen(Qt::blue);
        p.drawLine(pts[0], pts[1]);
        p.setPen(Qt::NoPen);
        for (int i = 0; i < 2; ++i) {
            p.setBrush(i == hover ? Qt::yellow : Qt::blue);
            p.drawEllipse(pts[i], radius, radius);
        }
    }
    virtual void mousePressEvent(QMouseEvent *event) {
        if (active == -1 && event->button() == Qt::LeftButton) {
            int current = index(event->pos());
            if (current != -1)
                active = current;
        }
    }
    virtual void mouseReleaseEvent(QMouseEvent *event) {
        if (active != -1 && event->button() == Qt::LeftButton) {
            active = -1;
        }
    }
    virtual void mouseMoveEvent(QMouseEvent *event) {
        if (active != -1) {
            pts[active] = event->pos();
            renderLine();
        }
        int current = index(event->pos());
        if (current != hover) {
            hover = current;
            update();
        }
    }
private:
    QPointF coords(int idx) {
        return QPointF(pts[idx])/scale;
    }
    QPoint roundCoords(int idx) {
        return (coords(idx) - QPointF(0.5, 0.5)).toPoint();
    }
    int index(QPoint p) {
        for (int i = 0; i < 2; ++i) {
            if (QLineF(p, pts[i]).length() <= radius)
                return i;
        }
        return -1;
    }
    void renderLine() {
        image.fill(qRgb(255, 255, 255));
        QPainter p(&image);
        p.setPen(Qt::red);
        if (round) {
            p.drawLine(roundCoords(0), roundCoords(1));
        } else {
            p.drawLine(coords(0), coords(1));
        }
        emitCoords();
        update();
    }
    int size;
    int scale;
    int radius;
    int active;
    int hover;
    QImage image;
    QPoint pts[2];
    bool round;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget widget;
    QLabel label;
    QCheckBox round("Round coords");
    DrawLine draw;
    QObject::connect(&draw, SIGNAL(coordsUpdated(QString)), &label, SLOT(setText(QString)));
    QObject::connect(&round, SIGNAL(toggled(bool)), &draw, SLOT(setRound(bool)));
    QGridLayout layout;
    layout.addWidget(&round, 0, 0);
    layout.addWidget(&label, 0, 1);
    layout.addWidget(&draw, 1, 0, 1, 2);
    layout.setColumnStretch(1, 1);
    widget.setLayout(&layout);
    widget.show();
    draw.emitCoords();
    return app.exec();
}

#include "main.moc"

Исходная версия kamre, :

Для Ъ: начиная с 4.8 Qt криво рисует линии.

В целочисленных действительно стал криво рисовать. А вот в qreal - наоборот получше вроде. Чем не подходит округлять в qreal и рисовать?

Вроде нормально рисуется:

#include <QApplication>
#include <QLabel>
#include <QCheckBox>
#include <QPainter>
#include <QMouseEvent>
#include <QLayout>

class DrawLine: public QWidget {
Q_OBJECT
public:
    DrawLine() : size(11), scale(60), radius(5), active(-1), hover(-1),
                 image(size, size, QImage::Format_RGB32), round(false) {
        int sz = size*scale;
        setMinimumSize(sz, sz);
        int half = sz/2;
        pts[0] = QPoint(half/2, half);
        pts[1] = QPoint(half*3/2, half);
        renderLine();
        setMouseTracking(true);
    }
    void emitCoords() {
        QString str;
        if (round) {
            QPoint p0 = roundCoords(0);
            QPoint p1 = roundCoords(1);
            str.sprintf("P0: (%d, %d) P1: (%d, %d)", p0.x(), p0.y(), p1.x(), p1.y());
        } else {
            QPointF p0 = coords(0);
            QPointF p1 = coords(1);
            str.sprintf("P0: (%.2f, %.2f) P1: (%.2f, %.2f)", p0.x(), p0.y(), p1.x(), p1.y());
        }
        emit coordsUpdated(str);
    }
public slots:
    void setRound(bool round) {
        this->round = round;
        renderLine();
    }
signals:
    void coordsUpdated(QString coords);
protected:
    virtual void paintEvent(QPaintEvent*) {
        QPainter p(this);
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < size; ++j) {
                QRgb cur = image.pixel(i, j);
                p.fillRect(i*scale, j*scale, scale, scale, QColor(cur));
            }
        }
        p.setPen(Qt::lightGray);
        int sz = size*scale;
        for (int i = 0; i < size; ++i) {
            int x = i*scale;
            p.drawLine(x, 0, x, sz);
            p.drawLine(0, x, sz, x);
        }
        p.setRenderHint(QPainter::Antialiasing);
        p.setPen(Qt::blue);
        p.drawLine(pts[0], pts[1]);
        p.setPen(Qt::NoPen);
        for (int i = 0; i < 2; ++i) {
            p.setBrush(i == hover ? Qt::yellow : Qt::blue);
            p.drawEllipse(pts[i], radius, radius);
        }
    }
    virtual void mousePressEvent(QMouseEvent *event) {
        if (active == -1 && event->button() == Qt::LeftButton) {
            int current = index(event->pos());
            if (current != -1)
                active = current;
        }
    }
    virtual void mouseReleaseEvent(QMouseEvent *event) {
        if (active != -1 && event->button() == Qt::LeftButton) {
            active = -1;
        }
    }
    virtual void mouseMoveEvent(QMouseEvent *event) {
        if (active != -1) {
            pts[active] = event->pos();
            renderLine();
        }
        int current = index(event->pos());
        if (current != hover) {
            hover = current;
            update();
        }
    }
private:
    QPointF coords(int idx) {
        return QPointF(pts[idx])/scale;
    }
    QPoint roundCoords(int idx) {
        return (coords(idx) - QPointF(0.5, 0.5)).toPoint();
    }
    int index(QPoint p) {
        for (int i = 0; i < 2; ++i) {
            if (QLineF(p, pts[i]).length() <= radius)
                return i;
        }
        return -1;
    }
    void renderLine() {
        image.fill(qRgb(255, 255, 255));
        QPainter p(&image);
        p.setPen(Qt::red);
        if (round) {
            p.drawLine(roundCoords(0), roundCoords(1));
        } else {
            p.drawLine(coords(0), coords(1));
        }
        emitCoords();
        update();
    }
    int size;
    int scale;
    int radius;
    int active;
    int hover;
    QImage image;
    QPoint pts[2];
    bool round;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget widget;
    QLabel label;
    QCheckBox round("Round coords");
    DrawLine draw;
    QObject::connect(&draw, SIGNAL(coordsUpdated(QString)), &label, SLOT(setText(QString)));
    QObject::connect(&round, SIGNAL(toggled(bool)), &draw, SLOT(setRound(bool)));
    QGridLayout layout;
    layout.addWidget(&round, 0, 0);
    layout.addWidget(&label, 0, 1);
    layout.addWidget(&draw, 1, 0, 1, 2);
    layout.setColumnStretch(1, 1);
    widget.setLayout(&layout);
    widget.show();
    draw.emitCoords();
    return app.exec();
}

#include "main.moc"