Fer-de-lance
Fer-de-lance

Reputation: 421

setting background image for a widget in another class

I've been recently learning pyqt5 as my first gui framework. So far I have been experimenting with QtStackedLayout. I currently have two window screens, one created inside the UI class and another in another separate class. I have two concerns:

  1. Everything was working until I started experimenting on adding a background image for Window 1. There is no image displayed but the code runs ok.
  2. There is this small fraction of time in the beginning where window one will get displayed first until it gets loaded to the mainwindow, I tried passing self during instantiation of the object to sert as some kind of parent to prevent this but I think I'm not doing it right.

See below code (I have bad import statements, I will sort it out)

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class Ui(QWidget):

    def setupUi(self, Main, width, height):
        self.stack = QStackedLayout()
        self.window_1 = WindowOne(width, height)
        self.window_2 = QWidget(self)
        self.window_2_UI()

        self.stack.addWidget(self.window_1)
        self.stack.addWidget(self.window_2)

        # Only one button
        self.btn = QPushButton("Change window", self)

        # Create the central widget of your Main Window
        self.main_widget = QWidget(self)
        layout = QVBoxLayout(self.main_widget)
        layout.addLayout(self.stack)
        layout.addWidget(self.btn)

        self.setCentralWidget(self.main_widget)

        self.btn.clicked.connect(self.change_window)

    def change_window(self):
        if self.stack.currentIndex() == 0:
            self.stack.setCurrentIndex(1)
        else:
            self.stack.setCurrentIndex(0)

    def window_2_UI(self):
        label = QLabel("In Window 2", self.window_2)


class WindowOne(QWidget):
    def __init__(self, width, height):
        super().__init__()
        self.set_bg(width, height)
        self.set_label()
        # self.setStyleSheet("background-image: url(:resource/images/blue_bg.jpg)")

    def set_label(self):
        label = QLabel("In Window 1", self)

    def set_bg(self, w, h):
        oImage = QImage("resource/images/blue_bg.jpg")
        sImage = oImage.scaled(QSize(w, h))
        palette = QPalette()
        palette.setBrush(10, QBrush(sImage))
        self.setPalette(palette)


class Main(QMainWindow, Ui):
    def __init__(self):
        super().__init__()
        self.w_width = 480
        self.w_height = 720
        self.resize(self.w_width, self.w_height)
        self.init_ui()
        self.setupUi(self, self.w_width, self.w_height)

    def init_ui(self):
        self.center()
        self.setWindowTitle('Main Window')

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

if __name__ == "__main__":
    app = QApplication(sys.argv)
    M = Main()
    M.show()
    sys.exit(app.exec())

Upvotes: 1

Views: 4847

Answers (1)

eyllanesc
eyllanesc

Reputation: 243907

By default only the window (which is different to a widget) will use the background color of QPalette, if you want a widget to use the background color of QPalette you must enable the autoFillBackground property.

# ...
self.set_label(width, height)
self.setAutoFillBackground(True)
# ...

Although your code is a little messy, for example you establish that certain methods receive certain parameters but you never use them. Finally I think you want the background of the image to be re-scale using the size of the window so I have override the resizeEvent() method so that scaling takes the size of the window.

Considering all the above, I have improved your code:

import sys

from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.m_stacked_layout = QtWidgets.QStackedLayout()

        self.widget_1 = WidgetOne()
        self.widget_2 = QtWidgets.QWidget()

        self.widget_2_UI()

        self.m_stacked_layout.addWidget(self.widget_1)
        self.m_stacked_layout.addWidget(self.widget_2)

        button = QtWidgets.QPushButton(
            "Change window", clicked=self.change_window
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addLayout(self.m_stacked_layout)
        lay.addWidget(button)

    @QtCore.pyqtSlot()
    def change_window(self):
        ix = self.m_stacked_layout.currentIndex()
        self.m_stacked_layout.setCurrentIndex(1 if ix == 0 else 0)

    def widget_2_UI(self):
        label = QtWidgets.QLabel("In Window 2", self.widget_2)


class WidgetOne(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAutoFillBackground(True)
        self.set_label()
        self.m_image = QtGui.QImage("resource/images/blue_bg.jpg")

    def set_label(self):
        label = QtWidgets.QLabel("In Window 1", self)

    def resizeEvent(self, event):
        palette = self.palette()
        sImage = self.m_image.scaled(event.size())
        palette.setBrush(10, QtGui.QBrush(sImage))
        self.setPalette(palette)
        super(WidgetOne, self).resizeEvent(event)

class Main(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        widget = Widget()
        self.setCentralWidget(widget)

        self.resize(480, 720)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(app.exec())

Upvotes: 2

Related Questions