silent_missile
25th June 2014, 09:19
now I'm developing a software to plot and manipulate some lines in the GUI, but I meet some difficulties.
1) I hope to have a fixed scale when resize the window or the tabwidget, so that means the scale range would change but the div would not change. I read all examples of qwt, but I can't find it. it seems QwtPlotRescaler can realize it, but it seems conflict with the 2nd requirement.
2) I have a tabwidget with more than 1 tabs for the manipulation, I hope they can use same scale, it seems I can add signal and slot connection to solve it, but when I test it, I found there is different display when I scale it by mouse wheel or resize the window. because only one tab is shown, so the hidden tab would not rescale.
3) I hope to add manipulation of the plot. left button to manipulate the point to move and replot the line simultaneously, mid button to move, and wheel to zoom, also mouse position as the zoom center. I find some helpful information about it. QwtPlotMagnifier can help the wheel zoom, but I can't find the setting of zoom center, it always zoom by original point. QwtPlotPanner can help the move operation, what I need to do is just to change the mouse button to mid button. but I can't find any class can help for the point drag and move manipulation. In examples I found the event_filter example, it's very similar like what I need, and I tried to use similar method, but it can't work, if I set the mouse button to left button, then I can't move the point.
A simple summary is if I want to have a lot of operations on keyboard and mouse, such as:
a) left button single click/double click means different action
b) left button drag from empty position is rubber band picker, from some element means drag the element
c) midbutton drag to move the plot
d) right button single click zoom to fit, drag means rubber band zoom
e) left and mid button together means some operation
f) keep left pressed, and press mid button then release left button means some operation
...a lot of operations, how can I realize it?
eventFilter maybe a good solution. but if I want to use existing classes within qwt to move plot, move item, zoom...how can I call them in the eventFilter?
class main_window : public QMainWindow
{
Q_OBJECT
public:
explicit main_window(QWidget *parent = 0);
~main_window();
signals:
public slots:
private:
QTabWidget *_tabs;
};
main_window::main_window(QWidget *parent) :
QMainWindow(parent)
{
_tabs = new QTabWidget(this);
for(int n1(0);n1<2;++n1
{
_tabs->addTab(new QWidget(), QString::number(n1));
_plots.push_back(new main_plot(_tabs->widget(n1)));
QGridLayout *lay = new QGridLayout(meridional_tabs->widget(n1));
lay->addWidget(main_plots[n1],0,0);
main_plots[n1]->plot_curves();
for(int n2(0);n2<static_cast<int>(main_plots.size());++n2)
{
if(n1!=n2)
{
connect((QObject*)(main_plots[n1]->axisWidget(QwtPlot::xBottom)),SIGNAL(scaleDivChang ed()),meridional_plots[n2],SLOT(scaleDivChangedSlot()));
connect((QObject*)(main_plots[n2]->axisWidget(QwtPlot::xBottom)),SIGNAL(scaleDivChang ed()),meridional_plots[n1],SLOT(scaleDivChangedSlot()));
}
}
}
setCentralWidget(_tabs);
}
class main_plot : public QwtPlot
{
Q_OBJECT
public:
main_plot(QWidget *parent = nullptr);
public Q_SLOTS:
void plot_curves();
private:
QVector<QwtPlotCurve*> curves;
QwtPlotRescaler *rescaler;
QwtPlotMagnifier *pm;
QwtPlotPanner *pp;
private Q_SLOTS:
void scaleDivChangedSlot();
};
ain_plot::main_plot(QWidget *parent ):
QwtPlot( parent )
{
setCanvasColor( Qt::white );
// Avoid jumping when label with 3 digits
// appear/disappear when scrolling especially for y axis
QwtScaleDraw *sdy = axisScaleDraw( QwtPlot::yLeft );
sdy->setMinimumExtent( sdy->extent( axisWidget( QwtPlot::yLeft )->font() ) );
setAxisTitle(QwtPlot::yLeft, "r");
QwtScaleDraw *sdx = axisScaleDraw( QwtPlot::xBottom );
sdx->setMinimumExtent( sdx->extent( axisWidget( QwtPlot::xBottom )->font() ) );
setAxisTitle(QwtPlot::xBottom, "z");
plotLayout()->setAlignCanvasToScales( true );
rescaler = new QwtPlotRescaler(canvas(),QwtPlot::xBottom,QwtPlotR escaler::Expanding);
rescaler->setAspectRatio(QwtPlot::yLeft,1.0);
rescaler->setAspectRatio(QwtPlot::xTop,0.0);
rescaler->setAspectRatio(QwtPlot::yRight,0.0);
pm = new QwtPlotMagnifier( canvas() );
pp = new QwtPlotPanner(canvas());
pp->setMouseButton(Qt::MidButton,Qt::NoModifier);
replot();
}
void main_plot::plot_curves()
{
//add some code to plot a simple curve
}
void main_plot::scaleDivChangedSlot()
{
QwtPlot *plt = qobject_cast<QwtPlot*>((sender())->parent());
QwtInterval intv = plt->axisInterval (QwtPlot::xBottom);
this->setAxisScale(QwtPlot::xBottom, intv.minValue(), intv.maxValue());
intv = plt->axisInterval (QwtPlot::yLeft);
this->setAxisScale(QwtPlot::yLeft, intv.minValue(), intv.maxValue());
this->replot();
}
also English is not my mother language, sometimes I can't understand the difference of scale/zoom, div/scale/interval, if anybody can explain it to me more visually, I appreciate very much.
1) I hope to have a fixed scale when resize the window or the tabwidget, so that means the scale range would change but the div would not change. I read all examples of qwt, but I can't find it. it seems QwtPlotRescaler can realize it, but it seems conflict with the 2nd requirement.
2) I have a tabwidget with more than 1 tabs for the manipulation, I hope they can use same scale, it seems I can add signal and slot connection to solve it, but when I test it, I found there is different display when I scale it by mouse wheel or resize the window. because only one tab is shown, so the hidden tab would not rescale.
3) I hope to add manipulation of the plot. left button to manipulate the point to move and replot the line simultaneously, mid button to move, and wheel to zoom, also mouse position as the zoom center. I find some helpful information about it. QwtPlotMagnifier can help the wheel zoom, but I can't find the setting of zoom center, it always zoom by original point. QwtPlotPanner can help the move operation, what I need to do is just to change the mouse button to mid button. but I can't find any class can help for the point drag and move manipulation. In examples I found the event_filter example, it's very similar like what I need, and I tried to use similar method, but it can't work, if I set the mouse button to left button, then I can't move the point.
A simple summary is if I want to have a lot of operations on keyboard and mouse, such as:
a) left button single click/double click means different action
b) left button drag from empty position is rubber band picker, from some element means drag the element
c) midbutton drag to move the plot
d) right button single click zoom to fit, drag means rubber band zoom
e) left and mid button together means some operation
f) keep left pressed, and press mid button then release left button means some operation
...a lot of operations, how can I realize it?
eventFilter maybe a good solution. but if I want to use existing classes within qwt to move plot, move item, zoom...how can I call them in the eventFilter?
class main_window : public QMainWindow
{
Q_OBJECT
public:
explicit main_window(QWidget *parent = 0);
~main_window();
signals:
public slots:
private:
QTabWidget *_tabs;
};
main_window::main_window(QWidget *parent) :
QMainWindow(parent)
{
_tabs = new QTabWidget(this);
for(int n1(0);n1<2;++n1
{
_tabs->addTab(new QWidget(), QString::number(n1));
_plots.push_back(new main_plot(_tabs->widget(n1)));
QGridLayout *lay = new QGridLayout(meridional_tabs->widget(n1));
lay->addWidget(main_plots[n1],0,0);
main_plots[n1]->plot_curves();
for(int n2(0);n2<static_cast<int>(main_plots.size());++n2)
{
if(n1!=n2)
{
connect((QObject*)(main_plots[n1]->axisWidget(QwtPlot::xBottom)),SIGNAL(scaleDivChang ed()),meridional_plots[n2],SLOT(scaleDivChangedSlot()));
connect((QObject*)(main_plots[n2]->axisWidget(QwtPlot::xBottom)),SIGNAL(scaleDivChang ed()),meridional_plots[n1],SLOT(scaleDivChangedSlot()));
}
}
}
setCentralWidget(_tabs);
}
class main_plot : public QwtPlot
{
Q_OBJECT
public:
main_plot(QWidget *parent = nullptr);
public Q_SLOTS:
void plot_curves();
private:
QVector<QwtPlotCurve*> curves;
QwtPlotRescaler *rescaler;
QwtPlotMagnifier *pm;
QwtPlotPanner *pp;
private Q_SLOTS:
void scaleDivChangedSlot();
};
ain_plot::main_plot(QWidget *parent ):
QwtPlot( parent )
{
setCanvasColor( Qt::white );
// Avoid jumping when label with 3 digits
// appear/disappear when scrolling especially for y axis
QwtScaleDraw *sdy = axisScaleDraw( QwtPlot::yLeft );
sdy->setMinimumExtent( sdy->extent( axisWidget( QwtPlot::yLeft )->font() ) );
setAxisTitle(QwtPlot::yLeft, "r");
QwtScaleDraw *sdx = axisScaleDraw( QwtPlot::xBottom );
sdx->setMinimumExtent( sdx->extent( axisWidget( QwtPlot::xBottom )->font() ) );
setAxisTitle(QwtPlot::xBottom, "z");
plotLayout()->setAlignCanvasToScales( true );
rescaler = new QwtPlotRescaler(canvas(),QwtPlot::xBottom,QwtPlotR escaler::Expanding);
rescaler->setAspectRatio(QwtPlot::yLeft,1.0);
rescaler->setAspectRatio(QwtPlot::xTop,0.0);
rescaler->setAspectRatio(QwtPlot::yRight,0.0);
pm = new QwtPlotMagnifier( canvas() );
pp = new QwtPlotPanner(canvas());
pp->setMouseButton(Qt::MidButton,Qt::NoModifier);
replot();
}
void main_plot::plot_curves()
{
//add some code to plot a simple curve
}
void main_plot::scaleDivChangedSlot()
{
QwtPlot *plt = qobject_cast<QwtPlot*>((sender())->parent());
QwtInterval intv = plt->axisInterval (QwtPlot::xBottom);
this->setAxisScale(QwtPlot::xBottom, intv.minValue(), intv.maxValue());
intv = plt->axisInterval (QwtPlot::yLeft);
this->setAxisScale(QwtPlot::yLeft, intv.minValue(), intv.maxValue());
this->replot();
}
also English is not my mother language, sometimes I can't understand the difference of scale/zoom, div/scale/interval, if anybody can explain it to me more visually, I appreciate very much.