How to add a background image to a QWidget without using QMainWindow?
Out of curiosity, I tried on my side with my own MCVE.
C++ source testQWidgetBackgroundImage.cc
:
// Qt header:
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("Test Background Image");
qWinMain.resize(640, 480);
qWinMain.setObjectName("Widget");
qWinMain.setStyleSheet("#Widget { background-image: url(cat.jpg); }");
qWinMain.show();
// runtime loop
return app.exec();
}
Build script CMakeLists.txt
:
project(QWidgetBackgroundImage)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(Qt5Widgets CONFIG REQUIRED)
include_directories("${CMAKE_SOURCE_DIR}")
add_executable(testQWidgetBackgroundImage testQWidgetBackgroundImage.cc)
target_link_libraries(testQWidgetBackgroundImage Qt5::Widgets)
Output:
So, I was able to show a plain QWidget
with a background image set by a style sheet, at least, in Windows 10 with VS 2017 and Qt 5.13.
This is in accordance with what is documented in Qt Style Sheets Reference – background:
Shorthand notation for setting the background. Equivalent to specifying background-color, background-image, background-repeat, and/or background-position.
This property is supported by QAbstractItemView subclasses, QAbstractSpinBox subclasses, QCheckBox, QComboBox, QDialog, QFrame, QGroupBox, QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QRadioButton, QSplitter, QTextEdit, QToolTip, and plain QWidgets.
Note:
I must admit that I don't have any experience concerning the use of Qt resources. Hence, I provided the URL just as url(cat.jpg)
which results in the attempt to load from a file in the local current working directory (with success as seen in the snapshot above). The prefixing with :
(e.g. url(:/cat.jpg)
) would address an entry in the Qt resources instead.
Further readings: The Qt Resource System
After having read the doc. in the above link, I noticed that it's not that complicated to use and modified the above MCVE a bit:
C++ source file testQWidgetBackgroundImage.cc
// Qt header:
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("Test Background Image");
qWinMain.resize(640, 480);
qWinMain.setObjectName("Widget");
qWinMain.setStyleSheet("#Widget { background-image: url(:/cat.jpg); }");
qWinMain.show();
// runtime loop
return app.exec();
}
Effectively, the only change was url(cat.jpg)
→ url(:/cat.jpg)
.
Qt resource file testQWidgetBackgroundImage.qrc
:
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource>
<file>cat.jpg</file>
</qresource>
</RCC>
Qt project file testQWidgetBackgroundImage.pro
:
SOURCES = testQWidgetBackgroundImage.cc
RESOURCES = testQWidgetBackgroundImage.qrc
QT += widgets
Built and tested in cygwin64:
$ qmake-qt5 testQWidgetBackgroundImage.pro
$ make && ./testQWidgetBackgroundImage
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQWidgetBackgroundImage.o testQWidgetBackgroundImage.cc
/usr/lib/qt5/bin/rcc -name testQWidgetBackgroundImage testQWidgetBackgroundImage.qrc -o qrc_testQWidgetBackgroundImage.cpp
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o qrc_testQWidgetBackgroundImage.o qrc_testQWidgetBackgroundImage.cpp
g++ -o testQWidgetBackgroundImage.exe testQWidgetBackgroundImage.o qrc_testQWidgetBackgroundImage.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
Qt Version: 5.9.4
Output:
Background picture in QMainwindow PyQt5
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_())
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:
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_())
how to add a background image to a main window without affecting the widgets in Pyqt5
Try it:
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.pushButton1 = QPushButton("Button 1", self.centralwidget)
self.pushButton2 = QPushButton("Button 2", self.centralwidget)
lay = QHBoxLayout(self.centralwidget)
lay.addWidget(self.pushButton1)
lay.addWidget(self.pushButton2)
stylesheet = """
MainWindow {
background-image: url("D:/_Qt/img/cat.jpg");
background-repeat: no-repeat;
background-position: center;
}
"""
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
app.setStyleSheet(stylesheet) # <---
window = MainWindow()
window.resize(640, 640)
window.show()
sys.exit(app.exec_())
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralWidget)
self.horizontalLayout_2.setContentsMargins(11, 11, 11, 11)
self.horizontalLayout_2.setSpacing(6)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setSpacing(6)
self.horizontalLayout.setObjectName("horizontalLayout")
self.start_button = QtWidgets.QPushButton(self.centralWidget)
self.start_button.setObjectName("start_button")
self.horizontalLayout.addWidget(self.start_button)
self.stop_button = QtWidgets.QPushButton(self.centralWidget)
self.stop_button.setObjectName("stop_button")
self.horizontalLayout.addWidget(self.stop_button)
self.horizontalLayout_2.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 26))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
self.statusBar = QtWidgets.QStatusBar(MainWindow)
self.statusBar.setObjectName("statusBar")
MainWindow.setStatusBar(self.statusBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.start_button.setText(_translate("MainWindow", "Start"))
self.stop_button.setText(_translate("MainWindow", "Stop"))
class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
stylesheet = """
QMainWindow {
background-image: url("D:/_Qt/img/cat.jpg");
background-repeat: no-repeat;
background-position: center;
}
"""
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(stylesheet)
w = MyWindow()
# MainWindow = QtWidgets.QMainWindow()
# ui = Ui_MainWindow()
# ui.setupUi(MainWindow)
# MainWindow.show()
w.show()
sys.exit(app.exec_())
How to change the background image of a QMainWindow central widget?
To change the background image of a QWidget you should override the paintEvent method, in your case yours in a QStackedWidget, we create a class that inherits from this:
class StackedWidget(QStackedWidget):
def __init__(self, parent=None):
QStackedWidget.__init__(self, parent=parent)
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(self.rect(), QPixmap("ninja.png"))
QStackedWidget.paintEvent(self, event)
And then you change:
self.central_widget = QStackedWidget()
to:
self.central_widget = StackedWidget()
Example:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class StackedWidget(QStackedWidget):
def __init__(self, parent=None):
QStackedWidget.__init__(self, parent=parent)
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(self.rect(), QPixmap("image.png"))
QStackedWidget.paintEvent(self, event)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setCentralWidget(StackedWidget())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Screenshot:
The case of QStackedWidget is a special case since this is not shown, this serves to show other widgets, to those widgets you must change the background image.
From your code, the first widget they attach is a QMdiArea
, this is also a special case since it has a viewport and this should be changed.
class MdiArea(QMdiArea):
def __init__(self, parent=None):
QMdiArea.__init__(self, parent=parent)
def paintEvent(self, event):
QMdiArea.paintEvent(self, event)
painter = QPainter(self.viewport())
painter.drawPixmap(self.rect(), QPixmap("image.png"))
In your code change:
self.mdi = QMdiArea()
to:
self.mdi = MdiArea()
Screenshots:
How to put a widget on a background image in QMainWindow in Pyqt5?
The issue is not related to the background: the LED widgets are there, the problem is that widgets added to a parent that is already shown (and without using a layout manager) does not make them visible, and they must be explicitly shown by calling show()
or setVisible(True)
.
You can see the difference if you remove the self.show()
line after setting the palette (but leaving the mainWin.show()
at the end): in that case, the leds become automatically visible.
The solution is to either show the child widgets explicitly, or call show()
/setVisible(True)
on the parent after adding them.
How do I set a background image to mainwindow?
Try to add What you have tried so far,with out that we cant help.
Try the below one
setStyleSheet("MainWindow {background-image:url(:/files/MainPic/Technology-Banner1.jpg)}");
How Could I Set The Main Window Background To A Base64 Image In PyQt5 [duplicate]
There is no direct way to do this, so you need to implement the paint event of the main window, and ensure that its central widget does not paint its background (by setting the background color in the stylesheet or using autoFillBackground()
).
The following will render the pixmap at the center:
class Win(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setCentralWidget(QtWidgets.QWidget())
self.bkgnd = QtGui.QPixmap # base64 data ...
def paintEvent(self, event):
qp = QtGui.QPainter(self)
pmRect = self.bkgnd.rect()
pmRect.moveCenter(self.centralWidget().geometry().center())
qp.drawPixmap(pmRect, self.bkgnd)
You can also get tiling:
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.fillRect(self.centralWidget().geometry(), QtGui.QBrush(self.bkgnd))
Or stretch the contents of the image:
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.drawPixmap(self.centralWidget().geometry(), self.bkgnd)
Or scale by keeping the aspect ratio:
def paintEvent(self, event):
qp = QtGui.QPainter(self)
rect = self.centralWidget().geometry()
scaled = self.bkgnd.scaled(rect.size(), QtCore.Qt.KeepAspectRatio)
pmRect = scaled.rect()
pmRect.moveCenter(rect.center())
qp.drawPixmap(pmRect, scaled)
In all the situations above, you can also try to use the full rectangle of the main window (self.rect()
) instead of that of the central widget, if you want to set a background that also renders under menus, toolbars, etc, but I would not suggest you to do so, as it would probably make those elements difficult to see, and it's also possible that some styles would paint their background in any case.
Qt Creator and main window background image
While editing your main window form find styleSheet property, and put something like this:
background: url(:/path/to-your-resource.png)
Related Topics
How Come a Non-Const Reference Cannot Bind to a Temporary Object
Can a Local Variable'S Memory Be Accessed Outside Its Scope
What Are Rvalues, Lvalues, Xvalues, Glvalues, and Prvalues
Can Num++ Be Atomic For 'Int Num'
How to Determine Cpu and Memory Consumption from Inside a Process
What Is the Proper Declaration of Main in C++
Why Can't the Switch Statement Be Applied on Strings
Function With Same Name But Different Signature in Derived Class
Difference Between Float and Double
Why Can In-Class Initializers Only Use = or {}
Store Hex Value as String (Arduino Project)
Why Should I Not #Include ≪Bits/Stdc++.H≫
Passing a 2D Array to a C++ Function
Pointer to Class Data Member "::*"
Order of Evaluation in C++ Function Parameters