首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在QChartView上实现选择

在QChartView上实现选择
EN

Stack Overflow用户
提问于 2018-01-09 08:28:23
回答 1查看 3.9K关注 0票数 6

我想做一个基于QChartQChartView的图表选择的实现。这些类的家族有一个很大的优势--例如易于使用的openGL动画

代码语言:javascript
复制
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);    

QChartView类提供了有用的缩放功能-- QChartView::setRubberBand()

代码语言:javascript
复制
chartView->setRubberBand(QChartView::RectangleRubberBand);

主要的问题是橡皮筋只能用于缩放,但我需要实现它的水平选择而不缩放,因为通常在音频编辑器中实现的特性:

现在,当我继承了QChartView之后,我可以在选择之后禁用缩放:

代码语言:javascript
复制
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);
    }
}

然后,我就不能在鼠标键释放事件上实现缩放操作:

代码语言:javascript
复制
void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_rubberBand.isVisible()) 
    {
        if (event->button() == Qt::LeftButton)
        {
            m_drawRubberBand = false;    
            do_nothing(); // <==
        }

    }
}

所以,我现在的问题是:

  1. 如何将视觉橡皮筋的边界映射到真实图表的坐标。也就是说,如何将所选内容映射成图表上的一行序列?现在我收到了同样错误的坐标: void::resizeEvent(QResizeEvent *event) {QChartView::resizeEvent(事件);QRect rct(QPoint(10,10),QPoint(20,20));qDebug() << mapToScene;<== }

输出:

代码语言:javascript
复制
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))
...
  1. 如何与视图一起按比例调整现有的橡胶选择?

编辑:可能是一个有用的关键字- QGraphicsScene::setSelectionArea()

Qt 5芯片示例,提供了不错的橡皮筋选择。,但示例基于QGraphicsView,而不是基于QChartView。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-10 14:45:42

由于对这个答案的回答:在QChartView的轴系统中获取鼠标坐标,这个问题得到了解决。

关键时刻:有必要调用Q图::mapToValue()进行正确的坐标转换:

代码语言:javascript
复制
QPointF ChartView::point_to_chart(const QPoint &pnt)
{
    QPointF scene_point = mapToScene(pnt);
    QPointF chart_point = chart()->mapToValue(scene_point);

    return chart_point;
}

以及逆变换:

代码语言:javascript
复制
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;
}

我就是这样在resizeEvent上实现橡皮筋尺寸调整的。

首先,我保存鼠标释放事件上当前的橡皮筋:

代码语言:javascript
复制
void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_rubberBand.isVisible()) 
    {
        update_rubber_band(event);            
        m_drawRubberBand = false;
        save_current_rubber_band(); <==            
    }
}

其中:

代码语言:javascript
复制
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());
}

和:

代码语言:javascript
复制
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);
}

和如何在“调整大小”事件上重新绘制橡胶:

代码语言:javascript
复制
void ChartView::resizeEvent(QResizeEvent *event)
{
    QChartView::resizeEvent(event);

    if (m_rubberBand.isVisible())
    {
        restore_rubber_band();
    }

    apply_nice_numbers();
}

其中:

代码语言:javascript
复制
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));
}

别忘了“不错的数字”

代码语言:javascript
复制
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();
        }
    }
}

这种逻辑在起作用。调整大小之前:

调整大小后:

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48164065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档