Issue
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_())
Solution
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.
Answered By - Tim Meyer
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.