Search code examples
c++qtqwidget

How to add a background image to a QWidget without using QMainWindow?


Edit: The problem is not solved yet, I used @Scheffs answer as a workaround temporarily.

Is it possible to add an image as a background to a Qt widget application created with QWidget as a base class? I'm not using QMainWindow here at all.

In Qt Creator, you can generate skeleton source code files while creating a new project. If you choose QWidget as a base class, and you try to add an image as a background by changing the widgets style sheet (wither manually or from the design section of the IDE), The image doesn't show up when you build the project. How can I fix this if it's possible?

I create a Qt Resource File, add an image (which is in the source code directory), and set the style sheet, That's it. But if I add a background color with

Widget->setStyleSheet(QString::fromUtf8("#Widget {background-color: rgb(55,55,55)};")); 

in ui_widget.h, It works fine and shows up after build.

And if I preview the widget from inside Qt Creator, the image appears, but doesn't after building and running.

Here you choose QWidget as a Base class in Qt Creator:

Creating a new project in Qt Creator

This is main.cpp:

#include "widget.h"
#include <QtCore/qglobal.h>
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

This is ui_widget.h:

#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE
class Ui_Widget
{ 
public:
    void setupUi(QWidget *Widget)
    {
        if (Widget->objectName().isEmpty())
            Widget->setObjectName(QString::fromUtf8("Widget"));
        Widget->resize(600, 150);

        // I add this line, if I changed the style sheet to a simple background color it shows up with no problem {background-color: rgb(1,1,200)}
        Widget->setStyleSheet(QString::fromUtf8("#Widget {background-image: url(:/pic.jpg);}"));

        retranslateUi(Widget);
        QMetaObject::connectSlotsByName(Widget);
    } // setupUi

    void retranslateUi(QWidget *Widget)
    {
        Widget->setWindowTitle(QApplication::translate("Widget", "Widget", nullptr));
    } // retranslateUi

};

namespace Ui {
    class Widget: public Ui_Widget {};
} // namespace Ui

QT_END_NAMESPACE

This is widget.h:

#include <QtCore/qglobal.h>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
};

This is widget.cpp:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); }

Widget::~Widget() { delete ui; }

Sorry for adding the whole generated code but it might be helpful, Thanks.


Solution

  • 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:

    snapshot of testQWidgetBackgroundImage.exe

    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:

    snapshot of ./testQWidgetBackgroundImage