如何在QGraphicsView的边框上制作标尺 [英] How to make a ruler on the border of a QGraphicsView

查看:971
本文介绍了如何在QGraphicsView的边框上制作标尺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个小的 .ui 项目,并且我试图了解如何正确地在 QGraphicsView



因此,当用户看到图像时,它看起来如下所示:





但是如果用户需要放大(或缩小)标尺随测量值一起移动。





感谢您对此问题的解释,并抱歉提供任何可能的示例或指向正确的方向。

解决方案

通过将 QWidget 子类化以绘制标尺来创建一个新类。然后,根据标尺的大小设置视口边距。



主要困难是处理标尺单位:Qt中的绘制过程仅使用像素。因此,必须将所有距离转换为正确的单位。



任何 QAbstractScrollArea (包括 QGraphicsView ):

 类标尺:公共QWidget 
{
Q_OBJECT
public:
Ruler(QAbstractScrollArea * parent = nullptr):QWidget(parent),
offset(0)
{
.setFixedSize(40,parent-> height());
move(0,40);
connect(parent-> verticalScrollBar(),& QScrollBar :: valueChanged,this,& Ruler :: setOffset);
}
virtual void paintEvent(QPaintEvent * event)
{
QPainter painter(this);
painter.translate(0,-offset);
int const heightMM = height()* toMM();
painter.setFont(font());
QFontMetrics fm(font());
for(int position = 0; position< heightMM; ++ position)
{
int const positionInPix = int(position / toMM());
if(位置%10 == 0)
{
if(位置!= 0)
{
QString const txt = QString :: number(position);
QRect txtRect = fm.boundingRect(txt).translated(0,positionInPix);
txtRect.translate(0,txtRect.height()/ 2);
painter.drawText(txtRect,txt);
}
painter.drawLine(width()-15,positionInPix,width(),positionInPix);
}
else {
painter.drawLine(width()-10,positionInPix,width(),positionInPix);
}
}
}

虚拟void resizeEvent(QResizeEvent * event)
{

int const maximumMM = event- > size()。height()* toMM();
QFontMetrics fm(font());
int w = fm.width(QString :: number(maximumMM))+ 20;
if(w!= event-> size()。width())
{
QSize const newSize(w,event-> size()。height());
sizeChanged(newSize);
return setFixedSize(newSize);
}
返回QWidget :: resizeEvent(event);
}

void setOffset(int value)
{
offset = value;
update();
}
信号:
void sizeChanged(QSize const&);
私人:
int抵销;

静态qreal toMM()
{
return 25.4 / qApp-> desktop()-> logicalDpiY();
}
};

paintEvent()和<$ c如果要在垂直方向而不是水平方向绘制值,可以简化$ c> resizeEvent()函数(不必调整标尺的大小即可显示所有数字)。



使用方法:

  class GraphicsView:public QGraphicsView 
{
public:
GraphicsView(QWidget * parent = nullptr):QGraphicsView(parent),
Ruler(new Ruler(this))
{
connect(ruler) ,& Ruler :: sizeChanged,[this](QSize const& size){setViewportMargins(size.width(),size.width(),0,0);});
}

void setScene(QGraphicsScene * scene)
{
QGraphicsView :: setScene(scene);
if(场景)
标尺-> setFixedHeight(scene-> height());
}
私人:
标尺*标尺;
};

转换像素->毫米不是很准确,您应该找到另一种实现方法。 / p>

我也没有处理场景的调整大小。


I am working on a small .ui project and I am was trying to understand how to properly make a ruler on a QGraphicsView.

So when the use sees the image it looks like the following:

But if the user needs to zoom-in (or zoom-out) the ruler moves accordingly along with the value of the measurements:

Thanks for shedding light on this issue and sor providing any potential example or point to the right direction.

解决方案

Create a new class by subclassing QWidget to draw your ruler. Then, set a viewport margin based on the size of your ruler.

The main difficulty is to handle the units of your ruler: The painting process in Qt uses only pixels. So, you have to convert all the distance to the right unit.

An example of ruler (in millimeters) for any QAbstractScrollArea (including QGraphicsView):

class Ruler: public QWidget
{
    Q_OBJECT
public:
    Ruler(QAbstractScrollArea* parent=nullptr): QWidget(parent),
        offset(0)
    {
        setFixedSize(40, parent->height());
        move(0, 40);
        connect(parent->verticalScrollBar(), &QScrollBar::valueChanged, this, &Ruler::setOffset);
    }
    virtual void paintEvent(QPaintEvent* event)
    {
        QPainter painter(this);
        painter.translate(0, -offset);
        int const heightMM = height() * toMM();
        painter.setFont(font());
        QFontMetrics fm(font());
        for (int position = 0; position < heightMM; ++position)
        {
            int const positionInPix = int(position / toMM());
            if (position % 10 == 0)
            {
                if (position != 0)
                {
                    QString const txt = QString::number(position);
                    QRect txtRect = fm.boundingRect(txt).translated(0, positionInPix);
                    txtRect.translate(0, txtRect.height()/2);
                    painter.drawText(txtRect, txt);
                }
                painter.drawLine(width() - 15, positionInPix, width(), positionInPix);
            }
            else {
                painter.drawLine(width() - 10, positionInPix, width(), positionInPix);
            }
        }
    }

    virtual void resizeEvent(QResizeEvent* event)
    {

        int const maximumMM = event->size().height() * toMM();
        QFontMetrics fm(font());
        int w = fm.width(QString::number(maximumMM)) + 20;
        if (w != event->size().width())
        {
            QSize const newSize(w, event->size().height());
            sizeChanged(newSize);
            return setFixedSize(newSize);
        }
        return QWidget::resizeEvent(event);
    }

    void setOffset(int value)
    {
        offset = value;
        update();
    }
signals:
    void sizeChanged(QSize const&);
private:
    int offset;

    static qreal toMM()
    {
        return 25.4 / qApp->desktop()->logicalDpiY();
    }
};

The paintEvent() and resizeEvent() functions could be simplified if you want to draw the values at the vertical instead of horizontal (you will not have to resize the ruler to be able to display all digits).

How to use it:

class GraphicsView: public QGraphicsView
{
public:
    GraphicsView(QWidget* parent=nullptr): QGraphicsView(parent),
        ruler(new Ruler(this))
    {
        connect(ruler, &Ruler::sizeChanged, [this](QSize const& size) { setViewportMargins(size.width(), size.width(), 0, 0); });
    }

    void setScene(QGraphicsScene* scene)
    {
        QGraphicsView::setScene(scene);
        if (scene)
            ruler->setFixedHeight(scene->height());
    }
private:
    Ruler* ruler;
};

The conversion pixel -> millimeters is not really accurate and you should find another way to make it.

I didn't handle the resize of the scene, either.

这篇关于如何在QGraphicsView的边框上制作标尺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆