QtWebView - 如何启用页面滚动和页面中元素的滚动(例如谷歌地图)

Posted

技术标签:

【中文标题】QtWebView - 如何启用页面滚动和页面中元素的滚动(例如谷歌地图)【英文标题】:QtWebView - How to enable scrolling of page and scrolling of elements in a page (e.g. Google Maps) 【发布时间】:2015-01-15 20:11:21 【问题描述】:

我遇到了一些与我的公司一直在为我们的一个产品线开发/维护的白名单 Web 浏览器相关的问题。浏览器运行在 Qt 4.8.6 之上,使用 qtwebkit(迁移到 5.X 是理想的,但是我们使用的嵌入式 Linux 操作系统太旧,无法支持基于我们的测试的较新版本,并升级到较新的版本操作系统对我们/我们的客户来说太贵了)。浏览器的主要界面是安装在飞机驾驶舱内的 6x8 触摸屏。

对于具有可滚动/嵌入地图(例如 Google 地图)之类的网站,浏览器的用户希望能够在选择地图之外的内容时拖动整个页面,并且只拖动地图(没有the entire page scrolling) when the map is selected (Ala most of the popular mobile browsers).

到目前为止,我可以做一个或另一个,但不能同时做:

当我将鼠标处理程序挂接到 QWebView 或 QGraphicsWebView 时,我可以将光标变成一只手,并且非常轻松地支持整个网页的拖动。但是,这会抑制页面在用户拉动地图时处理鼠标事件的能力(即,当用户在地图上拖动时,它会拖动整个页面而不移动地图)。

当我不添加处理鼠标事件的钩子时,地图之类的东西可以通过抓住/拖动它们来滚动,但当然用户失去了拖动整个页面的能力。

目前,浏览器使用后者,禁用滚动条并使用方向箭头覆盖以允许用户滚动整个页面(因为显示大小有限,并且滚动条在调整大小时占用了太多空间大到足以让用户与他们互动)...但这并不理想。

我的问题:有什么简单的方法可以让页面和页面中的元素无缝滚动?

谢谢! 抢

【问题讨论】:

【参考方案1】:

在我看来,您需要检查您是否在这样的地图上并在这种情况下忽略(传递)该事件。我认为你应该能够做这样的事情:

bool GraphicsWebView::isOverMap(QPoint pos) 
    QWebPage* webPage = this->page();
    if (webPage) 
        QWebFrame* webFrame = webPage->frameAt(pos);
        if (webFrame) 
            QString selectorQuery = "#map-canvas"; // Based on https://developers.google.com/maps/tutorials/fundamentals/adding-a-google-map
            QList<QWebElement> list = webFrame->findAllElements(selectorQuery).toList(); // Find all the maps!

            foreach(QWebElement element, list) 
                if (element.geometry().contains(pos)) 
                    return true; // Cursor is over a map
                
            
        
    
    return false; // No match

显然这是一个非常具体的功能,但可能有一种方法可以提出一个更好的选择器查询,该查询将适用于所有这些类型的QWebElement

假设您通过子类化 QGraphicsWebView 并重新实现 void mouseMoveEvent(QGraphicsSceneMouseEvent * event) 来挂钩鼠标事件,我建议您执行以下操作:

void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) 
    if (isOverMap(mapFromScene(event->scenePos()).toPoint()))  // We got a map!
        event.ignore(); // Clear the accept flag
        return; // Return, we're done here
    

    handleMoveView(); // Not over any maps, let's scroll the page

This 文档的一部分解释了如何处理与最顶层项目相关的事件。我特别推荐你阅读第三段。

希望有帮助!

编辑:做了更多的研究,看起来像这样的东西可能更通用: graphicsView.focusItem()-&gt;flags().testFlag(QGraphicsItem::ItemIsMovable);

作为isOverMap()的替代品,至少值得研究

编辑:知道了,你可以试试这里。 首先继承 QGraphicsSceneMouseEvent 并添加一个名为 void destroyedWithoutAccept() 的信号,如果事件未被接受,该信号将在析构函数中发出。

然后将 mouseMoveEvent 修改为如下所示:

void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) 
    MyEvent myEvent = new MyEvent(event); // Copy event
    event.accept(); // accept original event
    connect(myEvent, SIGNAL(destroyedWithoutAccept),
            this, SLOT(handleMoveView)); // Callback if unused

    QGraphicsWebView::mouseMoveEvent(myEvent); // Pass it to Base class

如果这样可行,如果使用 deleteLater 来销毁它,它可能会引入一些延迟。但在这种情况下,也要重新实现它。

【讨论】:

感谢您的回复!不幸的是,谷歌地图只是一个例子……航空公司实际上正在寻求使用各种天气、航班跟踪和其他相关网站。其中一些具有交互式地图,而另一些则没有(每个站点的实现也是独一无二的)。我只提到了谷歌地图,因为它是我目前用来测试的。我之前也尝试过上面的命中测试行为,但没有任何访问权限(当您查询它是否可移动时,它总是报告'false')。 没问题。刚刚做了一个新的编辑,应该会带来更好、更灵活的设计。

以上是关于QtWebView - 如何启用页面滚动和页面中元素的滚动(例如谷歌地图)的主要内容,如果未能解决你的问题,请参考以下文章

如何在垂直滚动其内容(集合视图)时启用 UIPageViewController 的页面滚动?

滚动到 UICollectionView 中启用分页的页面

具有滚动效果的页面视图控制器与启用分页的 UIScrollView

QtWebView 中的 In-Page href 无法显示任何内容

如何仅在正文上启用反弹过度滚动(而不是页眉和页脚)?

QtWebView中的页内href无法显示任何内容