Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PyQt:环绕QScrollara中小部件的布局_Python_Layout_Pyqt_Alignment_Qscrollarea - Fatal编程技术网

Python PyQt:环绕QScrollara中小部件的布局

Python PyQt:环绕QScrollara中小部件的布局,python,layout,pyqt,alignment,qscrollarea,Python,Layout,Pyqt,Alignment,Qscrollarea,我正在开发一个使用PyQt4记忆文本的应用程序。我想把所有的单词都放在泡泡里,这样你就可以看到这个单词有多长了。但是当我的qscrollara中有所有气泡时,它们一个接一个地对齐。我想让它们并排对齐,但要用换行符 我使用带有圆形边框的QLabel使气泡工作。但现在我有了《代码> QLabor的< /C> >中的文字,PyQt不把它们当作词——而是作为小部件。因此PyQt将一个小部件置于另一个小部件之下。我希望小部件并排对齐,直到它们到达行的末尾,然后它们应该环绕到下一行-这意味着QLabel的应

我正在开发一个使用PyQt4记忆文本的应用程序。我想把所有的单词都放在泡泡里,这样你就可以看到这个单词有多长了。但是当我的
qscrollara
中有所有气泡时,它们一个接一个地对齐。我想让它们并排对齐,但要用换行符

我使用带有圆形边框的
QLabel
使气泡工作。但现在我有了《代码> QLabor的< /C> >中的文字,PyQt不把它们当作词——而是作为小部件。因此PyQt将一个小部件置于另一个小部件之下。我希望小部件并排对齐,直到它们到达行的末尾,然后它们应该环绕到下一行-这意味着
QLabel的
应该像文本文档中的单词一样工作

以下是我目前的代码:

f = open(r'myFile.txt')

class Bubble(QtGui.QLabel):
    def __init__(self, text):
        super(Bubble, self).__init__(text)
        self.word = text
        self.setContentsMargins(5, 5, 5, 5)

    def paintEvent(self, e):
        p = QtGui.QPainter(self)
        p.setRenderHint(QtGui.QPainter.Antialiasing,True)
        p.drawRoundedRect(0,0,self.width()-1,self.height()-1,5,5)
        super(Bubble, self).paintEvent(e)


class MainWindow(QtGui.QMainWindow):
    def __init__(self, text, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.MainArea = QtGui.QScrollArea
        self.widget = QtGui.QWidget()
        vbox = QtGui.QVBoxLayout()
        self.words = []
        for t in re.findall(r'\b\w+\b', text):
            label = Bubble(t)
            label.setFont(QtGui.QFont('SblHebrew', 18))
            label.setFixedWidth(label.sizeHint().width())
            self.words.append(label)
            vbox.addWidget(label)
        self.widget.setLayout(vbox)
        self.MainArea.setWidget(self.widget)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    myWindow = MainWindow(f.read(), None)
    myWindow.show()
    sys.exit(app.exec_())
当我运行此命令时,我得到:

但我希望单词(包含单词的
Qlabel的
)彼此相邻,而不是相互下方,如下图所示(photoshopped):


我已经做了很多研究,但没有任何答案可以帮助我将小部件彼此对齐

我认为可以在
QTextBrowser
小部件中使用html来实现这一点,但Qt不支持气泡标签所需的
border radius
CSS属性

所以看起来您需要一个的PyQt端口。这可以在容器中“字包装”一组小部件,还允许调整边距和水平/垂直间距

下面是一个演示脚本,它实现了
FlowLayout
类,并演示了如何在示例中使用它:

import sys
from PyQt4 import QtCore, QtGui

class FlowLayout(QtGui.QLayout):
    def __init__(self, parent=None, margin=-1, hspacing=-1, vspacing=-1):
        super(FlowLayout, self).__init__(parent)
        self._hspacing = hspacing
        self._vspacing = vspacing
        self._items = []
        self.setContentsMargins(margin, margin, margin, margin)

    def __del__(self):
        del self._items[:]

    def addItem(self, item):
        self._items.append(item)

    def horizontalSpacing(self):
        if self._hspacing >= 0:
            return self._hspacing
        else:
            return self.smartSpacing(
                QtGui.QStyle.PM_LayoutHorizontalSpacing)

    def verticalSpacing(self):
        if self._vspacing >= 0:
            return self._vspacing
        else:
            return self.smartSpacing(
                QtGui.QStyle.PM_LayoutVerticalSpacing)

    def count(self):
        return len(self._items)

    def itemAt(self, index):
        if 0 <= index < len(self._items):
            return self._items[index]

    def takeAt(self, index):
        if 0 <= index < len(self._items):
            return self._items.pop(index)

    def expandingDirections(self):
        return QtCore.Qt.Orientations(0)

    def hasHeightForWidth(self):
        return True

    def heightForWidth(self, width):
        return self.doLayout(QtCore.QRect(0, 0, width, 0), True)

    def setGeometry(self, rect):
        super(FlowLayout, self).setGeometry(rect)
        self.doLayout(rect, False)

    def sizeHint(self):
        return self.minimumSize()

    def minimumSize(self):
        size = QtCore.QSize()
        for item in self._items:
            size = size.expandedTo(item.minimumSize())
        left, top, right, bottom = self.getContentsMargins()
        size += QtCore.QSize(left + right, top + bottom)
        return size

    def doLayout(self, rect, testonly):
        left, top, right, bottom = self.getContentsMargins()
        effective = rect.adjusted(+left, +top, -right, -bottom)
        x = effective.x()
        y = effective.y()
        lineheight = 0
        for item in self._items:
            widget = item.widget()
            hspace = self.horizontalSpacing()
            if hspace == -1:
                hspace = widget.style().layoutSpacing(
                    QtGui.QSizePolicy.PushButton,
                    QtGui.QSizePolicy.PushButton, QtCore.Qt.Horizontal)
            vspace = self.verticalSpacing()
            if vspace == -1:
                vspace = widget.style().layoutSpacing(
                    QtGui.QSizePolicy.PushButton,
                    QtGui.QSizePolicy.PushButton, QtCore.Qt.Vertical)
            nextX = x + item.sizeHint().width() + hspace
            if nextX - hspace > effective.right() and lineheight > 0:
                x = effective.x()
                y = y + lineheight + vspace
                nextX = x + item.sizeHint().width() + hspace
                lineheight = 0
            if not testonly:
                item.setGeometry(
                    QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint()))
            x = nextX
            lineheight = max(lineheight, item.sizeHint().height())
        return y + lineheight - rect.y() + bottom

    def smartSpacing(self, pm):
        parent = self.parent()
        if parent is None:
            return -1
        elif parent.isWidgetType():
            return parent.style().pixelMetric(pm, None, parent)
        else:
            return parent.spacing()

class Bubble(QtGui.QLabel):
    def __init__(self, text):
        super(Bubble, self).__init__(text)
        self.word = text
        self.setContentsMargins(5, 5, 5, 5)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
        painter.drawRoundedRect(
            0, 0, self.width() - 1, self.height() - 1, 5, 5)
        super(Bubble, self).paintEvent(event)

class MainWindow(QtGui.QMainWindow):
    def __init__(self, text, parent=None):
        super(MainWindow, self).__init__(parent)
        self.mainArea = QtGui.QScrollArea(self)
        self.mainArea.setWidgetResizable(True)
        widget = QtGui.QWidget(self.mainArea)
        widget.setMinimumWidth(50)
        layout = FlowLayout(widget)
        self.words = []
        for word in text.split():
            label = Bubble(word)
            label.setFont(QtGui.QFont('SblHebrew', 18))
            label.setFixedWidth(label.sizeHint().width())
            self.words.append(label)
            layout.addWidget(label)
        self.mainArea.setWidget(widget)
        self.setCentralWidget(self.mainArea)

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = MainWindow('Harry Potter is a series of fantasy literature')
    window.show()
    sys.exit(app.exec_())
导入系统 从PyQt4导入QtCore、QtGui 类流布局(QtGui.QLayout): 定义初始化(self,parent=None,margin=-1,hspacing=-1,vspacing=-1): 超级(FlowLayout,self)。\uuuuu初始化\uuuuuu(父级) 自排=自排 self.\u vspacking=vspacking self._项=[] self.setContentsMargins(边距、边距、边距、边距) 定义(自我): 删除自身项目[:] def附加项(自身,项目): self.\u items.append(项目) def水平间距(自): 如果self.\u hspacing>=0: 返回自我 其他: 返回自定间距( QtGui.QStyle.PM_布局权限(水平间距) def垂直间距(自): 如果self.\u vspacing>=0: 返回自我空间 其他: 返回自定间距( QtGui.QStyle.PM_布局垂直间距) def计数(自身): 返回len(自身项目) def itemAt(自身,索引): 如果0: x=有效。x() y=y+线宽+vspace nextX=x+item.sizeHint().width()+hspace 线宽=0 如果不只是测试: item.setGeometry( QtCore.QRect(QtCore.QPoint(x,y),item.sizeHint()) x=nextX lineheight=max(lineheight,item.sizeHint().height()) 返回y+线宽-矩形y()+底部 def智能间距(自、pm): parent=self.parent() 如果父项为“无”: 返回-1 elif parent.isWidgetType(): 返回parent.style().pixelMetric(pm,None,parent) 其他: 返回parent.spating() 类气泡(QtGui.QLabel): 定义初始化(self,text): 超级(气泡,自我)。\uuuuu初始化\uuuuuuu(文本) self.word=文本 self.setContentsMargins(5,5,5,5) def paintEvent(自身,事件): painter=QtGui.QPainter(自) painter.setRenderHint(QtGui.QPainter.Antialiasing,True) 油漆工( 0,0,self.width()-1,self.height()-1,5,5) 超级(泡泡,自我)。绘画事件(事件) 类主窗口(QtGui.QMainWindow): def uuu init uuu(self,text,parent=None): 超级(主窗口,自我)。\uuuuu初始化\uuuuuuu(父级) self.mainArea=QtGui.QScrollArea(self) self.mainArea.SetWidgetResizeable(True) widget=QtGui.QWidget(self.mainArea) widget.setMinimumWidth(50) 布局=流程布局(小部件) self.words=[] 对于text.split()中的单词: 标签=气泡(字) label.setFont(QtGui.QFont('SblHebrew',18)) label.setFixedWidth(label.sizeHint().width()) self.words.append(标签) layout.addWidget(标签) self.mainArea.setWidget(小部件) self.setCentralWidget(self.main区域) 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': app=QtGui.QApplication(sys.argv) window=MainWindow(《哈利波特》是一系列奇幻文学作品) window.show() sys.exit(app.exec_())
以下是流程布局演示脚本的PyQt5版本:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class FlowLayout(QtWidgets.QLayout):
    def __init__(self, parent=None, margin=-1, hspacing=-1, vspacing=-1):
        super(FlowLayout, self).__init__(parent)
        self._hspacing = hspacing
        self._vspacing = vspacing
        self._items = []
        self.setContentsMargins(margin, margin, margin, margin)

    def __del__(self):
        del self._items[:]

    def addItem(self, item):
        self._items.append(item)

    def horizontalSpacing(self):
        if self._hspacing >= 0:
            return self._hspacing
        else:
            return self.smartSpacing(
                QtWidgets.QStyle.PM_LayoutHorizontalSpacing)

    def verticalSpacing(self):
        if self._vspacing >= 0:
            return self._vspacing
        else:
            return self.smartSpacing(
                QtWidgets.QStyle.PM_LayoutVerticalSpacing)

    def count(self):
        return len(self._items)

    def itemAt(self, index):
        if 0 <= index < len(self._items):
            return self._items[index]

    def takeAt(self, index):
        if 0 <= index < len(self._items):
            return self._items.pop(index)

    def expandingDirections(self):
        return QtCore.Qt.Orientations(0)

    def hasHeightForWidth(self):
        return True

    def heightForWidth(self, width):
        return self.doLayout(QtCore.QRect(0, 0, width, 0), True)

    def setGeometry(self, rect):
        super(FlowLayout, self).setGeometry(rect)
        self.doLayout(rect, False)

    def sizeHint(self):
        return self.minimumSize()

    def minimumSize(self):
        size = QtCore.QSize()
        for item in self._items:
            size = size.expandedTo(item.minimumSize())
        left, top, right, bottom = self.getContentsMargins()
        size += QtCore.QSize(left + right, top + bottom)
        return size

    def doLayout(self, rect, testonly):
        left, top, right, bottom = self.getContentsMargins()
        effective = rect.adjusted(+left, +top, -right, -bottom)
        x = effective.x()
        y = effective.y()
        lineheight = 0
        for item in self._items:
            widget = item.widget()
            hspace = self.horizontalSpacing()
            if hspace == -1:
                hspace = widget.style().layoutSpacing(
                    QtWidgets.QSizePolicy.PushButton,
                    QtWidgets.QSizePolicy.PushButton, QtCore.Qt.Horizontal)
            vspace = self.verticalSpacing()
            if vspace == -1:
                vspace = widget.style().layoutSpacing(
                    QtWidgets.QSizePolicy.PushButton,
                    QtWidgets.QSizePolicy.PushButton, QtCore.Qt.Vertical)
            nextX = x + item.sizeHint().width() + hspace
            if nextX - hspace > effective.right() and lineheight > 0:
                x = effective.x()
                y = y + lineheight + vspace
                nextX = x + item.sizeHint().width() + hspace
                lineheight = 0
            if not testonly:
                item.setGeometry(
                    QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint()))
            x = nextX
            lineheight = max(lineheight, item.sizeHint().height())
        return y + lineheight - rect.y() + bottom

    def smartSpacing(self, pm):
        parent = self.parent()
        if parent is None:
            return -1
        elif parent.isWidgetType():
            return parent.style().pixelMetric(pm, None, parent)
        else:
            return parent.spacing()

class Bubble(QtWidgets.QLabel):
    def __init__(self, text):
        super(Bubble, self).__init__(text)
        self.word = text
        self.setContentsMargins(5, 5, 5, 5)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
        painter.drawRoundedRect(
            0, 0, self.width() - 1, self.height() - 1, 5, 5)
        super(Bubble, self).paintEvent(event)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, text, parent=None):
        super(MainWindow, self).__init__(parent)
        self.mainArea = QtWidgets.QScrollArea(self)
        self.mainArea.setWidgetResizable(True)
        widget = QtWidgets.QWidget(self.mainArea)
        widget.setMinimumWidth(50)
        layout = FlowLayout(widget)
        self.words = []
        for word in text.split():
            label = Bubble(word)
            label.setFont(QtGui.QFont('SblHebrew', 18))
            label.setFixedWidth(label.sizeHint().width())
            self.words.append(label)
            layout.addWidget(label)
        self.mainArea.setWidget(widget)
        self.setCentralWidget(self.mainArea)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow('Harry Potter is a series of fantasy literature')
    window.show()
    sys.exit(app.exec_())
导入系统 从PyQt5导入QtCore、QtGui、QtWidgets 类FlowLayout(QtWidgets.QLayout): 定义初始化(self,parent=None,margin=-1,hspacing=-1,vspacing=-1): 超级(FlowLayout,self)。\uuuuu初始化\uuuuuu(父级) 自排=自排 self.\u vspacking=vspacking self._项=[] self.setContentsMargins(边距、边距、边距、边距) 定义(自我): 删除自身项目[:] def附加项(自身,项目): self.\u items.append(项目) def水平间距(自): 如果self.\u hspacing>=0: 返回自我 其他: 返回自定间距( qtwidts.QStyle.PM_layoutAuthorizontalSpacing) def垂直间距(自): 如果self.\u vspacing>=0: 返回自我空间 其他: 返回自定间距( qtwidts.QStyle.PM_布局垂直间距) def计数(自身): 返回len(自身项目) def itemAt(自身,索引): 如果0: x=有效。x() y=y+线宽+vspace nextX=x+item.sizeHint().width()+hspace 线宽=0 如果不只是测试: