Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt: Force QWebView to click on a web element, even one not visible on the window

So let's say I'm trying to click a link in the QWebView, here is what I have:

// extending QWebView
void MyWebView::click(const QString &selectorQuery)
{
    QWebElement el = this->page()->mainFrame()->findFirstElement(selectorQuery);
    if (!el)
         return;

    el.setFocus();

    QMouseEvent pressEvent(QMouseEvent::MouseButtonPress, el.geometry().center(), 
                    Qt::MouseButton::LeftButton, Qt::LeftButton, Qt::NoModifier);
    QCoreApplication::sendEvent(this, &pressEvent);

    QMouseEvent releaseEvent(QMouseEvent::MouseButtonRelease, 
                             el.geometry().center(), Qt::MouseButton::LeftButton,
                             Qt::LeftButton, Qt::NoModifier);
    QCoreApplication::sendEvent(this, &releaseEvent);
}

And you call it as so:

myWebView->click("a[href]");  // will click first link on page
myWebView->click("input[type=submit]"); // submits a form

THE ONLY PROBLEM IS: if the element is not visible in the window, it is impossible to click. What I mean is if you have to scroll down to see it, you can't click it. I imagine this has to do with the geometry, since the element doesn't show up on the screen it can't do the math to click it right.

Any ideas to get around this? Maybe some way to make the window behave like a billion x billion pixels but still look 200x200?

like image 756
Pirate for Profit Avatar asked Apr 16 '10 18:04

Pirate for Profit


3 Answers

I think calling el.evaluateJavaScript("click()"); should work. I say should work because in the past I've been using QWebElement::function() with "click" argument with success. This method did not become part of QWebElement API, however. I think authors came to conclusion it was superfluous in presence of QWebElement::evaluateJavaScript().

My similar question - How to follow a link in QWebKit? - still without answer :(
I came up with the same workaround like you here - Problem with evaluateJavaScript()

like image 85
Piotr Dobrogost Avatar answered Oct 25 '22 07:10

Piotr Dobrogost


Hi I know this question is quite old, but I wanted to offer a different answer. You said: "...since the element doesn't show up on the screen it can't do the math to click it...". Well, "it" can not do the math, but "You" can. ;) You can get the position of the element you want to click on and calculate how many pixels (X) you need to scroll down/up in order to make it visible. Then you can auto scroll the page by X pixels and use the X value to calculate the current position of the element and click there. The same logic is used if you have to scroll left or right too. Just use Y pixels as a horizontal correction value. I've done this in another language and I know it is doable and works fine. :)

EDIT: (Feb 21 2013)

OK, I had to do this for one of my projects too. So to illustrate what I meant above, below is the Qt code. I realize it has some flaws, especially if you are dealing with small elements around the page edges, but in most cases it works just fine.

(in the code below *elemt is the element you want to click on and *web is the QWebView widget)

QRect elGeom=element->geometry();
QPoint elPoint=elGeom.center();
int elX=elPoint.x();
int elY=elPoint.y();
int webWidth=web->width();
int webHeight=web->height();
int pixelsToScrolRight=0;
int pixelsToScrolDown=0;
if (elX>webWidth) pixelsToScrolRight=elX-webWidth+elGeom.width()/2+10; //the +10 part if for the page to scroll a bit further
if (elY>webHeight) pixelsToScrolDown=elY-webHeight+elGeom.height()/2+10; //the +10 part if for the page to scroll a bit further
web->page()->mainFrame()->setScrollBarValue(Qt::Horizontal,pixelsToScrolRight);
web->page()->mainFrame()->setScrollBarValue(Qt::Vertical,pixelsToScrolDown);
QPoint pointToClick(elX-pixelsToScrolRight,elY-pixelsToScrolDown);

QMouseEvent pressEvent(QMouseEvent::MouseButtonPress,pointToClick,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);
QCoreApplication::sendEvent(web, &pressEvent);
QMouseEvent releaseEvent(QMouseEvent::MouseButtonRelease,pointToClick,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);
QCoreApplication::sendEvent(web, &releaseEvent);

This is what works for me, when the java click fails. I hope it will be useful to someone else too.

like image 7
dv8 Avatar answered Oct 25 '22 09:10

dv8


For those who want to click on Webview button then do these

frame1->evaluateJavaScript( "document.forms[0].submit();" ); 
like image 1
Kashyap Avatar answered Oct 25 '22 09:10

Kashyap