为富文本编辑器创建一个“页面视图”样式布局,滚动条靠右对齐

1 投票
1 回答
701 浏览
提问于 2025-04-18 10:48

我正在尝试创建一个富文本编辑器,布局类似于微软Word的“页面视图”或“打印布局”。我希望在主窗口中水平居中放置一个QTextEdit,并且滚动条靠在主窗口的最右边。

我找不到方法可以独立移动QTextEdit的默认滚动条。于是,我尝试创建一个单独的滚动条,并使用这里找到的解决方案让QTextEdit在垂直方向上自动增长:一个像QTextEdit的QWidget,它的高度会自动适应内容?

这是我的尝试:

import sys
from PySide import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

    def initUI(self):
        cw = CentralWidget()
        self.setCentralWidget(cw)

        self.setGeometry(200, 200, 1000, 600)

        self.show()

    def resizeEvent(self, event):
        self.centralWidget().setFixedHeight(event.size().height())

class CentralWidget(QtGui.QWidget):

    def __init__(self):
        super(CentralWidget, self).__init__()
        self.initUI()

    def initUI(self):

        text = MainTextEdit()
        text.setMinimumWidth(850)
        text.setStyleSheet('border: 0;')

        pageWidget = QtGui.QWidget()

        scroll = QtGui.QScrollArea()
        scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        scroll.setMaximumWidth(18)
        # If you change setWidgetResizeable to False,
        # the textedit will center, but scrolling will not work.
        scroll.setWidgetResizable(True)
        scroll.setWidget(pageWidget)

        hbox = QtGui.QHBoxLayout()
        hbox.setContentsMargins(0,0,0,0)
        hbox.addStretch(0.5)
        hbox.addWidget(text)
        hbox.addStretch(0.5)
        pageWidget.setLayout(hbox)

        hbox2 = QtGui.QHBoxLayout()
        hbox2.setContentsMargins(0,0,0,0)
        hbox2.addWidget(pageWidget)
        hbox2.addWidget(scroll)
        self.setLayout(hbox2)

class MainTextEdit(QtGui.QTextEdit):

    def __init__(self, *args, **kwargs):
        super(MainTextEdit, self).__init__(*args, **kwargs)  

        self.document().contentsChanged.connect(self.sizeChange)

        self.setFontPointSize(80)

        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

    def sizeChange(self):
        docHeight = self.document().size().height()
        self.setMinimumHeight(docHeight)

def main():

    app = QtGui.QApplication(sys.argv)
    mw = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

这里面至少有两个问题:

问题 #1

目前的代码没有让QTextEdit在主窗口中水平居中,但最右边的滚动条是可以用的。如果你把scroll.setWidgetResizable(True)改成scroll.setWidgetResizable(False)(在第41行),QTextEdit就会水平居中,但滚动条就不能用了。看起来你只能选择一个功能,不能同时拥有两个。

问题 #2

为了防止当QTextEdit内容增多时主窗口自动扩展,主窗口在每次调整大小时会给中央小部件分配一个固定的高度(见上面代码的第19行)。这样做效果不错,直到用户尝试垂直缩小主窗口。用户可以通过点击并拖动底部边框来垂直扩展窗口,但无法垂直缩小。

结论

也许这根本就是错误的方法。有什么建议吗?

1 个回答

0

通过使用 setViewportMargins 方法,可以为 QTextEdit 设置一个对称的边距。需要注意的是,QTextEdit 是从 QAbstractScrollArea 这个类继承来的。

下面是一个例子:

from PySide import QtGui, QtCore

app = QtGui.QApplication([])
window = QtGui.QWidget()
layout = QtGui.QVBoxLayout(window)
edit = QtGui.QTextEdit('jfdh afdhgfkjg fdnvfh vklkfjvkflj lddkl ljklfjkl jvkldjfkvljfgvjldf ll dl dljvklj ljljlbl  llkb jbgl')
edit.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
edit.setViewportMargins(30, 0, 30, 30)
layout.addWidget(edit)
window.show()
app.exec_()

这样做的效果是:

垂直滚动条没有连接。

撰写回答