Seite 1 von 1
QwtPlotCurve::closestPoint
Verfasst: 26. Oktober 2009 09:56
von christophr
Hallo zusammen,
ich möchte einen Tooltip im Diagramm zu dem Punkt anzeigen, der sich unter dem Mauszeiger befindet. Dazu verwende ich QwtPlotCurve::closestPoint. Dort wird jedoch mit einem Offset gearbeitet. Mit etwas Augenmaß würde ich sagen, dass die Verschiebung in X und Y etwa der Achsenskalierung (also des langen Strichs mit den Ticks, nicht die Achsenlabel) entspricht.
Handelt es sich dabei um einen Fehler oder muss ich selber den Mauszeiger noch in ein Child-Widget mappen bevor ich closestPoint mit den Koordinaten füttern kann?
Ich verwende Qwt 5.0.1 mit Qt 4.2.1.
Gruß,
Christoph
Edit:
Anbei ein Screenshot mit dem Problem. Das schwarze Kreuz ist der Mauszeiger, rot umrandet ist der Punkt, den er mit 0,5 Pixeln Abstand berechnet hat.
Verfasst: 6. November 2009 09:36
von christophr
Da ich immer noch keine Lösung für das Problem habe, zwischendurch aber auch mit anderen Projekten beschäftigt war, versuche ich mal ein kleines
*push*
Gruß,
Christoph
Verfasst: 7. November 2009 13:12
von Uwe
Ohne zu schreiben welche Koordinaten wie umrechnest kannst Du auch keine sinnvolle Antwort erwarten.
Ich würde Dir vorschlagen einfach von QwtPlotPicker abzuleiten und QwtPlotPicker::trackerText() zu überladen. Dort gibst Du nur dann einen nichtleeren Text zurück, wenn die Position in der Nähe eines Punkts liegt. Wenn Du setTrackerMode(QwtPlotPicker::AlwaysOn) aktivierst solltest Du haben was Du benötigst.
QwtPlotCurve::closestPoint iteriert über all Punkte und ist damit natürlich sehr langsam. Wenn Du viele Punkte hast solltest Du in jedem Fall eine räumlich Vorsortierung ( z.B Quadrantenbaum ) verwenden.
Uwe
Verfasst: 9. November 2009 21:32
von christophr
QwtPlotPicker geht aus zwei Gründen nicht:
1. Kann man ihn mit Escape beenden und
2. ist ein Tooltip gefordert, da noch zwei Grafiken in Abhänigkeit des Punktes angezeigt werden sollen.
Reproduzieren lässt sich das Verhalten mit folgender kleiner Methode:
Code: Alles auswählen
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if( (object == ui->signalPlot) && (event->type() == QEvent::ToolTip) )
{
QHelpEvent* he( static_cast<QHelpEvent*>(event) );
double distance( 0.0 );
int cp( this->curves[0]->closestPoint( he->pos(), &distance ) );
if( (cp >= 0) && (distance < 5.0) )
{
QString text = QString( "x: %1\ny: %2\nd: %3" )
.arg( this->data[0]->x(cp) )
.arg( this->data[0]->y(cp) )
.arg(distance);
QToolTip::showText( he->globalPos(), text, ui->signalPlot );
return true;
}
}
return false;
}
zusammen mit
Code: Alles auswählen
MainWindow::MainWindow(...)
{
[...]
ui->signalPlot->installEventFilter( this );
}
Der Code ist aus dem Gedächtnis geschrieben und auf das wesentlichste beschränkt. ui->signalPlot ist dabei das QwtPlot-Widget, welches vom Designer bzw. uic erstellt wurde.
Das Verhalten mit dem Offset zwischen Mauszeiger und gefundenem Punkt zeigt sich damit stichprobenartig (>10 Kurven mit unterschiedlichen Wertebereichen von 0.001 bis 240 Mio.) bei mir bei allen Datensätzen.
Verfasst: 10. November 2009 07:57
von cypher
Hi,
die positionen mit denen closesPoint etc. funktionen rechnen sind relativ zur plotting region nich zum QwtPlot Widget.
(Hatte das zwar nich bei closesPoint aber bei anderen ähnlichen Sachen, daher denke ich dass das hier auch das Problem ist)
Daher he->pos x/y umrechnen in nen neuen QPoint und diesen übergeben. Umrechnen geht mit:
//pos relativ zu QwtPlot nach position auf plotting region
double QwtPlot::invTransform (int axisId, int pos)
//umgekehrt
int QwtPlot::transform (int axisId, double value)
axisId is dabei QwtPlot::yLeft etc.. ->
enum Axis {
yLeft,
yRight,
xBottom,
xTop,
axisCnt
}
hier nochmal zum nachlesen
http://qwt.sourceforge.net/class_qwt_plot.html
hoffe das hilft

Verfasst: 12. November 2009 11:02
von christophr
Hallo!
Code: Alles auswählen
double x(( _ui.signalPlot->invTransform( QwtPlot::xBottom, event->pos().x() ) ));
double y(( _ui.signalPlot->invTransform( QwtPlot::yLeft, event->pos().y() ) ));
QPoint regionPoint( static_cast<int>(x), static_cast<int>(y) );
qDebug()
<< "\tConverted widget point" << event->pos() << "to plot region point" << regionPoint;
Mit obigem Code stehen in regionPoint die mathematische X- und Y-Koordinate. Wenn ich damit QwtPlotCurve::closestPoint füttere, gibt er mir als Minimalabstand (je nach angezeigter Kurve) Werte zurück, die größer als meine Bildschirmdiagonale sind. Damit dürfte das nicht der richtige Ansatz sein.
Heißt also, dass ich mir der Transformation bei diesem Ansatz nicht weiter komme. Wenn keiner einen anderen Vorschlag hat, werde ich wohl closestPoint selber schreiben. Ist ja im ersten Ansatz nur eine Iteration über alle Punkte der Kurve und finden des minimalen Abstands.
Gruß,
Christoph