BrianShoe
BrianShoe

Reputation: 11

PyQt Image(pixmap) gets cropped when other content changes width in a widget

I'm making a table-like widget that displays an image, the file name, and two box-selection areas. I have two objects 'grid_row' & 'grid_table' (both using QGridLayout), grid_row being a single row and grid_table containing x number of grid_rows (I'm designing it like this because it's simply easier to keep track of my custom properties).

The tool looks like this

The final layout is a QVBoxLayout, then from top to bottom, I have QHBoxLayout(the one with a label and combobox), grid_row(for the headers 1,2,3), a scroll_area that contains the grid_table with each one being grid_rows. Lastly another QHBoxLayout for the buttons.

Each grid_row contains a 'image-widget', and two region labels(QLabel). The image widget contains a label(I used setPixmap for display) and a pushbutton. Here are my grid_row and image_widget classes:

class grid_row(QWidget):
    def __init__(self, parent=None):
        super().__init__()
        #self.frame = frame_main()
    
        self.grid_layout = QGridLayout()
        self.grid_layout.setSpacing(50)

        self.image_widget = image_widget()
    
        self.grid_layout.addWidget(self.image_widget, 0, 0, 1, 1, Qt.AlignHCenter)

    
        self.region_2 = QLabel('null')
        self.grid_layout.addWidget(self.region_2, 0, 2, 1, 1, Qt.AlignHCenter)

        self.setLayout(self.grid_layout)

        self.region_1 = QLabel('null')
        self.grid_layout.addWidget(self.region_1, 0, 1, 1, 1, Qt.AlignHCenter)
class image_widget(QWidget):
    def __init__(self, parent=None):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setAcceptDrops(True)
        self.image_widget_layout = QHBoxLayout()
        self.image_widget_label = QLabel()
        self.image_widget_label.setPixmap(QPixmap('default.png').scaled(96, 54))
        self.image_widget_layout.addWidget(self.image_widget_label)
        self.img_btn = QPushButton()
        self.img_btn.setEnabled(False)
        self.img_btn.setText('Drag Here!') 
        self.image_widget_layout.addWidget(self.img_btn)
        self.setLayout(self.image_widget_layout)
if __name__ == '__main__': 
    app = QApplication(sys.argv)
    widget = QWidget()
    layout = QVBoxLayout()
    grid_row = grid_row()
    layout.addWidget(grid_row)
    btn = QPushButton('press')
    btn.clicked.connect(lambda: grid_row.region_1.setText('[0,0,1920,1080]'))
    layout.addWidget(btn)
    widget.setLayout(layout)
    scroll_area = QScrollArea()
    scroll_area.setWidget(widget)
    scroll_area.show()
    sys.exit(app.exec_())

So currently, I've implemented events that allow me to drag images into the image_widget and click the push button to modify the two regions that are framed (format: [x1, y1, x2, y2]). The problem is that when I do that(e.g. region values go from 'null' to say '[20,20, 500, 500]', the image gets squished because now the labels are taking up more width.

I realize that some size policy needs to be set (and maybe other properties) but I don't know which property to use and on which widget. I want the image to remain the same. Maybe stretch out the width of each column for the grid_row?

To clarify, I want the label containing the pixmap to remain the same size (always 96*54) and fully displayed(not cropped or stretched) at all times.

I've provided the a simplified executable code to display my problem, the classes are the same as my code, I just only put grid_row inside the scroll_area and added a button to change one of the values of the region to simulate the situation. Can provide additional code if needed. Thanks in advance!

Upvotes: 0

Views: 3051

Answers (2)

BrianShoe
BrianShoe

Reputation: 11

Wow sometimes the answer is really one extra line of code... So the documentation mentions that QScrollArea by default honors the size of its widget. Which is why when I changed the region (to a value that's wider/ more text) the widget does not auto adjust.

I needed to add

scroll_area.setWidgetResizable(True)

to allow the widget to resize wider thus prompting the scroll bars to appear. This way my pixmap image doesn't get cropped from not having enough space.

Upvotes: 1

UmNyobe
UmNyobe

Reputation: 22890

The easiest way would be to add size constraints to the label before adding to the layout

 self.image_widget_label.adjustSize()
 self.image_widget_label.setFixedSize(self.image_widget_label.size())
 self.image_widget_layout.addWidget(self.image_widget_label)

adjustSize would resize the label depending on the contents.

The more difficult way is to answer the questions :

"when I change the size of the overall window, how do I want this particular item to behave? When the window is at its minimal size, which items do I want hidden or out of view? When the window is full size, where do I want empty spots?"

To answer these better read a bit on Qt Layout management

Upvotes: 0

Related Questions