PDA

View Full Version : How to create a ruler widget for a qcustomplot with a given ICSRulerWidget Class?



mson9
4th April 2017, 01:55
I am trying to create a ruler widget that I can use to measure customplot's keys or values. I found an existing thread that included the .cpp and .h file for the ICSRulerWidget Class. However, I do not quite know to use the given class' methods to create the ruler. Specifically, I'd like it to be placed at the place the mouse was pressed, and be able to be dragged to the spot to be measured until mouse released.

Can anyone help with a simple example of creating the ruler?

The icsrulerwidget.cpp file:

#include <QDebug>
#include <QIcon>
#include <QPen>
#include <QPaintEvent>
#include <QPainter>
#include "icsrulerwidget.h"

ICSRulerWidget::ICSRulerWidget(QWidget* pParent): QWidget(pParent) {}

int ICSRulerWidget::createMarker(bool pInverted) {
auto pMarker = new QLabel(this);

pMarker->installEventFilter(this);
pMarker->setProperty("ICS_MarkerInverted", pInverted);
pMarker->setProperty("ICS_MarkerValue", 0.0f);
pMarker->setPixmap(
m_nOrientation == Qt::Horizontal
? QIcon(":/resources/toolbar/rulerTool.png").pixmap(16, 16)
: QIcon(":/resources/toolbar/rulerTool.png").pixmap(16, 16)
);

m_lstMarkers.append(pMarker);
setMarkerRange(m_lstMarkers.length() - 1, 0.0f, m_fMaximum);

return m_lstMarkers.length() - 1;
}

void ICSRulerWidget::setOrientation(Qt::Orientation pOrientation) {
if(pOrientation == Qt::Horizontal)
setMinimumSize(0, fontMetrics().height() + 16);
else
setMinimumSize(fontMetrics().height() + 16, 0);

m_nOrientation = pOrientation;

updateGeometry();
}

float ICSRulerWidget::markerValue(int pIndex) const { return m_lstMarkers[pIndex]->property("ICS_MarkerValue").toFloat(); }

void ICSRulerWidget::setMarkerValue(int pIndex, float pValue) {
auto pMarker = m_lstMarkers[pIndex];

pMarker->setProperty("ICS_MarkerValue", pValue);

if(m_nOrientation == Qt::Horizontal)
pMarker->move(
pMarker->property("ICS_MarkerInverted").toBool()
? m_nOrigin + float(physicalDpiX()) / 25.4f * (m_fMaximum - pValue)
: m_nOrigin + float(physicalDpiX()) / 25.4f * pValue,
0
);
else
pMarker->move(
0,
pMarker->property("ICS_MarkerInverted").toBool()
? m_nOrigin + float(physicalDpiY()) / 25.4f * (m_fMaximum - pValue)
: m_nOrigin + float(physicalDpiY()) / 25.4f * pValue
);

emit markerValueChanged(pIndex, pValue);
}

void ICSRulerWidget::setMarkerRange(int pIndex, float pMinimum, float pMaximum) {
m_lstMarkers[pIndex]->setProperty("ICS_MarkerRange", QVariant::fromValue<QPair<float, float> >(QPair<float, float>(pMinimum, pMaximum)));
}

bool ICSRulerWidget::eventFilter(QObject* pSender, QEvent* pEvent) {
if(auto pMarker = dynamic_cast<QLabel*>(pSender))
switch(pEvent->type()) {
case QEvent::MouseButtonPress: {
auto pMouseEvent = dynamic_cast<QMouseEvent*>(pEvent);

if(!mouseGrabber() && pMouseEvent->button() == Qt::LeftButton) {
pMarker->grabMouse();
pMarker->setProperty("ICS_MouseGrabPoint", pMouseEvent->pos());

emit markerValueAboutToBeChanged(m_lstMarkers.indexOf(p Marker));
return true;
}
}

break;

case QEvent::MouseMove:
if(mouseGrabber() == pMarker) {
auto ptParent = pMarker->mapToParent(dynamic_cast<QMouseEvent*>(pEvent)->pos()) - pMarker->property("ICS_MouseGrabPoint").toPoint();
auto cRange = pMarker->property("ICS_MarkerRange").value<QPair<float, float> >();

if(m_nOrientation == Qt::Horizontal) {
if(ptParent.x() >= physicalDpiX() / 25.4f * cRange.first && ptParent.x() <= m_nOrigin + physicalDpiX() / 25.4f * cRange.second) {
pMarker->move(ptParent.x(), 0);

emit markerValueChanging(
m_lstMarkers.indexOf(pMarker),
pMarker->property("ICS_MarkerInverted").toBool()
? m_fMaximum - float(ptParent.x() - m_nOrigin) * 25.4f / float(physicalDpiX())
: float(ptParent.x() + m_nOrigin) * 25.4f / float(physicalDpiX())
);

return true;
}
} else if(ptParent.y() >= physicalDpiY() / 25.4f * cRange.first && ptParent.y() <= m_nOrigin + physicalDpiY() / 25.4f * cRange.second) {
pMarker->move(0, ptParent.y());

emit markerValueChanging(
m_lstMarkers.indexOf(pMarker),
pMarker->property("ICS_MarkerInverted").toBool()
? m_fMaximum - float(ptParent.y() - m_nOrigin) * 25.4f / float(physicalDpiY())
: float(ptParent.y() + m_nOrigin) * 25.4f / float(physicalDpiY())
);

return true;
}
}

break;

case QEvent::MouseButtonRelease: {
auto pMouseEvent = dynamic_cast<QMouseEvent*>(pEvent);
auto cRange = pMarker->property("ICS_MarkerRange").value<QPair<float, float> >();

if(mouseGrabber() == pMarker && pMouseEvent->button() == Qt::LeftButton) {
auto ptParent = pMarker->mapToParent(pMouseEvent->pos()) - pMarker->property("ICS_MouseGrabPoint").toPoint();

pMarker->releaseMouse();

if(m_nOrientation == Qt::Horizontal) {
if(ptParent.x() >= physicalDpiX() / 25.4f * cRange.first && ptParent.x() <= m_nOrigin + physicalDpiX() / 25.4f * cRange.second) {
pMarker->move(ptParent.x(), 0);
pMarker->setProperty(
"ICS_MarkerValue",
pMarker->property("ICS_MarkerInverted").toBool()
? m_fMaximum - float(ptParent.x() - m_nOrigin) * 25.4f / float(physicalDpiX())
: float(ptParent.x() + m_nOrigin) * 25.4f / float(physicalDpiX())
);
}
} else if(ptParent.y() >= physicalDpiY() / 25.4f * cRange.first && ptParent.y() <= m_nOrigin + physicalDpiY() / 25.4f * cRange.second) {
pMarker->move(0, ptParent.y());
pMarker->setProperty(
"ICS_MarkerValue",
pMarker->property("ICS_MarkerInverted").toBool()
? m_fMaximum - float(ptParent.y() - m_nOrigin) * 25.4f / float(physicalDpiY())
: float(ptParent.y() + m_nOrigin) * 25.4f / float(physicalDpiY())
);
}

emit markerValueChanged(m_lstMarkers.indexOf(pMarker), pMarker->property("ICS_MarkerValue").toFloat());

return true;
}
}

break;

default:
break;
}

return QWidget::eventFilter(pSender, pEvent);
}

void ICSRulerWidget::paintEvent(QPaintEvent* pEvent) {
Q_UNUSED(pEvent);

QPainter cPainter(this);

cPainter.fillRect(0, 0, width(), height(), Qt::white);
cPainter.setPen(Qt::lightGray);
cPainter.drawRect(0, 0, width(), height());

if(m_nOrientation == Qt::Horizontal) {
float nX = 8.0f;

cPainter.translate(m_nOrigin, 0.0f);

for(int nValue = 0; nValue <= m_fMaximum; nValue += 2) {
if(nX + m_nOrigin >= 0 && nX + m_nOrigin < width()) {
if(nValue % 10 == 0) {
auto strText = QString::number(nValue / 10);

cPainter.setPen(QPen(QBrush(Qt::black), 2.0f));
cPainter.drawLine(nX, height() - 2, nX, height() - fontMetrics().height() / 2 - 2);
cPainter.drawText(nX - fontMetrics().width(strText) / 2, height() - fontMetrics().height() / 2 - 8, strText);
} else {
cPainter.setPen(Qt::black);
cPainter.drawLine(nX, height() - 2, nX, height() - fontMetrics().height() / 3 - 2);
}
}

nX += float(physicalDpiX()) / 12.7f;
}
} else {
float nY = 8.0f;

cPainter.translate(0.0f, m_nOrigin);

for(int nValue = 0; nValue <= m_fMaximum; nValue += 2) {
if(nY + m_nOrigin >= 0 && nY + m_nOrigin < height()) {
if(nValue % 10 == 0) {
auto strText = QString::number(nValue / 10);

cPainter.setPen(QPen(QBrush(Qt::black), 2.0f));
cPainter.drawLine(width() - 2, nY, width() - fontMetrics().height() / 2 - 2, nY);
cPainter.drawText(4, nY + fontMetrics().height() / 3, strText);
} else {
cPainter.setPen(Qt::black);
cPainter.drawLine(width() - 2, nY, width() - fontMetrics().height() / 3 - 2, nY);
}
}

nY += float(physicalDpiY()) / 12.7f;
}
}
}

void ICSRulerWidget::setOrigin(int pOrigin) {
m_nOrigin = -pOrigin;

for(auto pMarker: m_lstMarkers) {
auto fValue = pMarker->property("ICS_MarkerValue").toFloat();

if(m_nOrientation == Qt::Horizontal)
pMarker->move(
pMarker->property("ICS_MarkerInverted").toBool()
? m_nOrigin + float(physicalDpiX()) / 25.4f * (m_fMaximum - fValue)
: m_nOrigin + float(physicalDpiX()) / 25.4f * fValue,
0
);
else
pMarker->move(
0,
pMarker->property("ICS_MarkerInverted").toBool()
? m_nOrigin + float(physicalDpiY()) / 25.4f * (m_fMaximum - fValue)
: m_nOrigin + float(physicalDpiY()) / 25.4f * fValue
);
}

update();
}

void ICSRulerWidget::setMaximum(float pMaximum) {
if(m_fMaximum != pMaximum) {
m_fMaximum = pMaximum;

for(int nIndex = 0; nIndex < m_lstMarkers.size(); nIndex++) {
auto fValue = markerValue(nIndex);

setMarkerRange(nIndex, 0, m_fMaximum);

if(fValue > pMaximum)
setMarkerValue(nIndex, pMaximum);
else {
if(m_nOrientation == Qt::Horizontal)
m_lstMarkers[nIndex]->move(
m_lstMarkers[nIndex]->property("ICS_MarkerInverted").toBool()
? m_nOrigin + float(physicalDpiX()) / 25.4f * (m_fMaximum - fValue)
: m_nOrigin + float(physicalDpiX()) / 25.4f * fValue,
0
);
else
m_lstMarkers[nIndex]->move(
0,
m_lstMarkers[nIndex]->property("ICS_MarkerInverted").toBool()
? m_nOrigin + float(physicalDpiY()) / 25.4f * (m_fMaximum - fValue)
: m_nOrigin + float(physicalDpiY()) / 25.4f * fValue
);
}
}

update();
}
}

void ICSRulerWidget::clearMarkers(void) {
qDeleteAll(m_lstMarkers);
update();
}


I've attached the icsrulerwidget.h file: 12423

The original Thread: http://www.qtcentre.org/threads/60546-Ruler-widget-implementation

d_stranz
4th April 2017, 23:17
I think you misunderstand what this widget does. It is not a ruler for measuring the distance between two points on the screen, it is like the bar you see at the top of Microsoft Word and other document editing programs. The picture below is from OpenOffice. I do not know how the ICSRulerWidget looks, but it is probably similar.

12425