PDA

View Full Version : displaying proper x-coordinates of mouse move



chmodfx
3rd December 2013, 13:39
Hello all,

I started to build application based on stockchart example. Basing on CanvasPicker class I would like to handle mouse moves, forward them by emitting signal to main class and there display selected coordinates and draw lines from it on the chart. It is simple idea of technical analysis above the bar chart. My problem is coordinates are not properly displayed and lets say if I select point and move mouse once on 1.03(x-scale is qwtDate) on the x-scale and then change application window size (it is f.e. maximize) and after that once again move mouse on 1.03 -my cooridnates will be different.


CanvasPicker::CanvasPicker(QwtPlot *plot):
QObject(plot),
d_selectedCurve(NULL),
d_selectedPoint(-1)
{
plot->setMouseTracking(true);
QwtPlotCanvas *canvas = qobject_cast<QwtPlotCanvas*>(plot->canvas());
canvas->installEventFilter(this);

canvas->setFocusPolicy(Qt::StrongFocus);
canvas->setFocusIndicator(QwtPlotCanvas::ItemFocusIndicato r);
canvas->setFocus();

shiftCurveCursor(true);
}

bool CanvasPicker::event(QEvent *e)
{
if ( e->type() == QEvent::User )
{
showCursor(true);
return true;
}
return QObject::event(e);
}

bool CanvasPicker::eventFilter(QObject *object, QEvent *e)
{
if ( object != (QObject *)plot()->canvas() )
return false;

switch(e->type())
{
case QEvent::FocusIn:
showCursor(true);
case QEvent::FocusOut:
showCursor(false);

case QEvent::Paint:
{
QApplication::postEvent(this, new QEvent(QEvent::User));
break;
}
case QEvent::MouseButtonPress:
{
select(((QMouseEvent *)e)->pos());
return true;
}
case QEvent::MouseMove:
{
move(((QMouseEvent *)e)->pos());
return true;
}
default:
break;
}
return QObject::eventFilter(object, e);
}

void CanvasPicker::select(const QPoint &pos)
{
emit createCurve();
TAcurveDataX[0]=pos.x();
TAcurveDataY[0]=pos.y();
}

void CanvasPicker::move(const QPoint &pos)
{
TAcurveDataX[1]=pos.x();
TAcurveDataY[1]=pos.y();
emit emitCurve(TAcurveDataX[0],TAcurveDataY[0],TAcurveDataX[1],TAcurveDataY[1]);

}



Above is CanvasPicker class, simple idea is to handle mouse click and mouse move to create 2 points -
{TAcurveDataX[0],TAcurveDataY[0]},
{TAcurveDataX[1],TAcurveDataY[1]}.

These points are forwarding into main class.
After create QwtPlotCurve and connect with appropriate slots like below:


d_plot[chartUseNumber] = new Plot( this );
CanvasPicker *pick=new CanvasPicker(d_plot[chartUseNumber]);

connect(pick,SIGNAL(createCurve()),this,SLOT(Creat eNewCanvasCurve()));
connect(pick,SIGNAL(emitCurve(double,double,double ,double)),this,SLOT(ReceiveCurveData(double,double ,double,double)));


Creating plot:


Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
this->setMouseTracking(true);
this->curve=NULL;
QwtDateScaleDraw *scaleDraw = new DateScaleDraw( Qt::UTC );
QwtDateScaleEngine *scaleEngine = new QwtDateScaleEngine( Qt::UTC );

//setAxisTitle( QwtPlot::xBottom, QString( "2010" ) );
setAxisScaleDraw( QwtPlot::xBottom, scaleDraw );
setAxisScaleEngine( QwtPlot::xBottom, scaleEngine );
setAxisLabelRotation( QwtPlot::xBottom, -50.0 );
setAxisLabelAlignment( QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom );

Legend *legend = new Legend;
//insertLegend( legend, QwtPlot::RightLegend );

this->global_sample_count=255;
this->current_instr=0;

QwtPlotPanner *panner = new QwtPlotPanner( canvas() );
panner->setMouseButton( Qt::MidButton );

connect( legend, SIGNAL( checked( QwtPlotItem *, bool, int ) ),
SLOT( showItem( QwtPlotItem *, bool ) ) );
}

void Plot::populate2(int instrument,int start,int end,int mode)
{

GridItem *gridItem = new GridItem();
gridItem->attach( this );

const Qt::GlobalColor colors[] =
{
Qt::red,
Qt::blue,
Qt::darkCyan,
Qt::darkMagenta,
Qt::darkYellow
};

if(curve!=NULL)
{
delete curve;
}

const int numColors = sizeof( colors ) / sizeof( colors[0] );
if(instrument!=0)
{
QuoteFactory::Stock stock = static_cast<QuoteFactory::Stock>( instrument-1 );
curve = new QwtPlotTradingCurve();
curve->setTitle( QuoteFactory::title( stock ) );
curve->setOrientation( Qt::Vertical );
curve->setSamples( QuoteFactory::samples_fn( stock,start,end,mode ) );
curve->setSymbolExtent( 12 * 3600 * 1000.0 );
curve->setMinSymbolWidth( 3 );
curve->setMaxSymbolWidth( 15 );
const Qt::GlobalColor color = colors[ instrument % numColors ];
curve->setSymbolPen( color );
curve->setSymbolBrush( QwtPlotTradingCurve::Decreasing, color );
curve->setSymbolBrush( QwtPlotTradingCurve::Increasing, Qt::white );
curve->attach( this );
showItem( curve, true );
}
}


I use it in the following way:


void MainWindow::ReceiveCurveData(double x1,double y1,double x2,double y2)
{
QDateTime year2010( QDate( 2010, 1, 1 ), QTime( 0, 0 ), Qt::UTC );
QVariant yvar;
yvar=( year2010.addDays( x1 )) ;
ine->setText(yvar.toString());

double arr1[2];
double arr2[2]={(d_plot[0]->invTransform(currvamac->yAxis(), y1)),(d_plot[0]->invTransform(currvamac->yAxis(), y2))};

QDateTime dt1 = QwtDate::toDateTime(x1);
QDateTime dt2 = QwtDate::toDateTime(x2);
double arr1o=QwtDate::toDouble(dt1);
double arr2o=QwtDate::toDouble(dt2);
double d1=QwtDate::toDouble( year2010.addDays( x1 )) ;
double d2=QwtDate::toDouble( year2010.addDays( x2 )) ;
arr1[0] = d1;
arr1[1] = d2;

currvamac->setSamples(arr1,arr2,2);
d_plot[0]->replot();
}



There is no problem with y-coordinates, only with x-coordinates. Thanks for help in advance.

chmodfx
3rd December 2013, 21:19
Ok, after digging in it I can express it more clear.

Without QwtDateScale as scale for X-axis it works great. with normal x-axis,y-axis and invTransform() on both x points and y points everything works successful.
But how to transform pos.x() into QwtDateScaleDraw position?




OK, I solved it.
It seems it is enough to use invTransform for both axes. I don't know why did it cause problems, some stupid mistakes.