Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Qgraphicscene中绘制标尺?_C++_Qt_Qgraphicsscene - Fatal编程技术网

C++ 在Qgraphicscene中绘制标尺?

C++ 在Qgraphicscene中绘制标尺?,c++,qt,qgraphicsscene,C++,Qt,Qgraphicsscene,我正在使用Qt构建一个地图小部件(类似于googlemap),基本上我使用了一个qgraphicscene来显示地图块 现在我想在这个小部件中添加一个标尺,就像谷歌地图中的那个一样。 关于如何实现这一点,有什么建议吗?请看: 按以下方式构造代码库: 编写一个继承QAbstractScrollArea的后代类的类(例如QGraphicsView、QMdiArea、QPlainTextEdit、QScrollArea、QTextEdit、QColumnView、QHeaderView、QListV

我正在使用Qt构建一个地图小部件(类似于googlemap),基本上我使用了一个qgraphicscene来显示地图块

现在我想在这个小部件中添加一个标尺,就像谷歌地图中的那个一样。 关于如何实现这一点,有什么建议吗?

请看:

按以下方式构造代码库:

  • 编写一个继承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:统治者类

#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;
};
#定义标尺宽度20
类:公共QWidget
{
Q_对象
Q_枚举(规则类型)
Q_属性(qreal origin READ origin WRITE setOrigin)
Q_属性(qreal rulerUnit READ rulerUnit WRITE setRulerUnit)
Q_属性(qreal rulerZoom READ rulerZoom WRITE setRulerZoom)
公众:
枚举规则类型{水平,垂直};
QDRuler(QDRuler::RulerType RulerType,QWidget*父项)
:QWidget(父)、mruletype(rulerType)、mOrigin(0.)、mRulerUnit(1.),
mRulerZoom(1.)、mMouseTracking(false)、mDrawText(false)
{
setMouseTracking(真);
QFont txtFont(“古迪旧式”,5,20);
setStyleHint(QFont::打字机,QFont::PreferOutline);
setFont(txtFont);
}
QSize minimumSizeHint()常量
{
返回QSize(标尺宽度、标尺宽度);
}
QDRuler::RulerType RulerType()常量
{
返回mRulerType;
}
qreal origin()常量
{
返回莫里金;
}
qreal rulerUnit()常量
{
返回mRulerUnit;
}
qreal rulerZoom()常量
{
返回mRulerZoom;
}
公众时段:
无效设置原点(常量原点)
{
if(mOrigin!=原点)
{
莫里金=起源;
更新();
}
}
void setRulerUnit(const qreal rulerUnit)
{
if(mRulerUnit!=规则runit)
{
mRulerUnit=规则runit;
更新();
}
}
void setRulerZoom(常量qreal rulerZoom)
{
if(mRulerZoom!=规则缩放)
{
mRulerZoom=规则缩放;
更新();
}
}
void setCursorPos(常量QPoint cursorPos)
{
mCursorPos=this->mapFromGlobal(cursorPos);
mCursorPos+=QPoint(标尺宽度,标尺宽度);
更新();
}
void setMouseTrack(const bool track)
{
如果(mMouseTracking!=跟踪)
{
mMouseTracking=跟踪;
更新();
}
}
受保护的:
作废mouseMoveEvent(QMouseEvent*事件)
{ 
mCursorPos=事件->位置();
更新();
QWidget::mouseMoveEvent(事件);
}
无效paintEvent(QPaintEvent*事件)
{
油漆工(本);
painter.setRenderInts(QPainter::TextAntialiasing | QPainter::HighQuality AntiAliasing);
QPen笔(Qt::黑色,0);//零宽度笔是化妆笔
//笔。设置化妆品(真);
画师:画笔;
//我们希望使用浮点运算,所以我们正在考虑
//作为QRectF的rect
QRectF rulerRect=this->rect();
//首先填充矩形
//painter.fillRect(rulerRect,QColor(220200180));
画家。fillRect(规则正确,QColor(236233216));
//绘制25的比例尺
drawAScaleMeter(&painter,rulerRect,25,(水平==mRulerType?rulerRect.height()
:rulerRect.width())/2);
//绘制50的比例尺
drawAScaleMeter(&painter,rulerRect,50,(水平==mRulerType?rulerRect.height()
:rulerRect.width())/4);
//绘制100的比例尺
mDrawText=true;
图纸校准仪(和油漆工,规则正确,100,0);
mDrawText=false;
//绘制当前鼠标位置指示器
设置不透明度(0.4);
画笔和画笔;
设置不透明度(1.0);
//在标尺和视图之间绘制无人地带
QPointF starPt=Horizontal==mRulerType?rulerRect.bottomLeft()
:rulerRect.topRight();
QPointF endPt=Horizontal==mRulerType?rulerRect.bottomRight()
:rulerRect.bottomRight();
画师:setPen(QPen(Qt::黑色,2));
油漆工。拉丝(起点、终点);
}
私人:
无效绘图比例计(QPainter*painter、QRectF规则更正、qreal比例计、qreal起始位置)
{
//标记我们是水平还是垂直只是为了减少
//多次检查
bool-isHorzRuler=水平==mRulerType;
scaleMeter=scaleMeter*mRulerUnit*mRulerZoom;
//直尺矩形起始标记
qreal rulerStartMark=isHorzRuler?rulerRect.left():rulerRect.top();
//直尺矩形结束标记
qreal rulerEndMark=isHorzRuler?rulerRect.right():rulerRect.bottom();
//条件A#如果原点在起始和结束mard之间,
//我们必须从原点到左标记,从原点到右标记。
//条件B#如果原点在起始标记的左侧,我们必须绘制
//从起点到终点。
//条件C#如果原点在终点标记的右侧,我们必须绘制
//从原点到起始标记。
if(mOrigin>=rulerStartMark&&mOrigin rulerEndMark)
{
int tickNo=int((mOrigin-rulerEndMark)/比例表);
drawFromOriginTo(画家、规则更正、莫里金-刻度表*tickNo,
规则开始标记、勾号、刻度计、开始位置);
}
}
从原点到原点的无效图纸(QPainter*painter、QRectF规则更正、qreal开始标记、qreal结束标记、int开始标记号、qreal步骤、qreal开始位置)
{
bool-isHorzRuler=水平==mRulerType;
int迭代=0;
对于(qreal电流=起始标记;
(步进<0?电流>=终点:电流绘制线(QLineF(x1,y1,x2,y2));
if(mDrawText)
{
QPainterPath txtPath;
addText(x1+1,y1+(isHorzRuler?7:-2),this->font(),QString::number(qAbs(int(step)*startTickNo++);
画师->绘图路径(txtPath);
迭代++;
}
}
}
无效绘图鼠标棒(QPainter*painter)
{
如果(mMouseTracking)
{
QPoint starPt=mCursorPos;
点端点;
if(水平==mRulerType)
{
starPt.setY(this->rect().top());
endPt.setX(starPt.x());
结束设置(此->r