i'm playing around with QtWebkit lately and i was wondering if it is possible to resolve the element displayed in the QWebView which is responsible for an event, e.g. a MouseEvent.
I've installed an EventFilter function at the WebView Object with a function like this:
bool WebKitManager::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonRelease)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if(mouseEvent->button() == Qt::LeftButton)
{
// what now?!
}
}
return false;
}
Is there any way to get a reference to the clicked element that is displayed in the QWebView? As far as i can tell, the passed QObject equals the WebView object and the event doesn't seem to hold reference to its dispatcher.
Since i'm far away from beeing a c++ professional i sincerely hope i missed something and you guys can help me out :)
Thanks in advance
Timo
I believe what you could do is:
cast object parameter to QWebView
get QWebFrame under mouse via vebView->page()->frameAt() method
use hitTestContent method of the returned frame to detect the element for the given mouse position
Below is an example:
bool WebKitManager::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::MouseButtonRelease)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::LeftButton)
{
QWebView *view = dynamic_cast<QWebView*>(object);
QPoint pos = view->mapFromGlobal(mouseEvent->globalPos());
qDebug() << view->url().toString() << " clicked at x:" << pos.x() << " y:" << pos.y();
QWebFrame *frame = view->page()->frameAt(mouseEvent->pos());
if (frame!=NULL)
{
QWebHitTestResult hitTestResult = frame->hitTestContent(pos);
qDebug() << "element" << hitTestResult.element().localName();
}
}
}
return false;
}
hope this helps, regards
Use qobject_cast instead of dynamic_cast.
Related
I have an subclassed QPlainTextEdit called Editor. The editor contains an object used to suggest text, called a Suggester. The user can press a button from the Suggester to show a QCompleter, the activeCompleter.
I need to mess with the activeCompleter when KeyPress events come in from the Editor, so in Suggester, I create an eventFilter and install it to the passed in Editor instance.
When the activeCompleter is not shown, the eventFilter receives the KeyPress events as expected. However, when the activeComplter is shown via activeComplter->complete(), the eventFilter does not recieve KeyPress events (the editor behaves however).
I don't understand why this is. The QCompleter is not a widget. The Editor retains focus. I do not intercept events or keys anywhere else.
Why is my eventFilter not receiving KeyPress events?
relevant code...
Editor::Editor(QWidget *parent) : QPlainTextEdit(parent){
suggester = new Suggester(this);
}
Suggester::Suggester(Editor* editor){
this->editor = editor;
editor->installEventFilter(this);
}
bool Suggester::eventFilter(QObject *obj, QEvent *event){
qDebug()<< "event filter of type " << event->type() << " from " << obj;
return false;
}
It seems that your eventFilter member is incomplete. You have to filter the QEvent:KeyPress event as follows:
bool Suggester::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
return true;
} else {
return false;
}
} else {
// pass the event on to the parent class
return Suggester::eventFilter(obj, event);
}
}
I want to change QScrollBar style on mouse hover. I have tried to get it working by adding eventFilter, but it doesn't work.
Code:
qApp->installEventFilter(this);
bool Test::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::Scroll) {
QScrollEvent *scrollEvent = static_cast<QScrollEvent*>(event);
if (scrollEvent->scrollState() == QScrollEvent::Enter) {
qDebug() << "Enter";
this->setStyleSheet("QScrollBar:vertical {width: 20px;}");
}
if (scrollEvent->scrollState() == QScrollEvent::Leave) {
qDebug() << "Leave";
this->setStyleSheet("QScrollBar:vertical {width: 12px;}");
}
}
return QObject::eventFilter(object, event);
}
How can I do this?
The correct events to handle in your event filter would actually be QEvent::Enter, and QEvent::Leave. QScrollEvent is used when scrolling actually occurs, that's why it was not triggered.
You can also probably directly use stylesheets with the :hover attribute.
I want to get rid of the my application's title and border, but to do that I need to be able to move the window by dragging on the menuBar. The two method's I've found to do this is:
void TopMenuBar::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
dragPosition = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
}
void TopMenuBar::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
move(event->globalPos() - dragPosition);
event->accept();
}
}
However if I put this in the MainWindow, it will move around no matter what you click on, and if I put it in a custom QMenuBar, it only moves the menubar within the window. I've also attempted to do some signals and slots trickery between the objects (Like keeping mousePressEvent in menuBar and mouseMoveEvent in MainWindow), but the tendency is that the window will "jump" to where the mouse pointer is instead of moving it smoothly.
Anyone else have a solution for this?
Environment is Windows
This will work for certain - just checked it. Call ui->menuBar->installEventFilter(this); in the MainWindow constructor.
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched == ui->menuBar)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouse_event = dynamic_cast<QMouseEvent*>(event);
if (mouse_event->button() == Qt::LeftButton)
{
dragPosition = mouse_event->globalPos() - frameGeometry().topLeft();
return false;
}
}
else if (event->type() == QEvent::MouseMove)
{
QMouseEvent* mouse_event = dynamic_cast<QMouseEvent*>(event);
if (mouse_event->buttons() & Qt::LeftButton)
{
move(mouse_event->globalPos() - dragPosition);
return false;
}
}
}
return false;
}
i'm trying to take screenshot with Paint event (WM_Paint) event in QT but i dont know how,
i used this code to take screenshot but it is not really good for do this
it must do screenshot when some changes in desktop not take screenshot every 1000 ms with timer
void MainWindow::shootScreen()
{
originalPixmap = QPixmap(); // clear image for low memory situations
// on embedded devices.
originalPixmap = QPixmap::grabWindow(QApplication::desktop()->winId());
//emit getScreen(originalPixmap);
updateScreenshotLabel();
}
void MainWindow::updateScreenshotLabel()
{
this->ui->label_2->setPixmap(originalPixmap.scaled(this->ui->label_2- >size(),
Qt::KeepAspectRatio,
Qt::SmoothTransformation));
}
Use QObject::installEventFilter on the widgets you are interested in, then check for the proper events. For example, in your MainWindow ui initialization:
void MainWindow::yourUiInitFunc()
{
exampleWidget = new QWidget;
...
exampleWidget->installEventFilter(this);
...
}
Then re-implement eventFilter:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == exampleWidget && event->type() == QEvent::KeyPress)
shootScreen();
return QMainWindow::eventFilter(obj, event);
}
tank you Jon Harper your codes was useful but i changed somethings there
your code just work when some key press event on my project form but i added paint method to your if and now it work on windows events too
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == this && QEvent::Paint == event->type()) {
shootScreen();
}
return false;
}
I have a Qt program with a QGraphicScene inside a QGraphicsView on top of QMainWindow.
The events are handled by the QMainWindow using an eventFilter function.
The function body looks similar to this code:
bool Window::eventFilter(QObject *, QEvent *event) {
QEvent::Type type = event->type();
if (type == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
switch(keyEvent->key()) {
case Qt::Key_A:
case Qt::Key_B:
case Qt::Key_C:
case Qt::Key_D:
// call a function that uses the current mouse position on the graphics scene
break;
default:
QLocale loc = QApplication::keyboardInputLocale();
if(loc.language() != QLocale::English) {
QString message = "A non-English key was pressed";
showMessage(message, QMessageBox::Warning);
}
}
return true;
}
return false;
}
I recently added the "default" part and since then the coordinates that are used in the A,B,C,D cases are totally wrong. In addition, if I add a simple cout print anywhere in the function the bug disappears and the correct mouse coordinates are used.
What can possibly cause this?