自定义QScrollArea

Custom QScrollArea

我已经开发了一些生成以下输出行的功能:6 个 QLabels 分配给它们的像素图,以及 6 个额外的 QLabels 和位于像素图 QLabels 上的分配文本。在上面的标签集下方,我在循环重复之前添加了一个包含更多信息的附加 QLabel。下面是一个示例图片:

生成的输出基于函数拉入的列表对象的长度,有时会比 window 中显示的要大。我已经多次尝试创建一个滚动区域来添加我的输出,但是没有任何方法可以重新创建上面显示的布局。 QVBoxLayout 和 QHBoxLayout 将分别垂直或水平堆叠每个单独的 QLabel,这不是我要创建的视觉效果(如上所示)。下面是一个比 window:

中显示的更长的输出示例

不确定是否有其他方法可以创建我正在尝试组合的布局,但是如果有人能想出一个不包含 QVBoxLayout 或 QHBoxLayout 的解决方案来将滚动条添加到 window, 那太好了。以下是生成错误输出的代码:

def create_sample_images(self, sample_numbers):

    # example of sample_numbers = [01,18,2022,1,2,3,4,5,6,2.0,0 Million,Roll]

    # print(sample_numbers)
    # print(len(sample_numbers))

    # creating the scroll area, widget and vbox
    self.scroll = QScrollArea()
    self.widget = QWidget()
    self.vbox = QVBoxLayout()

    if len(sample_numbers) != 0:

        i = 1
        x = 40
        y = 75
        w = 100
        h = 100

        for item in sample_numbers:

            # print("Here is an item")

            result = item[3:9]
            datevalue = item[:3]
            jackpotvalue = item[10]
            outcome = item[11]
            historylabel = ["DATE: " + str(datevalue[0]) + '-' + str(datevalue[1])
                            + '-' + str(datevalue[2])
                            + '    |   ' + "PRIZE: " + jackpotvalue
                            + '    |   ' + "ROLL (NO WINNER)"]
            result.append(historylabel)

            # print(result)
            # print(type(result))
            # print(datevalue)
            # print(jackpotvalue)
            # print(outcome)
            # print(historylabel)

            for obj in result:

                # print("Here is an obj in item")

                self.outputlabel = QLabel(self)
                self.labeltext = QLabel(self)

                self.labeltext.setText(str(obj))
                self.labeltext.setAlignment(QtCore.Qt.AlignCenter)
                self.labeltext.setStyleSheet("QLabel { color : black; }")

                if i < 6:

                    self.pixmap = QPixmap(u":/graphics/Images/lottoball.png")

                else:

                    self.pixmap = QPixmap(u":/graphics/Images/lottoslip.jpg")

                self.outputlabel.setPixmap(self.pixmap)

                self.outputlabel.resize(self.pixmap.width(),
                                        self.pixmap.height())

                self.outputlabel.setGeometry(x, y, w, h)
                self.labeltext.setGeometry(x, y, w, h)

                # adding labels to vbox
                self.vbox.addWidget(self.outputlabel)
                self.vbox.addWidget(self.labeltext)

                x += 125
                i += 1

                if i == 7:

                    i += 1
                    x = 40
                    y += 125

                elif i > 7:

                    self.outputlabel.setPixmap(None)
                    self.labeltext.setText(historylabel[0])
                    self.labeltext.setStyleSheet("QLabel { color : white; }")
                    self.labeltext.adjustSize()

                    # adding label to vbox
                    self.vbox.addWidget(self.labeltext)

                    i = 1
                    x = 40
                    y += 50

                self.widget.setLayout(self.vbox)

                # Scroll Area Properties
                self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
                self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
                self.scroll.setWidgetResizable(True)
                self.scroll.setWidget(self.widget)

                self.setCentralWidget(self.scroll)

        self.show()

下面是错误输出的示例。所有小部件都堆叠在一起并垂直或水平显示 (vbox/hbox):

您可以使用“gridlayout”或像下面的示例一样使用“setMinimumSize”为您的项目设置限制

from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt



class main(QMainWindow):
    def __init__(self):
        super().__init__()


        self.scroll = QScrollArea()
        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
        self.widget = QWidget()
        self.scroll.setWidgetResizable(True)

        # => grid set
        self.grid = QGridLayout(self.widget)
        self.grid.setContentsMargins(10,40,10,20)
        self.grid.setHorizontalSpacing(20)
        self.grid.setVerticalSpacing(10)

        for i in range(6):            
            for j in range(3):  
                if i % 2 == 1:
                    self.grid.addWidget(QLabel("DateTime => 01.19.2022  |  0  |  ROLL"), i,j, 1,3)
                    break
                else:
                    self.label = QLabel("9")
                    self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                    self.label.setStyleSheet("background-color: red;")

                    # => item set minimum size !
                    self.label.setMinimumSize(120,120)

                    self.grid.addWidget(self.label, i, j, 1,1)

        
        self.scroll.setWidget(self.widget)
        self.setCentralWidget(self.scroll)
        self.resize(600,550)
        self.show()



app = QApplication([])
window = main()
app.exec()

使用 SimoN SavioR 的提示和上面的示例代码,我想出了如何重构我的函数来生成我正在寻找的结果,这模仿了 SimoN 在他的示例中生成的结果。首先,我认为我在以前的代码中遇到的最大问题是使用 Vbox 而不是 Grid,并将 Widget 分配给 Vbox 而不是将 Widget 分配给布局。下面是我的函数的新代码,现在可以按需运行,以及我得到的新输出的示例屏幕截图。在研究了 SimoN 的代码并了解它如何产生输出后,我设法将某些代码块集成到我自己的原始代码中,以使该功能正常工作并以我最初想要的方式显示输出。我从 SimoN 借用的主要代码块是 for 循环之前的两个块,以及 for 循环之后的块。我能够保留我的原始代码的所有其余部分,并进行一些细微的修改以使其协同工作。

    def create_sample_images(self, sample_numbers):

    displaytext = "Displaying " + str(len(sample_numbers)) + " results"

    self.setWindowTitle(displaytext)

    # print(sample_numbers)
    # print(len(sample_numbers))

    # self.gridlayout = QGridLayout()
    # # self.groupbox = QGroupBox("Results")
    # self.vbox = QVBoxLayout()
    # self.scroll = QScrollArea()

    self.scroll = QScrollArea()
    self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
    self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
    self.widget = QWidget()
    self.scroll.setWidgetResizable(True)

    # => grid set
    self.gridlayout = QGridLayout(self.widget) # widget is parent widget
    self.gridlayout.setContentsMargins(10, 40, 10, 20) # left, top, right, bottom
    self.gridlayout.setHorizontalSpacing(20)
    self.gridlayout.setVerticalSpacing(10)

    if len(sample_numbers) != 0:

        i = 1
        ballrow = 0
        inforow = 1
        ballcolumn = 0
        infocolumn = 0

        for item in sample_numbers:

            # print("Here is an item")

            result = item[3:9]
            datevalue = item[:3]
            jackpotvalue = item[10]
            outcome = item[11]

            if outcome == "Roll":

                historylabel = ["Date: " + str(datevalue[0]) + '-' + str(datevalue[1])
                                + '-' + str(datevalue[2])
                                + '  |  ' + "Prize: " + jackpotvalue
                                + '  |  ' + "Roll (No Winner)"]

            else:

                historylabel = ["Date: " + str(datevalue[0]) + '-' + str(datevalue[1])
                                + '-' + str(datevalue[2])
                                + '  |  ' + "Prize: " + jackpotvalue
                                + '  |  ' + "Jackpot Winner(s)"]

            result.append(historylabel)

            # print(result)
            # print(type(result))
            # print(datevalue)
            # print(jackpotvalue)
            # print(outcome)
            # print(historylabel)

            for obj in result:

                # print("Here is an obj in item")

                self.outputlabel = QLabel(self)
                self.labeltext = QLabel(self)

                self.labeltext.setText(str(obj))
                self.labeltext.setAlignment(QtCore.Qt.AlignCenter)
                self.labeltext.setStyleSheet("QLabel { color : black; }")
                self.labeltext.setFont(QFont("Arial", 18))

                if i < 6:

                    self.pixmap = QPixmap(u":/graphics/whiteball.png")

                elif i == 6:

                    self.pixmap = QPixmap(u":/graphics/redball.png")

                self.outputlabel.setPixmap(self.pixmap)

                self.outputlabel.setScaledContents(Qt.KeepAspectRatio)

                # self.outputlabel.resize(self.pixmap.width(),
                #                         self.pixmap.height())

                self.outputlabel.setMinimumSize(112, 112)
                self.labeltext.setMinimumSize(56, 56)
                self.outputlabel.setMaximumSize(112, 112)
                self.labeltext.setMaximumSize(800, 800)

                self.gridlayout.addWidget(self.outputlabel, ballrow, ballcolumn, 1, 1)
                self.gridlayout.addWidget(self.labeltext, ballrow, ballcolumn, 1, 1)

                # self.groupbox.setLayout(self.gridlayout)

                # self.scroll.setLayout(self.gridlayout)

                i += 1
                ballcolumn += 1

                if i == 7:

                    i += 1
                    inforow += 1

                elif i > 7:

                    self.outputlabel.setPixmap(None)
                    self.labeltext.setText("                               " + str(historylabel[0]))
                    self.labeltext.setStyleSheet("QLabel { color : #7393B3; }") #steel blue 4682B4 bright blue 0096FF denim 6F8FAF royal blue 4169E1 blue gray 7393B3
                    self.labeltext.setFont(QFont("Arial", 18))
                    self.labeltext.setAlignment(Qt.AlignmentFlag.AlignLeft)
                    self.gridlayout.addWidget(self.labeltext, inforow, infocolumn, 1, 10)

                    i = 1
                    inforow += 2
                    ballrow += 3
                    ballcolumn = 0

        # widget is parent widget of grid layout. being added to scroll layout
        self.scroll.setWidget(self.widget)
        self.setCentralWidget(self.scroll)
        # resize entire window show to display all objects (width, height)
        # self.resize(1000, 550)
        self.show()

    else:

        x = 265
        y = 225
        w = 275
        h = 100

        self.labeltext = QLabel(self)
        self.labeltext.setText("Sorry, no results to display. Please try again.")
        self.labeltext.setStyleSheet("QLabel { color : white; }")
        self.labeltext.setGeometry(x, y, w, h)

        self.show()

感谢 SimoN SavioR 帮助我更好地理解布局;没有他们的贡献,不可能找到最终的解决方案!