【Qt】QTextEdit/QPlainTextEdit 实现 Ctrl + 鼠标滚轮 缩放文本功能

I - 实现自定义控件

1.1 - 原理与代码

主要原理:自定义控件继承 QTextEdit 或者 QPlainTextEdit 类,重写滚轮事件 wheelEvent, QTextEdit 和 QPlainTextEdit 中均包含此函数。
使用 QApplication 静态方法 QApplication::keyboardModifiers() 获取是否按下 Ctrl 键,然后调用父类的 zoomIn 和 zoomOut 接口实现缩放。

头文件 TextEdit.h ,自定义类 TextEdit 继承 QTextEdit (或 QPlainTextEdit)

#include <QTextEdit>
// 或 #include <QPlainTextEdit>
#include <QWheelEvent>
 
class TextEdit : public QTextEdit
// 或 class TextEdit : public QPlainTextEdit
{
    Q_OBJECT
public:
    explicit TextEdit(QWidget* parent = nullptr);

protected:
    void wheelEvent(QWheelEvent *e) override; //滚轮事件
    // 添加 override 编译时检查是否重写父类函数,防止敲错
 
}

源文件 TextEdit.cpp
重写 wheelEvent 函数,调用父类的 zoomIn 和 zoomOut 接口实现缩放

#include <QApplication>
#include "TextEdit.h"

TextEdit(QWidget* parent) : QTextEdit(parent)
// 或 TextEdit(QWidget* parent) : QPlainTextEdit(parent)
{
}

 
void TextEdit::wheelEvent(QWheelEvent *e)
{
    // 检查按键 Ctrl 是否按下
    if (Qt::ControlModifier == QApplication::keyboardModifiers())
    {
        if (e->delta() > 0) // 鼠标滚轮向上滚动
        {
            zoomIn(); // 文本放大
        }
        else
        {
            zoomOut(); // 文本缩小
        }
    }

	// 调用父类事件函数 保证鼠标滚轮查看文本功能正常
	QTextEdit::wheelEvent(e);
	// 或 QPlainTextEdit::wheelEvent(e);
}

1.2 - 问题与解决

使用上述代码时,出现了 zoomIn 和 zoomOut 调用均不生效无的问题,最后研究发现,原因是在设置了编辑器控件 (QTextEdit/QPlainTextEdit) 的 style sheet 样式表,设置了如下 QSS 编辑器样式的字体大小 point-size

QTextEdit, QPlainTextEdit
{
	/*...*/
	point-size: 15px;
	/*...*/
}

point-size 属性删除即可解决问题。因此也衍生出了另一种解决方法使用 QSS, 在每次 wheelEvent 中调用 zoomIn 和 zoomOut 处调用 设置样式表 setStyleSheet,使用成员变量记录当前的字体大小

代码如下:

// TextEdit.h 定义成员变量字体大小
int m_pointSize = 15;

// TextEdit.cpp wheelEvent 中
void TextEdit::wheelEvent(QWheelEvent *e)
{
    // 检查按键 Ctrl 是否按下
    if (Qt::ControlModifier == QApplication::keyboardModifiers())
    {
        if (e->delta() > 0) // 鼠标滚轮向上滚动
        {
            ++m_pointSize; // 文本放大
        }
        else
        {
            --m_pointSize; // 文本缩小
        }
    }

	// 字体大小变化后 更新样式表
	this->setStyleSheet(QString("QTextEdit, QPlainTextEdit { point-size: %1px; }").arg(m_pointSize));
	
	// 调用父类事件函数,保证鼠标滚轮查看文本功能正常
	QTextEdit::wheelEvent(e);
	// 或 QPlainTextEdit::wheelEvent(e);
}

代码中的 qss 样式仅为示例,可包含更多属性设置,此处只给出关键属性设置。

II - 完整代码

TextEdit.h

#include <QTextEdit>
// 或 #include <QPlainTextEdit>
#include <QWheelEvent>
 
class TextEdit : public QTextEdit
// 或 class TextEdit : public QPlainTextEdit
{
    Q_OBJECT
public:
    explicit TextEdit(QWidget* parent = nullptr);

protected:
    void wheelEvent(QWheelEvent *e) override; //滚轮事件
    // 添加 override 编译时检查是否重写父类函数,防止敲错
private:
	int m_pointSize = 15;
}

TextEdit.cpp

#include <QApplication>
#include "TextEdit.h"

TextEdit(QWidget* parent) : QTextEdit(parent)
// 或 TextEdit(QWidget* parent) : QPlainTextEdit(parent)
, m_pointSize(15)
{
}
 
void TextEdit::wheelEvent(QWheelEvent *e)
{
    // 检查按键 Ctrl 是否按下
    if (Qt::ControlModifier == QApplication::keyboardModifiers())
    {
        if (e->delta() > 0) // 鼠标滚轮向上滚动
        {
            zoomIn(); // 文本放大
        }
        else
        {
            zoomOut(); // 文本缩小
        }
    }

	// 调用父类事件函数,保证鼠标滚轮查看文本功能正常
	QTextEdit::wheelEvent(e);
	// 或 QPlainTextEdit::wheelEvent(e);
}
// 或
void TextEdit::wheelEvent(QWheelEvent *e)
{
    // 检查按键 Ctrl 是否按下
    if (Qt::ControlModifier == QApplication::keyboardModifiers())
    {
        if (e->delta() > 0) // 鼠标滚轮向上滚动
        {
            ++m_pointSize; // 文本放大
        }
        else
        {
            --m_pointSize; // 文本缩小
        }
    }

	// 字体大小变化后 更新样式表
	this->setStyleSheet(QString("QTextEdit, QPlainTextEdit { point-size: %1px; }").arg(m_pointSize));
	
	// 调用父类事件函数,保证鼠标滚轮查看文本功能正常
	QTextEdit::wheelEvent(e);
	// 或 QPlainTextEdit::wheelEvent(e);
}

III - 参考链接

https://blog.csdn.net/weixin_36323170/article/details/119532007

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐