RobbieE RobbieE - 2 months ago 17
C++ Question

How do you keep QPen pixel width the same when zooming in a QGraphicsView

I wrote a quick and nasty program to help me visualise an aspect of a project I'm working on. Although I've been working with Qt since 4.1.1, I've never really had the need to use the QGraphics* module.

When I started playing round with the program, I was working on an old computer running Windows XP and Qt4.7.0 and Visual Studio 2008. I've now just copied the file across to my main computer running Windows 8. I've decided to give Qt5 a shot so I've installed QtCreator with Qt5.0.2.

When I compile the exact same code as I created on the Qt4.7.0/XP machine, I get a vastly different result.

This is what I see on my Qt4.7.0 compilation:

Zoomed-out view from Qt4.7.0/XP compilation

and this is what I see on my Qt5.0.2 compilation:
Zoomed-out view from Qt5.0.2/Win8x64 compilation

Clearly there's different behaviour in the drawing of each rectangle's border. Also, if I zoom in using the mouse wheel, the rectangle border width gets bigger in the Qt5 compilation but stays the same(about 1 pixel wide) in the Qt4.7 compilation.

How do I change the code so that behaviour in Qt5 is the same as in Qt4.7?

Here's the full code:

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

Answer

The best answer is given by rpsml below this one. But for historical reasons I'll leave this one here.

Setting the width of the pen to zero will make it a "cosmetic" pen with a width of 1.

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