-2

I have developed some functionality that generates the following rows of output: 6 QLabels with pixmaps assigned to them, as well as 6 additional QLabels with assigned text that are positioned over the pixmap QLabels. Below the above set of labels, I include an additional QLabel with more information, before the cycle repeats. Below is an example image:

enter image description here

The output generated is based on the length of the list object the function is pulling in and will sometimes be larger than can be displayed in the window. I've made several attempts to create a scroll area to add my output to, but nothing works to recreate the layout shown above. QVBoxLayout and QHBoxLayout will stack each individual QLabel separately, either vertically or horizontally, which isn't the visual I'm trying to create (as shown above). Below is an example of output that is longer than can be shown in the window:

enter image description here

Not sure if there's some other way to create the layout I'm trying to put together, but if anyone can figure out a solution that doesn't incorporate QVBoxLayout or QHBoxLayout for adding scroll bars to a window, that would be great. Below is the code that generates the incorrect output:

def create_sample_images(self, sample_numbers):

    # example of sample_numbers = [01,18,2022,1,2,3,4,5,6,2.0,$100 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()

Below is an example of the bad output. All widgets are being stacked on top of each other and displayed vertically or horizontally (vbox/hbox):

Screenshot of incorrect output being generated by scrollarea code provided

embersofadyingfire
  • 523
  • 1
  • 4
  • 16
  • 1
    I don't understand. In the code you're showing you're adding widgets with fixed geometries, and there's no trace of a QScrollArea in all of it. What does `self` refer to? Please provide a valid [mre]. – musicamante Jan 18 '22 at 02:13
  • Scroll area code tried previously has been added – embersofadyingfire Jan 19 '22 at 00:53
  • Sorry but your example is still not very *reproducible*, the sample in the commented code has an invalid syntax and it seems like the cycle expects a list of lists. Please read more carefully the link above, we must be able to *easily* reproduce the code without trying to understand *how* to reproduce it. Besides, it seems like you need a nested layout structure, possibly using a QGridLayout. I suggest you to read more about [layout managers](//doc.qt.io/qt-5/layout.html) to better understand how they work, and remember that setting geometries of widgets added to a layout is pointless. – musicamante Jan 19 '22 at 01:34

2 Answers2

1

you can use "gridlayout" or set limit for your items with use "setMinimumSize" below like this example

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  |  $400  |  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
  • 614
  • 4
  • 6
  • SimoN, your code definitely produces the type of output I'm wanting to display, and also produces the scrolling functionality I've been trying to add. I still need to figure out how to incorporate my desired output from the list object I'm pulling data from, but right now your contribution looks very promising. I'll report back once I've figured out how to incorporate your solution. Thank you! – embersofadyingfire Jan 26 '22 at 06:30
0

Using SimoN SavioR's tips and example code above, I figured out how to reconstruct my function to produce the results I was looking for, which mimic what SimoN produced in his example. Primarily, the biggest issues I think I had in my previous code is using Vbox instead of Grid, and assigning the Widget to Vbox instead of assigning the Widget to a layout. Below is my new code for my function which now works as desired, along with an example screenshot of the new output I'm getting. After studying SimoN's code and understanding how it produced the output, I managed to integrate certain chunks of code into my own original code in order to get the function to work appropriately and display the output the way I wanted it originally. The main code blocks I borrowed from SimoN were the two blocks before the for loop, and the block right after the for loop. I was able to keep all the rest of my original code, with some slight modifications to get it all to work together.

    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()

enter image description here

My props to SimoN SavioR for helping me out with their greater understanding of layouts; couldn't have figured out a final solution without their contribution!

embersofadyingfire
  • 523
  • 1
  • 4
  • 16