我遇到了一个与我公司为我们的某个产品线开发/维护的白名单Web浏览器相关的问题。浏览器运行在Qt 4.8.6之上,使用qtwebkit(迁移到5.X将是理想的,但我们使用的嵌入式Linux操作系统太旧,无法根据我们的测试支持更新版本,并升级到更新的操作系统对我们/我们的客户来说太昂贵了)。浏览器的主要界面是一个6x8触摸屏,安装在飞机驾驶舱内。
对于具有可滚动/嵌入式地图(例如Google地图)之类的网站,浏览器的用户希望能够在选择地图之外的内容时拖动整个页面,并只拖动地图(无需选择地图时的整个页面滚动(Ala大多数流行的移动浏览器)。
到目前为止,我可以做其中一个,但不能同时做到两个:
当我将鼠标处理程序挂钩到QWebView或QGraphicsWebView时,我可以将光标变成一只手,并且非常容易支持拖动整个网页。但是,当用户拖过地图时,这会抑制页面处理鼠标事件的能力(即当用户拖动地图时,它会拖动整个页面而不移动地图)。
当我没有添加钩子来处理鼠标事件时,像地图这样的东西可以通过抓取/拖动来滚动,但当然用户无法拖动整个页面。
现在,浏览器使用后者,禁用滚动条和方向箭头覆盖以允许用户滚动整个页面(因为显示大小有限,并且滚动条在大小时占用太多空间大到足以让用户与他们互动)...但这并不理想。
我的问题:是否有任何简单的方法可以使页面和页面中的元素无缝滚动?
谢谢! 罗布
答案 0 :(得分:2)
在我看来,你需要检查一下你是否在这样的地图上,并在这种情况下忽略(传递)事件。我想你应该可以这样做:
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()->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来销毁它,可能会引入一些延迟。但在这种情况下重新实现它。