Vla*_*hov 6 plot qt qt5 qtcharts qchart
我想实现基于QChart和QChartView的图表选择。这些类的家族有一个很大的优势 -易于使用 openGL和动画,例如:
QLineSeries *series = new QLineSeries();
series->setUseOpenGL(true); // <==
QChart *chart = new QChart();
chart->addSeries(series);
chart->setAnimationOptions(QChart::AllAnimations); // <==
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
Run Code Online (Sandbox Code Playgroud)
该QChartView类提供了有用的缩放功能- QChartView :: setRubberBand() :
chartView->setRubberBand(QChartView::RectangleRubberBand);
Run Code Online (Sandbox Code Playgroud)
主要问题是橡皮筋只能用于缩放,但我需要实现它用于不缩放的水平选择,因为该功能通常在音频编辑器中实现:
现在,当我继承 QChartView 时,我可以在选择后禁用缩放:
class ChartView : public QChartView
...
bool m_drawRubberBand;
QRubberBand m_rubberBand;
...
ChartView::ChartView(QChart *chart, QWidget *parent)
: QChartView(chart, parent)
{
setRubberBand(QChartView::HorizontalRubberBand);
}
...
// Just copy-paste from the Qt 5 sources - file \Src\qtcharts\src\charts\qchartview.cpp:
/*!
If the rubber band rectangle is displayed in the press event specified by
\a event, the event data is used to update the rubber band geometry.
Otherwise, the default QGraphicsView::mouseMoveEvent() implementation is called.
*/
void ChartView::mouseMoveEvent(QMouseEvent *event)
{
if (m_drawRubberBand && m_rubberBand.isVisible())
{
QRect rect = chart()->plotArea().toRect();
int width = event->pos().x() - m_rubberBandOrigin.x();
int height = event->pos().y() - m_rubberBandOrigin.y();
if (!rubberBand().testFlag(VerticalRubberBand))
{
m_rubberBandOrigin.setY(rect.top());
height = rect.height();
}
if (!rubberBand().testFlag(HorizontalRubberBand))
{
m_rubberBandOrigin.setX(rect.left());
width = rect.width();
}
m_rubberBand.setGeometry(QRect(m_rubberBandOrigin.x(), m_rubberBandOrigin.y(), width, height).normalized());
}
else
{
QGraphicsView::mouseMoveEvent(event);
}
}
Run Code Online (Sandbox Code Playgroud)
那么我就不能在鼠标键释放事件上实现缩放操作:
void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
if (m_rubberBand.isVisible())
{
if (event->button() == Qt::LeftButton)
{
m_drawRubberBand = false;
do_nothing(); // <==
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我现在的问题:
可视橡皮筋的边界如何映射到真实图表的坐标。即,如何将选择映射到图表上的线系列?现在我收到同样错误的坐标:
void MyView::resizeEvent(QResizeEvent *event)
{
QChartView::resizeEvent(event);
QRect rct(QPoint(10, 10), QPoint(20, 20));
qDebug() << mapToScene(rct); <==
}
Run Code Online (Sandbox Code Playgroud)输出:
QPolygonF(QPointF(10,10)QPointF(21,10)QPointF(21,21)QPointF(10,21))
QPolygonF(QPointF(10,10)QPointF(21,10)QPointF(21,21)QPointF(10,21))
QPolygonF(QPointF(10,10)QPointF(21,10)QPointF(21,21)QPointF(10,21))
QPolygonF(QPointF(10,10)QPointF(21,10)QPointF(21,21)QPointF(10,21))
...
Run Code Online (Sandbox Code Playgroud)
编辑:可能是一个有用的关键字 - QGraphicsScene::setSelectionArea()。
Qt 5 芯片示例提供了很好的橡皮筋选择,但该示例基于QGraphicsView,而不是基于 QChartView。
感谢对这个答案的回复,问题得到了解决:Get mouse conventions in QChartView's axis system
关键时刻:有必要调用QChart::mapToValue()来进行正确的坐标转换:
QPointF ChartView::point_to_chart(const QPoint &pnt)
{
QPointF scene_point = mapToScene(pnt);
QPointF chart_point = chart()->mapToValue(scene_point);
return chart_point;
}
Run Code Online (Sandbox Code Playgroud)
以及逆变换:
QPoint ChartView::chart_to_view_point(QPointF char_coord)
{
QPointF scene_point = chart()->mapToPosition(char_coord);
QPoint view_point = mapFromScene(scene_point);
return view_point;
}
Run Code Online (Sandbox Code Playgroud)
这就是我在resizeEvent上实现橡皮筋大小调整的方法。
首先,我在鼠标释放事件上保存当前的橡皮筋:
void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
if (m_rubberBand.isVisible())
{
update_rubber_band(event);
m_drawRubberBand = false;
save_current_rubber_band(); <==
}
}
Run Code Online (Sandbox Code Playgroud)
在哪里:
void ChartView::update_rubber_band(QMouseEvent * event)
{
QRect rect = chart()->plotArea().toRect();
int width = event->pos().x() - m_rubberBandOrigin.x();
int height = event->pos().y() - m_rubberBandOrigin.y();
if (!rubberBand().testFlag(VerticalRubberBand))
{
m_rubberBandOrigin.setY(rect.top());
height = rect.height();
}
if (!rubberBand().testFlag(HorizontalRubberBand))
{
m_rubberBandOrigin.setX(rect.left());
width = rect.width();
}
m_rubberBand.setGeometry(QRect(m_rubberBandOrigin.x(), m_rubberBandOrigin.y(), width, height).normalized());
}
Run Code Online (Sandbox Code Playgroud)
和:
void ChartView::save_current_rubber_band()
{
QRect rect = m_rubberBand.geometry();
QPointF chart_top_left = point_to_chart(rect.topLeft());
m_chartRectF.setTopLeft(chart_top_left);
QPointF chart_bottom_right = point_to_chart(rect.bottomRight());
m_chartRectF.setBottomRight(chart_bottom_right);
}
Run Code Online (Sandbox Code Playgroud)
以及我如何在调整大小事件中重新绘制橡胶:
void ChartView::resizeEvent(QResizeEvent *event)
{
QChartView::resizeEvent(event);
if (m_rubberBand.isVisible())
{
restore_rubber_band();
}
apply_nice_numbers();
}
Run Code Online (Sandbox Code Playgroud)
在哪里:
void ChartView::restore_rubber_band()
{
QPoint view_top_left = chart_to_view_point(m_chartRectF.topLeft());
QPoint view_bottom_right = chart_to_view_point(m_chartRectF.bottomRight());
m_rubberBandOrigin = view_top_left;
m_rubberBand.setGeometry(QRect(view_top_left, view_bottom_right));
}
Run Code Online (Sandbox Code Playgroud)
并且不要忘记“好数字”:
void ChartView::apply_nice_numbers()
{
QList<QAbstractAxis*> axes_list = chart()->axes();
for each(QAbstractAxis* abstract_axis in axes_list)
{
QValueAxis* value_axis = qobject_cast<QValueAxis*>(abstract_axis);
if (value_axis)
{
value_axis->applyNiceNumbers();
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3294 次 |
最近记录: |