在放大QGraphicsView时,如何使QPen像素宽度保持不变?

时间:2013-06-12 21:24:56

标签: c++ qt5

我写了一个快速而讨厌的程序来帮助我想象我正在研究的项目的一个方面。虽然自4.1.1以来我一直在使用Qt,但我从来没有真正需要使用QGraphics *模块。

当我开始使用该程序时,我正在使用运行Windows XP和Qt4.7.0以及Visual Studio 2008的旧计算机。我现在只是将文件复制到运行Windows 8的主计算机上。我我决定给Qt5打一针,所以我用Qt5.0.2安装了QtCreator。

当我编译与我在Qt4.7.0 / XP机器上创建的完全相同的代码时,我得到了截然不同的结果。

这是我在Qt4.7.0编译中看到的:

Zoomed-out view from Qt4.7.0/XP compilation

这就是我在Qt5.0.2编译中看到的: Zoomed-out view from Qt5.0.2/Win8x64 compilation

显然,每个矩形边框的绘图都有不同的行为。另外,如果我使用鼠标滚轮放大,Qt5编译中的矩形边框宽度会变大,但在Qt4.7编辑中保持不变(大约1个像素宽)。

如何更改代码以使Qt5中的行为与Qt4.7中的行为相同?

这是完整的代码:

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QWheelEvent>

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>
#include <QSqlError>
#include <QMessageBox>

class ItemData : public QSqlRecord{
public:
    ItemData(QSqlRecord const &rec) : QSqlRecord(rec) {}

    qreal left() const { return value(0).toDouble(); }
    qreal top() const { return value(1).toDouble(); }
    qreal width() const { return value(2).toDouble() - left(); }
    qreal height() const { return value(3).toDouble() - top(); }
    QRectF rect() const { return QRectF(left(), top(), width(), height()); }
    QString barcode() const { return value(4).toString(); }
    QString msaName() const { return value(5).toString(); }
    QString msaDescription() const { return value(6).toString(); }
    QString hsaName() const { return value(7).toString(); }
    QString hsaDescription() const { return value(8).toString(); }
};

class DSAItem : public QGraphicsRectItem{
public:
    DSAItem(ItemData const &data, QGraphicsItem *parent = 0)
        :QGraphicsRectItem(parent) {
            setFlags(QGraphicsItem::ItemIsSelectable);
            setRect(data.rect());
            QString tip = "<p><b>%1</b></p><p><b>MLSA</b><br/>%2<br/>%3</p><p><b>HLSA</b><br/>%4<br/>%5</p>";
            setToolTip(tip.arg(data.barcode(), data.msaName(), data.msaDescription(), data.hsaName(), data.hsaDescription()));
            if(data.barcode() == "1010100101" || data.barcode() == "1010100114"){
                colour = QColor(Qt::red);
            } else {
                colour = QColor(Qt::yellow);
            }
            colour.setAlphaF(.5);
            setBrush(QBrush(colour));
    }

    QVariant itemChange(GraphicsItemChange change, QVariant const &value){
        if (change == QGraphicsItem::ItemSelectedHasChanged){
            QColor c = value.toBool() ? QColor(Qt::green) : colour;
            c.setAlphaF(.5);
            setBrush(QBrush(c));
            update(rect());

        }
        return QGraphicsRectItem::itemChange(change, value);
    }

private:
    QColor colour;
};

class View : public QGraphicsView {
public:
    View(QWidget *parent = 0): QGraphicsView(parent){
        populateScene();
        setScene(&scene);
        rotate(-90);
        scale(1.0, -1.0);
        setDragMode(ScrollHandDrag);
    }

protected:
    void wheelEvent(QWheelEvent *e){
        setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

        double scaleFactor = 1.15;
        if (e->delta() > 0){
            scale(scaleFactor, scaleFactor);
        } else {
            scale(1 / scaleFactor, 1 / scaleFactor);
        }
    }

private:
    void populateScene(){
        QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
        //db credentials here

        QString errorMessage;
        bool ok = db.open();
        if (ok){
            QSqlQuery query(db);
            QString sql = //query string here

            if (query.exec(sql)){
                while(query.next()){
                    scene.addItem(new DSAItem(query.record()));
                }
            } else {
                errorMessage = query.lastError().text();
            }
        } else {
            errorMessage = db.lastError().text();
        }

        if (!errorMessage.isEmpty()){
            QMessageBox::critical(0, "Database Error", errorMessage);
        }
    }

private:
    QGraphicsScene scene;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    View view;
    view.show();

    return a.exec();
}

2 个答案:

答案 0 :(得分:27)

这有点晚,但可能会有所帮助。

建议的解决方案工作正常,但限制了笔。另一种方法是使用指令

p.setCosmetic(true);

根据Qt参考(http://qt-project.org/doc/qt-5/qpen.html#isCosmetic

  

化妆笔用于绘制具有恒定宽度的笔划,无论应用于与其一起使用的QPainter的任何变换。

它还解释了将宽度设置为零的原因:

  

零宽度笔默认为化妆品;宽度非零的笔是非化妆品。

答案 1 :(得分:5)

最好的答案是由rpsml给出的。但由于历史原因,我会把这个放在这里。

将笔的宽度设置为零将使其成为宽度为1的“化妆品”笔。

QPen p = pen();
p.setWidth(0)
setPen(p);