2014-10-27 31 views
1

我正在使用Qt構建地圖小部件(類似谷歌地圖),基本上我使用了QGraphicsScene來顯示地圖圖塊。在QGraphicsScene中繪製比例尺嗎?

現在我想在小部件中添加比例尺,就像google map中的比例尺一樣。 關於我怎麼能意識到這一點的任何建議?

回答

1

this example看看:

結構代碼庫如下:

  • 寫一個類繼承的後代類QAbstractScrollArea的(作爲例子的QGraphicsView,QMdiArea,QPlainTextEdit,QScrollArea,的QTextEdit,QColumnView, QHeaderView,QListView,QTableView,QTreeView等)
  • 在你的類的構造函數中調用setViewportMargins並設置左/上/右/下區域邊距的長度。
  • 創建一個QGridLayout並在佈局中添加您的自定義標尺/比例尺。
  • 設置此佈局調用setLayout的

例子:

setViewportMargins(RULER_BREADTH,RULER_BREADTH,0,0); 
QGridLayout* gridLayout = new QGridLayout(); 
gridLayout->setSpacing(0); 
gridLayout->setMargin(0); 

mHorzRuler = new QDRuler(QDRuler::Horizontal); 
mVertRuler = new QDRuler(QDRuler::Vertical); 

QWidget* fake = new QWidget(); 
fake->setBackgroundRole(QPalette::Window); 
fake->setFixedSize(RULER_BREADTH,RULER_BREADTH); 
gridLayout->addWidget(fake,0,0); 
gridLayout->addWidget(mHorzRuler,0,1); 
gridLayout->addWidget(mVertRuler,1,0); 
gridLayout->addWidget(this->viewport(),1,1); 

this->setLayout(gridLayout); 

QDRuler:Ruler類

#define RULER_BREADTH 20 

class QDRuler : public QWidget 
{ 
Q_OBJECT 
Q_ENUMS(RulerType) 
Q_PROPERTY(qreal origin READ origin WRITE setOrigin) 
Q_PROPERTY(qreal rulerUnit READ rulerUnit WRITE setRulerUnit) 
Q_PROPERTY(qreal rulerZoom READ rulerZoom WRITE setRulerZoom) 
public: 
    enum RulerType { Horizontal, Vertical }; 
QDRuler(QDRuler::RulerType rulerType, QWidget* parent) 
: QWidget(parent), mRulerType(rulerType), mOrigin(0.), mRulerUnit(1.), 
    mRulerZoom(1.), mMouseTracking(false), mDrawText(false) 
{ 
    setMouseTracking(true); 
    QFont txtFont("Goudy Old Style", 5,20); 
    txtFont.setStyleHint(QFont::TypeWriter,QFont::PreferOutline); 
    setFont(txtFont); 
} 

QSize minimumSizeHint() const 
{ 
    return QSize(RULER_BREADTH,RULER_BREADTH); 
} 

QDRuler::RulerType rulerType() const 
{ 
    return mRulerType; 
} 

qreal origin() const 
{ 
    return mOrigin; 
} 

qreal rulerUnit() const 
{ 
    return mRulerUnit; 
} 

qreal rulerZoom() const 
{ 
    return mRulerZoom; 
} 

public slots: 

void setOrigin(const qreal origin) 
{ 
    if (mOrigin != origin) 
    { 
    mOrigin = origin; 
    update(); 
    } 
} 

void setRulerUnit(const qreal rulerUnit) 
{ 
    if (mRulerUnit != rulerUnit) 
    { 
    mRulerUnit = rulerUnit; 
    update(); 
    } 
} 

void setRulerZoom(const qreal rulerZoom) 
{ 
    if (mRulerZoom != rulerZoom) 
    { 
    mRulerZoom = rulerZoom; 
    update(); 
    } 
} 


void setCursorPos(const QPoint cursorPos) 
{ 
    mCursorPos = this->mapFromGlobal(cursorPos); 
    mCursorPos += QPoint(RULER_BREADTH,RULER_BREADTH); 
    update(); 
} 

void setMouseTrack(const bool track) 
{ 
    if (mMouseTracking != track) 
    { 
    mMouseTracking = track; 
    update(); 
    } 
} 

protected: 
void mouseMoveEvent(QMouseEvent* event) 
{ 
    mCursorPos = event->pos(); 
    update(); 
    QWidget::mouseMoveEvent(event); 
} 

void paintEvent(QPaintEvent* event) 
{ 
    QPainter painter(this); 
    painter.setRenderHints(QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing); 
    QPen pen(Qt::black,0); // zero width pen is cosmetic pen 
    //pen.setCosmetic(true); 
    painter.setPen(pen); 
    // We want to work with floating point, so we are considering 
    // the rect as QRectF 
    QRectF rulerRect = this->rect(); 

    // at first fill the rect 
    //painter.fillRect(rulerRect,QColor(220,200,180)); 
    painter.fillRect(rulerRect,QColor(236,233,216)); 

    // drawing a scale of 25 
    drawAScaleMeter(&painter,rulerRect,25,(Horizontal == mRulerType ? rulerRect.height() 
     : rulerRect.width())/2); 
    // drawing a scale of 50 
    drawAScaleMeter(&painter,rulerRect,50,(Horizontal == mRulerType ? rulerRect.height() 
     : rulerRect.width())/4); 
    // drawing a scale of 100 
    mDrawText = true; 
    drawAScaleMeter(&painter,rulerRect,100,0); 
    mDrawText = false; 

    // drawing the current mouse position indicator 
    painter.setOpacity(0.4); 
    drawMousePosTick(&painter); 
    painter.setOpacity(1.0); 

    // drawing no man's land between the ruler & view 
    QPointF starPt = Horizontal == mRulerType ? rulerRect.bottomLeft() 
     : rulerRect.topRight(); 
    QPointF endPt = Horizontal == mRulerType ? rulerRect.bottomRight() 
     : rulerRect.bottomRight(); 
    painter.setPen(QPen(Qt::black,2)); 
    painter.drawLine(starPt,endPt); 
} 

private: 
void drawAScaleMeter(QPainter* painter, QRectF rulerRect, qreal scaleMeter, qreal startPositoin) 
{ 
    // Flagging whether we are horizontal or vertical only to reduce 
    // to cheching many times 
    bool isHorzRuler = Horizontal == mRulerType; 

    scaleMeter = scaleMeter * mRulerUnit * mRulerZoom; 

    // Ruler rectangle starting mark 
    qreal rulerStartMark = isHorzRuler ? rulerRect.left() : rulerRect.top(); 
    // Ruler rectangle ending mark 
    qreal rulerEndMark = isHorzRuler ? rulerRect.right() : rulerRect.bottom(); 

    // Condition A # If origin point is between the start & end mard, 
    //we have to draw both from origin to left mark & origin to right mark. 
    // Condition B # If origin point is left of the start mark, we have to draw 
    // from origin to end mark. 
    // Condition C# If origin point is right of the end mark, we have to draw 
    // from origin to start mark. 
    if (mOrigin >= rulerStartMark && mOrigin <= rulerEndMark) 
    {  
    drawFromOriginTo(painter, rulerRect, mOrigin, rulerEndMark, 0, scaleMeter, startPositoin); 
    drawFromOriginTo(painter, rulerRect, mOrigin, rulerStartMark, 0, -scaleMeter, startPositoin); 
    } 
    else if (mOrigin < rulerStartMark) 
    { 
     int tickNo = int((rulerStartMark - mOrigin)/scaleMeter); 
     drawFromOriginTo(painter, rulerRect, mOrigin + scaleMeter * tickNo, 
      rulerEndMark, tickNo, scaleMeter, startPositoin); 
    } 
    else if (mOrigin > rulerEndMark) 
    { 
     int tickNo = int((mOrigin - rulerEndMark)/scaleMeter); 
    drawFromOriginTo(painter, rulerRect, mOrigin - scaleMeter * tickNo, 
      rulerStartMark, tickNo, -scaleMeter, startPositoin); 
    } 
} 

void drawFromOriginTo(QPainter* painter, QRectF rulerRect, qreal startMark, qreal endMark, int startTickNo, qreal step, qreal startPosition) 
{ 
    bool isHorzRuler = Horizontal == mRulerType; 
    int iterate = 0; 

    for (qreal current = startMark; 
     (step < 0 ? current >= endMark : current <= endMark); current += step) 
    { 
    qreal x1 = isHorzRuler ? current : rulerRect.left() + startPosition; 
    qreal y1 = isHorzRuler ? rulerRect.top() + startPosition : current; 
    qreal x2 = isHorzRuler ? current : rulerRect.right(); 
    qreal y2 = isHorzRuler ? rulerRect.bottom() : current; 
    painter->drawLine(QLineF(x1,y1,x2,y2)); 
    if (mDrawText) 
    { 
     QPainterPath txtPath; 
      txtPath.addText(x1 + 1,y1 + (isHorzRuler ? 7 : -2),this->font(),QString::number(qAbs(int(step) * startTickNo++))); 
     painter->drawPath(txtPath); 
     iterate++; 
    } 
    } 
} 

void drawMousePosTick(QPainter* painter) 
{ 
    if (mMouseTracking) 
    { 
    QPoint starPt = mCursorPos; 
    QPoint endPt; 
    if (Horizontal == mRulerType) 
    { 
     starPt.setY(this->rect().top()); 
     endPt.setX(starPt.x()); 
     endPt.setY(this->rect().bottom()); 
    } 
    else 
    { 
     starPt.setX(this->rect().left()); 
     endPt.setX(this->rect().right()); 
     endPt.setY(starPt.y()); 
    } 
    painter->drawLine(starPt,endPt); 
    } 
} 
private: 
    RulerType mRulerType; 
    qreal mOrigin; 
    qreal mRulerUnit; 
    qreal mRulerZoom; 
    QPoint mCursorPos; 
    bool mMouseTracking; 
    bool mDrawText; 
};