how to redirect Wheel events of QWidget to QTextEdit

强颜欢笑 提交于 2019-12-08 01:26:19

问题


when you turn the mouse wheel while the mouse is not on the QTextEdit ,the scroll bars will not move in such case ,but I still want to move the scroll bars by mouse wheel ,so how can I implement this function ? I know some software like Microsoft Word have this feature .

I implement this feature like the following ,but when you move the scroll bars to the top or bottom by mouse wheel ,an error would occur : maximum recursion depth exceeded while calling a Python object. anyone can help ? my code here http://codepad.org/1rq06qTk:

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *


class BoxLayout(QWidget):
    def __init__(self, parent=None):
        super(BoxLayout, self).__init__(parent)
        self.resize(100, 300)

        ok = QPushButton("OK")
        cancel = QPushButton("Cancel")
        self.textEdit = QTextEdit("This function returns true if the contents "
                                  "of the MIME data object, specified by source, "
                                  "can be decoded and inserted into the document. "
                                  "It is called for example when during a drag "
                                  "operation the mouse enters this widget and it "
                                  "is necessary to determine whether it is possible "
                                  "to accept the drag and drop operation.")

        vbox = QVBoxLayout()
        vbox.addWidget(self.textEdit)
        vbox.addWidget(ok)
        vbox.addWidget(cancel)
        self.setLayout(vbox)

#       self.textEdit.installEventFilter(self)


#    def eventFilter(self, obj, event):
#        if obj == self.textEdit:
#            if event.type() == QEvent.Wheel:
#                self.textEdit.wheelEvent(event)
#                return True
#            else:
#                return False
#        else:
#            return QMainWindow.eventFilter(self, obj, event)


    def wheelEvent(self, event):
        self.textEdit.wheelEvent(event)


app = QApplication(sys.argv)
qb = BoxLayout()
qb.show()
sys.exit(app.exec_())

回答1:


You could do this by installing an event filter on any widget which shall forward the mouse wheel event to the QTextEdit:

I can unfortunately only give you C++ code but it should give you a general idea. Also, I'm using Qt 4.6.1. I've detected a new "Scroll" Event type in Qt 4.8 and later, you might have to change the code when using that.


[Edit:]

For TextEdit scrolling, event processing differs from the standard way for some reason: Sending a Wheel Event to the Text Edit does not process it. Instead, some kind of private event filter calls wheelEvent through QAbstractScrollArea::viewportEvent which is unfortunately protected.

Long story short, we can fake Wheel Events by subclassing QTextEdit:

#include "MyTextEdit.h"

MyTextEdit::MyTextEdit( QWidget* parent ) :
    QTextEdit( parent )
{
}

void MyTextEdit::forwardViewportEvent( QEvent* event )
{
    viewportEvent( event );
}

When using this instead of the default QTextEdits, you can create an Event Forwarder like this:


#ifndef WHEELEVENTFORWARDER_H
#define WHEELEVENTFORWARDER_H

#include <QtCore/QObject>

class MyTextEdit;

class WheelEventForwarder : public QObject
{
    Q_OBJECT
public:
    explicit WheelEventForwarder( MyTextEdit* target );
    ~WheelEventForwarder();

    bool eventFilter( QObject* obj, QEvent* event );

private:
    MyTextEdit* _target;
};

#endif // WHEELEVENTFORWARDER_H

WheelEventForwarder.cpp

#include "WheelEventForwarder.h"
#include "MyTextEdit.h"
#include <QtCore/QEvent>
#include <QtGui/QApplication>

WheelEventForwarder::WheelEventForwarder( MyTextEdit* target ) :
    QObject(),
    _target( target )
{
}

WheelEventForwarder::~WheelEventForwarder()
{
    _target = NULL;
}

bool WheelEventForwarder::eventFilter( QObject* obj, QEvent* event )
{
    Q_UNUSED( obj );

    static bool recursionProtection = false;

    if( recursionProtection ) return false;

    if( !_target ) return false;

    if( event->type() == QEvent::Wheel )
    {
        recursionProtection = true;
        _target->forwardViewportEvent( event );
        recursionProtection = false;
    }

    // do not filter the event
    return false;
}

Then you can install an event filter like this:

MainWindow.cpp (or any better fitting place):

_wheelEventForwarder = new WheelEventForwarder( ui->textEdit );

ui->centralwidget->installEventFilter( _wheelEventForwarder );

See the documentation for QObject::installEventFilter for more information on this.




回答2:


You can also go with this approach:

Call QTextEdit.scroll(int,int) function to scroll qtextedit whenever required. Mean you can cal this function from the mouseScrollEvent of your widget



来源:https://stackoverflow.com/questions/17738997/how-to-redirect-wheel-events-of-qwidget-to-qtextedit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!