2013-06-12 10 views
7

Napisałem szybki i nieprzyjemny program, który pomoże mi zwizualizować aspekt projektu, nad którym pracuję. Chociaż pracowałem z Qt od wersji 4.1.1, nigdy nie potrzebowałem używać modułu QGraphics *.Jak zachować szerokość piksela QPen taką samą przy powiększaniu QGraphicsView

Kiedy zacząłem grać z programem, pracowałem na starym komputerze z systemem Windows XP i Qt4.7.0 i Visual Studio 2008. Właśnie skopiowałem plik na mój główny komputer z systemem Windows 8. Postanowiłem dać Qt5 strzał, więc zainstalowałem QtCreator z Qt5.0.2.

Kiedy skompiluję dokładnie ten sam kod, który utworzyłem na maszynie Qt4.7.0/XP, otrzymuję zupełnie inny wynik.

To co widzę na moim kompilacji Qt4.7.0:

Zoomed-out view from Qt4.7.0/XP compilation

i to, co widzę na moim kompilacji Qt5.0.2: Zoomed-out view from Qt5.0.2/Win8x64 compilation

Wyraźnie tam różne zachowanie w rysunek każdej granicy prostokąta. Ponadto, jeśli powiększam za pomocą kółka myszy, szerokość obramowania prostokąta staje się większa w kompilacji Qt5, ale pozostaje taka sama (szerokość około 1 piksela) w kompilacji Qt4.7.

Jak zmienić kod, aby zachowanie w Qt5 było takie samo jak w Qt4.7?

Oto pełny kod:

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

Odpowiedz

5

Najlepszą odpowiedzią jest przez rpsml poniżej tego. Ale z powodów historycznych zostawię ten tutaj.

Ustawienie szerokości pisaka do zera uczyni to „kosmetyczne” pióro o szerokości 1.

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

To była jedna z pierwszych rzeczy, próbowałem, ale nie, łuski szerokość pióra wraz z pozycji w Qt5 ale nie w Qt4.7 – RobbieE

+1

Docs dla QPen :: setWidth() powiedzieć „A szerokość linii zera oznacza długopis kosmetyczny, co oznacza, że ​​szerokość pisaka jest zawsze narysowana na szerokość jednego piksela, niezależnie od zestawu transformacji na malarzu. " czy próbowałeś ustawić szerokość na 0? –

+0

To wszystko !!! Dzięki Cory. Wartość domyślna musi się zmienić między wersjami. Utwórz odpowiedź, a dam ci kredyt. – RobbieE

23

To jest trochę późno, ale może być pomocne.

Proponowane rozwiązanie działa dobrze, ale ogranicza szerokość pióra. Alternatywą jest użycie Instrukcji

p.setCosmetic(true); 

zgodnie z referencjami Qt (http://qt-project.org/doc/qt-5/qpen.html#isCosmetic)

pióra kosmetyczne są używane do opracowania uderzeń, które mają stałą szerokość bez względu na zastosowane przekształcenia QPainter są one używane z.

I to również wyjaśnia, dlaczego ustawienie szerokości do zerowych robót:

Zero szerokość pióra jest kosmetyk domyślnie; długopisy o niezerowej szerokości są nie kosmetyczne.

+0

Podoba mi się ta informacja - jest czysta (czystsza niż przyjęte rozwiązanie) i oferuje większą elastyczność – DomTomCat

+0

IMHO, to jest właściwa poprawna odpowiedź. – quimnuss

+0

Ostatnie pół zdania jest dość niejednoznaczne: "Pióro o zerowej szerokości jest domyślnie kosmetycznym, pióra o niezerowej szerokości są nie kosmetyczne.". Jeśli czytasz tylko ostatnią połowę "długopisy o niezerowej szerokości są nie kosmetyczne." wtedy niezerowa szerokość pisaka NIE powinna być kosmetyczna, bez względu na to, co ustawisz w 'setCosmetic'. To jest rzeczywiście zachowanie, które widzę podczas testowania (PyQt4.7) – Peter