Kohshi's Blog
2013/12/15
QCustomPlotでマウスホバー時に値を表示
前回[QCustomPlotがいい感じ](http://kohshi.blogspot.jp/2013/12/qcustomplot.html)でグラフ表示の基本を書いてみたので 次はマウスホバー+グラフ値の表示方法について書いてみる。 マウスホバーはQCPItemTracerをつかう。 QCustomPlotは横軸のことをkeyAxis, 縦軸をvalueAxisと呼ぶがQCPMouseTrace::setGraphKey(int key)でkeyを 更新すると、対応するvalue値を保持して、指定したindicatorでグラフ内の対象箇所を示してくれる機能がある。 でも一点難点があるのはQCPGraphにだけ対応していてQCPBarsには対応してない点。 なので前回あげたヒストグラムには適応できない。 というわけで、ちょっと強引にQCPItemTracerにsetBars()とsetBarsKey()を追加してメンバー変数にQCPBarsを持たせてみる。 ```qcustomplot.h void setBars(QCPBars *bars); void setBarsKey(double key); QCPBars *mBars; ``` ```qcustomplot.cppp void QCPItemTracer::setBars(QCPBars *bars){ if(bars) { if(bars->parentPlot() == mParentPlot){ position->setType(QCPItemPosition::ptPlotCoords); position->setAxes(bars->keyAxis(), bars->valueAxis()); mBars = bars; updatePosition(); } else qDebug() << Q_FUNC_INFO << "bars isn't in same QCustomPlot instance as this item"; } else { mBars = 0; } } void QCPItemTracer::setBarsKey(double key){ setGraphKey(key); } // QCPItemTracer::updatePosition()の末尾に以下を追加 else if(mBars){ if(mBars->data()->size() > 1){ QCPBarDataMap::const_iterator first = mBars->data()->constBegin(); QCPBarDataMap::const_iterator last = mBars->data()->constEnd()-1; if (mGraphKey < first.key()) position->setCoords(first.key(), first.value().value); else if (mGraphKey > last.key()) position->setCoords(last.key(), last.value().value); else { QCPBarDataMap::const_iterator it = mBars->data()->lowerBound(mGraphKey); if (it != first) // mGraphKey is somewhere between iterators { QCPBarDataMap::const_iterator prevIt = it-1; if (mInterpolating) { // interpolate between iterators around mGraphKey: double slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key()); position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value); } else { // find iterator with key closest to mGraphKey: if (mGraphKey < (prevIt.key()+it.key())*0.5) it = prevIt; position->setCoords(it.key(), it.value().value); } } else // mGraphKey is exactly on first iterator position->setCoords(it.key(), it.value().value); } }else if (mBars->data()->size() == 1) { QCPBarDataMap::const_iterator it = mBars->data()->constBegin(); position->setCoords(it.key(), it.value().value); } else qDebug() << Q_FUNC_INFO << "graph has no data"; //Add a comment to this line } ``` これでQCPItemTracerでQCPBarsの値を保持するようになった(はず)。 でもってQCPCustomPlotでグラフを描画したいクラスで以下のようにQItemTracerを初期化する。 ``` mpMouseTracer = new QCPItemTracer(ui.histogram); ui.histogram->addItem(mpMouseTracer);// Graph上に表示を設定(histogram = QCustomPlot) mpMouseTracer->setBars(mpHistogramBars);// ここ以外はオリジナルQCPItemTracerと同じ mpMouseTracer->setGraphKey(0.0);// 初期key mpMouseTracer->setStyle(QCPItemTracer::tsCircle);// 対象点を●で表示他にもCrossなどがある mpMouseTracer->setPen(QPen(Qt::red));// ●の線の色 mpMouseTracer->setBrush(Qt::red);// ●の色 mpMouseTracer->setSize(7);//●の大きさ // 今回はグラフマウスホバーで値を表示したいのでQCustomPlot::mouseMove signal時にslotを読んでもらう connect(ui.histogram, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(histogramMouseMoved(QMouseEvent*))); ``` ``` void MainWindow::histogramMouseMoved(QMouseEvent *event){ QPoint pos = event->pos(); double key = floor(mpHistogramBars->keyAxis()->pixelToCoord(pos.x())); mpMouseTracer->setBarsKey(key); // 最新のkey値をセット ui.histogram->replot();// repolotして初めて新しいポジションに●が移動する } ``` とすると↓のように●でマウスホバー点をTraceしてくれる。
テキスト(key, value)の表示にはQCPItemTextを使う。 mpMouseTracerと同様にこんな感じで設定して・・ ``` mpMouseText = new QCPItemText(ui.histogram); ui.histogram->addItem(mpMouseText); mpMouseText->position->setType(QCPItemPosition::ptAxisRectRatio); mpMouseText->setFont(QFont(font().family(), 12)); mpMouseText->setPositionAlignment(Qt::AlignLeft); mpMouseText->position->setCoords(QPointF(0, 0)); mpMouseText->setText("(-, -)"); ``` histogramMouseMoved slotで更新する。 ``` void MainWindow::histogramMouseMoved(QMouseEvent *event){ QPoint pos = event->pos(); double key = floor(mpHistogramBars->keyAxis()->pixelToCoord(pos.x())); mpMouseTracer->setBarsKey(key); double x, y; // 以下は文字がグラフ外に出て行かないように適当にclipしている x = qBound(0., mpMouseTracer->position->key() / mpHistogramBars->keyAxis()->range().size(), 0.75); y = qBound(0., 1. - mpMouseTracer->position->value() / mpHistogramBars->valueAxis()->range().size(), 0.9);// value coord is TopLeft origin mpMouseText->position->setCoords(x, y); mpMouseText->setText("(" + QString::number(mpMouseTracer->position->key()) + ", " + QString::number(mpMouseTracer->position->value()) + ")"); ui.histogram->replot(); } ``` これでOK. UPDATE: こんな感じ↓
参考までに * tsCrosshair
* tsPlug
* tsSquare
ツイート
0 件のコメント:
コメントを投稿
次の投稿
前の投稿
ホーム
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿