如何将鼠标单击的坐标从Flickable发送到ListView?

时间:2018-10-24 15:56:09

标签: android qt qml

我正在为Android开发应用程序。

我在ListView中放置了一些ChartView。 在ListView上方,我有一个Flickable可以在x轴上同步滚动ChartViews。

我需要在用户点击的图表上显示该点的坐标。

但是我不能,因为flickable会捕获鼠标单击事件,并且不会将其传播到下面的其他对象。

我需要鼠标事件到达用户点击的特定委托。 it lookes like this

  1. 有可能解决这个问题吗?
  2. 有没有一种方法可以在滑动过程中获取鼠标坐标?
  3. 是否有一种将鼠标事件传播到ListView的方式,就像它们来自用户一样?

Rectangle {
color: "#ffffff"
Component {
    id: chartDelegate
    Rectangle {
        id: rootDelegRect

        anchors {left: parent.left; right: parent.right }
        height: 350

        ChartView {
            anchors { fill: parent;}
            x: -10
            y: -10
            width: parent.width + 20
            height: parent.height + 20

            legend.visible: false

            LineSeries {
                name: "LineSeries"
                axisX: ValueAxis {
                    min: 0
                    max: 4
                    labelFormat: "%.0f"
                }
                axisY: ValueAxis {
                    min: 0
                    max: 6
                    labelFormat: "%.0f"
                }
                XYPoint { x: 0; y: 0.0 }
                XYPoint { x: 1; y: 5.2 }
                XYPoint { x: 2; y: 2.4 }
                XYPoint { x: 3; y: 0.1 }
                XYPoint { x: 4; y: 5.1 }
            }
        }


        MouseArea {
        anchors.fill: parent
        hoverEnabled :true
        onMouseXChanged: console.log(mouseX,mouseY);//does not work when clicked
        }
    }
}

ListView { id: listViewCharts; objectName: "chart";
    clip: true
    anchors.top: parent.top; anchors.bottom: parent.bottom;

    width: 1500

    contentX:baseFlick.contentX; contentY:baseFlick.contentY;

    model: listViewIdsModel
    cacheBuffer: 1500
    delegate: chartDelegate
}

Flickable {
    id: baseFlick
    anchors.fill: parent

    contentHeight: listViewCharts.contentHeight
    contentWidth:  listViewCharts.width

}
}

1 个答案:

答案 0 :(得分:0)


显然,此问题只能使用c ++来解决


要捕获可滑动鼠标事件,请执行以下操作:
1)添加对象的名称为Flickable

objectName: "baseFlick"


2)创建qml场景后在c ++中。找到baseFlick对象,并在该对象上安装事件过滤器

auto rootObj = engine.rootObjects().at(0);
auto item = rootObj->findChild<QQuickItem *>("baseFlick");
if(item!=nullptr){
    item->installEventFilter(this);
} else qDebug()<<"ERR baseFlick item=nullptr";

3)实现eventFilter虚拟函数

bool IDS2forUser::eventFilter(QObject *watched, QEvent *event)
{
    ...
    return false;
}

为了将鼠标事件传播到ListView,就像它们来自用户一样。 在eventFilter函数中:
1)找到ListView(图表)对象

auto rootObj = engine.rootObjects().at(0);
auto item = rootObj->findChild<QQuickItem *>("chart");


2)找到他的所有孩子。
由于孩子的数量可能会发生变化,因此您每次都需要寻找孩子。
请注意,您应该使用QQuickItem :: childItems()函数而不是QObject :: children()

void IDS2forUser::getAllObjects(QQuickItem *parent, QList<QQuickItem *> &list) {

    QList<QQuickItem *> children = parent->childItems();
    foreach (QQuickItem *item, children) {
        list.append(item);
        getAllObjects(item,list);
    }
}


3)将所有坐标转换为对象的局部坐标。并发送所有孩子事件。
整个功能如下所示。

bool IDS2forUser::eventFilter(QObject *watched, QEvent *event)
{
    auto rootObj = engine.rootObjects().at(0);
    auto item = rootObj->findChild<QQuickItem *>("chart");

    QList<QQuickItem *> list;
    getAllObjects(item, list);

    QQuickItem *watchedIt = dynamic_cast<QQuickItem *>(watched);
    if(!watchedIt)return false;

    QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>(event);
    if(!mouseEvent)return false;

    foreach (QQuickItem *item, list) {
        QPointF point=item->mapFromItem(watchedIt,mouseEvent->localPos());

        if(point.x()<0 || point.y()<0 || point.x()>=item->width() || point.y()>=item->height())continue;

        QMouseEvent mouseEvent2(mouseEvent->type(),
                                point,
                                mouseEvent->button(),mouseEvent->buttons(),Qt::NoModifier);
        QCoreApplication::sendEvent(item, &mouseEvent2);
   }
return false;
}