如何通过工具栏按钮点击或Ctrl + 滚轮缩放QTextEdit区域

3 投票
1 回答
4034 浏览
提问于 2025-04-17 05:32

有没有办法让QTextEdit区域缩放(或者说“放大”)呢?我记得看到过把QTextEdit放在QLayout里面可以实现缩放,但我还没找到具体怎么做。有几个选择...

按住CTRL + 鼠标滚轮
运行下面的代码时,按住CTRL键并滚动鼠标滚轮,事件会被捕捉到,文本确实会缩放(至少在Windows上是这样),不过随着文本变大,滚轮需要转得越来越多才能看到明显的效果。所以一个目标是想办法修改这个,也许可以用一些数学方法来增加放大的幅度,让它在放大时变化更明显。

下面的setReadOnly()是因为似乎textEdit必须是只读(False)才能捕捉到鼠标事件,然后在滚动鼠标滚轮时需要设置为可编辑(True),最后在松开CTRL键时再恢复为原来的只读状态(False)。

工具栏按钮点击
另一个选择是使用工具栏按钮来放大和缩小。
当点击放大按钮时,会调用onZoomInClicked()。

下面代码的一些当前问题
1. 它打印出:QLayout: Attempting to add QLayout "" to MainWindow "", which already has a layout,我还没搞明白这是什么意思。
2. 用QtGui.QTextEdit(self.formLayout)而不是(self)来把textEdit放进布局里,会出现TypeError: 'PySide.QtGui.QTextEdit' called with wrong argument types的错误。
3. wheelEvent()可能需要某种方式来修改event.delta()?
4. 工具栏按钮(只有文字)目前点击时会运行它的定义,但里面只包含一个打印语句。

from PySide import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.formLayout   = QtGui.QFormLayout(self)
        self.textEdit     = QtGui.QTextEdit(self)
        self.toolBar      = QtGui.QToolBar(self)
        self.actionZoomIn = QtGui.QAction(self)
        self.textEdit.setHtml('<font color=blue>Hello <b>world</b></font>')
        self.setCentralWidget(self.textEdit)
        self.addToolBar(self.toolBar)
        self.toolBar.addAction(self.actionZoomIn)
        self.actionZoomIn.setText('Zoom In')
        self.actionZoomIn.connect(self.actionZoomIn,
            QtCore.SIGNAL('triggered()'), self.onZoomInClicked)

    def onZoomInClicked(self):
        print "onZoomInClicked(self) needs code"

    def wheelEvent(self, event):
        print "wheelEvent() captured"
        if (event.modifiers() & QtCore.Qt.ControlModifier):
            self.textEdit.setReadOnly(True)

            event.accept()            

    def keyReleaseEvent(self, evt):
        if evt.key() == QtCore.Qt.Key_Control:
            self.textEdit.setReadOnly(False)

if __name__ == '__main__':
    app   = QtGui.QApplication([])
    frame = MainWindow()
    frame.show()
    app.exec_()

我已经为这个问题纠结了好几天,如果能让QTextEdit的缩放功能正常工作,那就太好了,不知道这是否可能。

1 个回答

4

这两个错误信息可以这样理解:

  1. QMainWidget会自动有一个布局,所以使用QFormLayout就多余了。如果你想添加一个布局,可以先创建一个QWidget作为中心部件,然后把新的布局放在这个中心部件下面。之后,其他的部件就可以添加到这个新的布局里。
  2. 一个QWidget的子类的父类必须也是QWidget的子类,而QFormLayout并不是。

我对你的例子做了一些修改,使它能实现你大部分的需求。请注意,QTextEdit.zoomInQTextEdit.zoomOut这两个方法都需要一个range参数来控制缩放的程度。

from PySide import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.textEdit = Editor(self)
        self.toolBar = QtGui.QToolBar(self)
        self.actionZoomIn = QtGui.QAction('Zoom In', self)
        self.actionZoomOut = QtGui.QAction('Zoom Out', self)
        self.textEdit.setHtml('<font color=blue>Hello <b>world</b></font>')
        self.setCentralWidget(self.textEdit)
        self.addToolBar(self.toolBar)
        self.toolBar.addAction(self.actionZoomIn)
        self.toolBar.addAction(self.actionZoomOut)
        self.actionZoomIn.triggered.connect(self.onZoomInClicked)
        self.actionZoomOut.triggered.connect(self.onZoomOutClicked)

    def onZoomInClicked(self):
        self.textEdit.zoom(+1)

    def onZoomOutClicked(self):
        self.textEdit.zoom(-1)

class Editor(QtGui.QTextEdit):
    def __init__(self, parent=None):
        super(Editor, self).__init__(parent)

    def zoom(self, delta):
        if delta < 0:
            self.zoomOut(1)
        elif delta > 0:
            self.zoomIn(5)

    def wheelEvent(self, event):
        if (event.modifiers() & QtCore.Qt.ControlModifier):
            self.zoom(event.delta())
        else:
            QtGui.QTextEdit.wheelEvent(self, event)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec_()

撰写回答