PySide Qt:TextEdit 小部件的自动垂直增长,以及垂直布局中小部件之间的间距 [英] PySide Qt: Auto vertical growth for TextEdit Widget, and spacing between widgets in a vertical layout

查看:56
本文介绍了PySide Qt:TextEdit 小部件的自动垂直增长,以及垂直布局中小部件之间的间距的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要用上面的小部件解决两个问题.

  1. 我希望能够定义图像中显示的帖子小部件之间的空间量(它们看起来很好,但我想知道它已经完成了).
  2. 我想根据它们包含的文本量垂直增加文本编辑,而不是水平增加.

对于 1,填充小部件的代码如下:

self._body_frame = QWidget()self._body_frame.setMinimumWidth(750)self._body_layout = QVBoxLayout()self._body_layout.setSpacing(0)self._post_widgets = []对于我在范围内(self._posts_per_page):pw = PostWidget()self._post_widgets.append(pw)self._body_layout.addWidget(pw)self._body_frame.setLayout(self._body_layout)

SetSpacing(0) 并没有让事情变得更近,但是 SetSpacing(100) 确实增加了它.

编辑

(对于问题 2)我没有提到这一点,但我希望父小部件有一个垂直滚动条.

我已经回答了我自己的问题,但它很冗长,而且基于因果关系.解决这两点的适当的写得很好的教程风格的答案得到了赏金:D

编辑 2

使用下面我自己的答案,我已经解决了这个问题.我现在将接受我自己的答案.

解决方案

1) 布局

此处的另一个答案非常不清楚,可能与布局边距的工作方式无关.它实际上非常简单.

  1. 布局有内容边距
  2. 小部件具有内容边距

这两个都定义了围绕它们包含的内容的填充.布局上的边距设置为 2 意味着在所有边上填充 2 个像素.如果您有父子小部件和布局(在您编写 UI 时总是如此),则每个对象都可以具有单独生效的特定边距.也就是说……父布局指定边距为 2,子布局指定边距为 2,将有效地显示 4 个像素的边距(如果小部件有框架,显然中间会绘制一些框架.

一个简单的布局示例说明了这一点:

w = QtGui.QWidget()w.resize(600,400)布局 = QtGui.QVBoxLayout(w)layout.setMargin(10)框架 = QtGui.QFrame()frame.setFrameShape(frame.Box)layout.addWidget(frame)layout2 = QtGui.QVBoxLayout(frame)layout2.setMargin(20)frame2 = QtGui.QFrame()frame2.setFrameShape(frame2.Box)layout2.addWidget(frame2)

可以看到顶层边距每边10,子布局每边20.在数学方面没有什么真正复杂的.

也可以按边指定边距:

# left: 20, top: 0, right: 20, bottom: 0layout.setContentsMargins(20,0,20,0)

还可以选择在布局上设置间距.间距是放置在布局的每个子项之间的像素量.将其设置为 0 意味着它们正好相互对抗.间距是布局的一个特征,而边距是整个对象的一个​​特征.布局周围可以有边距,也可以在其子项之间留出间距.而且,widget 的子项可以有自己的边距,这是它们各自显示的一部分.

layout.setSpacing(10) # 每个布局项之间 10 个像素

2) 自动调整 QTextEdit 的大小

现在是问题的第二部分.我确信有几种方法可以创建自动调整大小的 QTextEdit.但是一种方法是观察文档中的内容变化,然后根据文档高度调整小部件:

类窗口(QtGui.QDialog):def __init__(self):super(Window, self).__init__()self.resize(600,400)self.mainLayout = QtGui.QVBoxLayout(self)self.mainLayout.setMargin(10)self.scroll = QtGui.QScrollArea()self.scroll.setWidgetResizable(True)self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)self.mainLayout.addWidget(self.scroll)scrollContents = QtGui.QWidget()self.scroll.setWidget(scrollContents)self.textLayout = QtGui.QVBoxLayout(scrollContents)self.textLayout.setMargin(10)对于 xrange(5) 中的 _:文本 = GrowingTextEdit()text.setMinimumHeight(50)self.textLayout.addWidget(text)类 GrowingTextEdit(QtGui.QTextEdit):def __init__(self, *args, **kwargs):super(GrowingTextEdit, self).__init__(*args, **kwargs)self.document().contentsChanged.connect(self.sizeChange)self.heightMin = 0self.heightMax = 65000def sizeChange(self):docHeight = self.document().size().height()如果 self.heightMin <= docHeight <= self.heightMax:self.setMinimumHeight(docHeight)

我继承了 QTextEdit -> GrowingTextEdit,并将从其文档发出的信号连接到检查文档高度的插槽 sizeChange.我还包括一个 heightMin 和 heightMax 属性,让您指定允许自动增长的大小.如果您尝试这样做,您会看到当您在框中键入时,小部件将开始调整自身大小,并在您删除线条时缩小.如果需要,您也可以关闭滚动条.现在,除了父滚动区域之外,每个文本编辑都有自己的栏.另外,我认为您可以向 docHeight 添加一个小的 pad 值,以便它扩展到足以不显示内容的滚动条.

这种方法的水平并不低.它使用小部件的常用信号和子成员来接收状态更改的通知.利用信号扩展现有小部件的功能是很常见的.

I need to Solve two problems With my widget above.

  1. I'd like to be able to define the amount of space put between the post widgets shown in the image (they look fine as is, but I wanna know it's done).
  2. I'd like to grow the text edits vertically based on the amount of text they contain without growing horizontally.

For 1 the code that populates the widgets is as follows :

self._body_frame = QWidget()
self._body_frame.setMinimumWidth(750)
self._body_layout = QVBoxLayout()
self._body_layout.setSpacing(0)
self._post_widgets = []
for i in range(self._posts_per_page):
    pw = PostWidget()
    self._post_widgets.append(pw)
    self._body_layout.addWidget(pw)

    self._body_frame.setLayout(self._body_layout)

SetSpacing(0) doesn't bring things any closer, however SetSpacing(100) does increase it.

edit

(for Question 2) I haven't mentioned this, but I want the parent widget to have a vertical scrollbar.

I have answered my own question, but its wordy, and cause and affect based. A proper well written tutorial style answer to address both points gets the bounty :D

edit 2

Using my own answer below I have solved the problem. I'll be accepting my own answer now.

解决方案

1) Layouts

The other answer on here is very unclear and possibly off about how layout margins work. Its actually very straightforward.

  1. Layouts have content margins
  2. Widgets have content margins

Both of these define a padding around what they contain. A margin setting of 2 on a layout means 2 pixels of padding on all sides. If you have parent-child widgets and layouts, which is always the case when you compose your UI, each object can specific margins which take effect individually. That is... a parent layout specifying a margin of 2, with a child layout specifying a margin of 2, will effectively have 4 pixels of margin being displayed (obviously with some frame drawing in between if the widget has a frame.

A simple layout example illustrates this:

w = QtGui.QWidget()
w.resize(600,400)

layout = QtGui.QVBoxLayout(w)
layout.setMargin(10)
frame = QtGui.QFrame()
frame.setFrameShape(frame.Box)
layout.addWidget(frame)

layout2 = QtGui.QVBoxLayout(frame)
layout2.setMargin(20)
frame2 = QtGui.QFrame()
frame2.setFrameShape(frame2.Box)
layout2.addWidget(frame2)

You can see that the top level margin is 10 on each side, and the child layout is 20 on each side. Nothing really complicated in terms of math.

Margin can also be specified on a per-side basis:

# left: 20, top: 0, right: 20, bottom: 0
layout.setContentsMargins(20,0,20,0)

There is also the option of setting spacing on a layout. Spacing is the pixel amount that is placed between each child of the layout. Setting it to 0 means they are right up against each other. Spacing is a feature of the layout, while margin is a feature of the entire object. A layout can have margin around it, and also spacing between its children. And, the children of the widget can have their own margins which are part of their individual displays.

layout.setSpacing(10) # 10 pixels between each layout item

2) Auto-Resizing QTextEdit

Now for the second part of your question. There are a few ways to create a auto-resizing QTextEdit I am sure. But one way to approach it is to watch for content changes in the document, and then adjust the widget based on the document height:

class Window(QtGui.QDialog):

    def __init__(self):
        super(Window, self).__init__()
        self.resize(600,400)

        self.mainLayout = QtGui.QVBoxLayout(self)
        self.mainLayout.setMargin(10)

        self.scroll = QtGui.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.mainLayout.addWidget(self.scroll)

        scrollContents = QtGui.QWidget()
        self.scroll.setWidget(scrollContents)

        self.textLayout = QtGui.QVBoxLayout(scrollContents)
        self.textLayout.setMargin(10)

        for _ in xrange(5):
            text = GrowingTextEdit()
            text.setMinimumHeight(50)
            self.textLayout.addWidget(text)


class GrowingTextEdit(QtGui.QTextEdit):

    def __init__(self, *args, **kwargs):
        super(GrowingTextEdit, self).__init__(*args, **kwargs)  
        self.document().contentsChanged.connect(self.sizeChange)

        self.heightMin = 0
        self.heightMax = 65000

    def sizeChange(self):
        docHeight = self.document().size().height()
        if self.heightMin <= docHeight <= self.heightMax:
            self.setMinimumHeight(docHeight)

I subclassed QTextEdit -> GrowingTextEdit, and connected the signal emitted from its document to a slot sizeChange that checks the document height. I also included a heightMin and heightMax attribute to let you specify how large or small its allowed to autogrow. If you try this out, you will see that as you type into the box, the widget will start to resize itself, and also shrink back when you remove lines. You can also turn off the scrollbars if you want. Right now each text edit has its own bars, in addition to the parent scroll area. Also, I think you could add a small pad value to the docHeight so that it expands just enough to not show scrollbars for the content.

This approach is not really low level. It uses the commonly exposed signals and child members of the widget for you to receive notifications of state changes. Its pretty common to make use of the signals for extending functionality of existing widgets.

这篇关于PySide Qt:TextEdit 小部件的自动垂直增长,以及垂直布局中小部件之间的间距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆