Search code examples
pythonpyqtpyqt5qmainwindow

Background picture in QMainwindow PyQt5


I'm trying to get a background image to my mainwindow but i can't get it to work properly.

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QLabel
from PyQt5.QtGui import QIcon
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSvg import *
from PyQt5.QtWidgets import *
from abc import abstractmethod


class App(QMainWindow):

    def __init__(self, parent=None):
        super(App, self).__init__(parent=parent)
        self.title = 'Title'
        self.left = 500
        self.top = 500
        self.width = 440
        self.height = 280
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # ...

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    #view = TableScene(ex)
    ex.show()
    sys.exit(app.exec_())

I've tried different kinds of methods but none of them works as it should. I found the following code as a solution from another topic but it just gives me a black background and the rest of the widgets get laggy.

     oImage = QImage("table.png")
     sImage = oImage.scaled(QSize(440, 280))
     palette = QPalette()
     palette.setBrush(QPalette.Window, QBrush(sImage))
     self.setPalette(palette)

I don't know if the whole window gets laggy or what really happens but the picture below is a screenshot of a part of the window using the code above, and as you can see it gets all black and the slider shows all the previous position it has been on, sort of laggy anyways.

Image of the "laggy" version

I've also tried the setStyleSheet but I don't know if it's my syntax that's wrong or if it's a faulty way of doing it. Does anyone know a way of doing it correctly?

EDIT

This is my current window:

current view

This is the picture I'm trying to implement as a background to my current window, the picture called "table.png" :

the picture I want as background

This is a visualization of what I'm trying to do, and this is made in paint since I don't know how to do it correctly:

desired view

And this is what I get if i use the code from the other topic:

incorrect view


Solution

  • One of the possible reasons why a black background appears is that QImage is null. And a QImage is null because the image is invalid or because the image path is incorrect. In this case I think it is the second case since the OP uses a relative path that is prone to errors. The solution is to build the absolute path using the script information such as its location:

    import os
    import sys
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
    
    
    class App(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(App, self).__init__(parent=parent)
            self.initUI()
    
        def initUI(self):
            self.setWindowTitle("Title")
            self.setGeometry(500, 500, 440, 280)
            oImage = QtGui.QImage(os.path.join(CURRENT_DIR, "table.png"))
            sImage = oImage.scaled(QtCore.QSize(440, 280))
            palette = QtGui.QPalette()
            palette.setBrush(QtGui.QPalette.Window, QtGui.QBrush(sImage))
            self.setPalette(palette)
    
            pushbutton = QtWidgets.QPushButton("test", self)
            pushbutton.move(100, 100)
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        ex = App()
        ex.show()
        sys.exit(app.exec_())

    enter image description here


    Note: The image provided by the OP has extension .jpg but the one indicated by code is .png, maybe "imgur" has changed the extension.

    Note: If the window is resized manually, the following behavior will be observed:

    enter image description here

    So for this there are 2 possible solutions depending on the developer's criteria:

    • Set a fixed size: self.setFixedSize(440, 280)
    • Adapt the image to the size of the window:

      import os
      import sys
      
      from PyQt5 import QtCore, QtGui, QtWidgets
      
      CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
      
      
      class App(QtWidgets.QMainWindow):
          def __init__(self, parent=None):
              super(App, self).__init__(parent=parent)
              self.initUI()
      
          def initUI(self):
              self.setWindowTitle("Title")
              self.setGeometry(500, 500, 440, 280)
              pushbutton = QtWidgets.QPushButton("test", self)
              pushbutton.move(100, 100)
      
              self.oImage = QtGui.QImage(os.path.join(CURRENT_DIR, "table.png"))
              # or QPixmap
              # self.oPixmap = QtGui.QPixmap(os.path.join(CURRENT_DIR, "table.png"))
      
          def paintEvent(self, event):
              painter = QtGui.QPainter(self)
              painter.drawImage(self.rect(), self.oImage)
              # or QPixmap
              # painter.drawPixmap(self.rect(), self.oPixmap)
      
      
      if __name__ == "__main__":
          app = QtWidgets.QApplication(sys.argv)
          ex = App()
          ex.show()
          sys.exit(app.exec_())
      

      or

      import os
      import sys
      
      from PyQt5 import QtCore, QtGui, QtWidgets
      
      CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
      
      
      class App(QtWidgets.QMainWindow):
          def __init__(self, parent=None):
              super(App, self).__init__(parent=parent)
              self.initUI()
      
          def initUI(self):
              self.setWindowTitle("Title")
              self.setGeometry(500, 500, 440, 280)
              pushbutton = QtWidgets.QPushButton("test", self)
              pushbutton.move(100, 100)
      
              self.setStyleSheet(
                  """
                  QMainWindow{
                      border-image: url(%s) 0 0 0 0 stretch stretch
                  }
                  """
                  % os.path.join(CURRENT_DIR, "table.png")
              )
      
      
      if __name__ == "__main__":
          app = QtWidgets.QApplication(sys.argv)
          ex = App()
          ex.show()
          sys.exit(app.exec_())