如何将QWidget的Wheel事件重定向到QTextEdit

2024-01-02

当鼠标不在QTextEdit上时转动鼠标滚轮,滚动条不会移动,但我仍然想通过鼠标滚轮移动滚动条,那么我该如何实现这个功能呢? 我知道像Microsoft Word这样的一些软件有这个功能。

我如下实现此功能,但是当您通过鼠标滚轮将滚动条移动到顶部或底部时,会发生错误:调用Python对象时超出最大递归深度。 任何人都可以帮忙吗? 我的代码在这里http://codepad.org/1rq06qTk 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_())

您可以通过在任何小部件上安装事件过滤器来实现此目的,该过滤器会将鼠标滚轮事件转发到 QTextEdit:

不幸的是,我只能给你 C++ 代码,但它应该给你一个总体思路。 另外,我正在使用 Qt 4.6.1。我在 Qt 4.8 及更高版本中检测到新的“滚动”事件类型,您在使用它时可能需要更改代码。


[Edit:]

对于 TextEdit 滚动,事件处理由于某种原因与标准方式不同: 将滚轮事件发送到文本编辑器不会对其进行处理。 相反,某种私有事件过滤器调用wheelEvent通过QAbstractScrollArea::viewportEvent不幸的是它受到保护。

长话短说,我们可以通过子类化 QTextEdit 来伪造 Wheel 事件:

#include "MyTextEdit.h"

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

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

当使用它而不是默认的 QTextEdits 时,您可以创建一个事件转发器,如下所示:


#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;
}

然后你可以安装一个事件过滤器,如下所示:

MainWindow.cpp(或任何更合适的地方):

_wheelEventForwarder = new WheelEventForwarder( ui->textEdit );

ui->centralwidget->installEventFilter( _wheelEventForwarder );

请参阅文档QObject::installEventFilter http://qt-project.org/doc/qt-5.1/qtcore/qobject.html#installEventFilter欲了解更多信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将QWidget的Wheel事件重定向到QTextEdit 的相关文章

随机推荐