Results 1 to 6 of 6

Thread: Scaling Background Image behind Widgets / dynamic stylesheet resources ?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jun 2010
    Posts
    2
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Scaling Background Image behind Widgets / dynamic stylesheet resources ?

    I'm simply trying to show a (nicely scaled) image as the background of some kind of container, with layout managed widgets (buttons).

    This use of stylesheets works perfectly :

    m_ui->my_frame->setStyleSheet("image: url(myGraphic.jpg); background-repeat: repeat;");
    Unfortunately, this code won't work for me. I need to load the graphic dynamically (using QImage or QPixmap, say), not from the resource management system or the hard-drive, and I can't see how to do that with stylesheets.

    Deriving a custom Frame, and writing a special also works, though it feels a lot like a hack, and causes performance issues when the Frame is re-sized. (in the code below, the custom Frame has a pixmap variable that has been pre-loaded with the graphic):

    void BackgroundFrame::paintEvent(QPaintEvent *pe)
    {
    if(!pixmap.isNull())
    {
    QPainter myPainter(this);
    pixmap.scaled(width(),height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    myPainter.drawPixmap(0,0, pixmap);
    }
    QFrame::paintEvent(pe);
    }

    I feel that there should be some way to do this with just a couple lines of code and/ or the simple QT designer built into QT Creator, but I haven't been able to find any examples.

    What is the correct way to do this?

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Scaling Background Image behind Widgets / dynamic stylesheet resources ?

    You wanted code tags not qtclass tags.

    This use of stylesheets works perfectly :
    Qt Code:
    1. m_ui->my_frame->setStyleSheet("image: url(myGraphic.jpg); background-repeat: repeat;");
    To copy to clipboard, switch view to plain text mode 
    Unfortunately, this code won't work for me. I need to load the graphic dynamically (using QImage or QPixmap, say), not from the resource management system or the hard-drive, and I can't see how to do that with stylesheets.
    Assuming the background will not change often then you could write the image to a temporary file and dynamically update the style string to point at it.

  3. #3
    Join Date
    Jun 2010
    Posts
    2
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Scaling Background Image behind Widgets / dynamic stylesheet resources ?

    You wanted code tags not qtclass tags.
    My bad, won't happen again. (thanks for the heads up)

    Assuming the background will not change often then you could write the image to a temporary file and dynamically update the style string to point at it.
    There are a couple reasons I didn't want to do that.

    1) The background will change as often as the user presses the next button. This could end up being three or four times in a second, depending on what the user is trying to do.
    2) Writing/Reading to/from a temporary file on the hard-drive when you already have the graphic loaded into memory doesn't seem like a reasonable solution, and could (potentially) cause permission-related difficulties down the road.

    Is there really no way to reference an object in memory instead of a file for stylesheets? How would someone load a skin from a database?

  4. #4
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Scaling Background Image behind Widgets / dynamic stylesheet resources ?

    You can do this with a QAbstractFileEngine. Following is code:
    Header:
    Qt Code:
    1. #ifndef TEST14_H
    2. #define TEST14_H
    3.  
    4. #include <QtGui/QMainWindow>
    5. #include <QAbstractFileEngineHandler>
    6. #include <QAbstractFileEngine>
    7. #include <QDateTime>
    8. #include <QByteArray>
    9. #include <QtAlgorithms>
    10.  
    11. class MainWindow : public QMainWindow
    12. {
    13. Q_OBJECT
    14.  
    15. public:
    16. MainWindow(QWidget *parent = 0);
    17. ~MainWindow();
    18. };
    19.  
    20. class NumbatEngineHandler : public QAbstractFileEngineHandler
    21. {
    22. public:
    23. QAbstractFileEngine *create(const QString &fileName) const;
    24. };
    25.  
    26. class NumbatEngine : public QAbstractFileEngine
    27. {
    28. public:
    29. NumbatEngine(const QString& fileName);
    30. bool caseSensitive () const { return false; }
    31. bool close () { return true; }
    32. QStringList entryList ( QDir::Filters filters, const QStringList & filterNames ) const { return QStringList(); }
    33. FileFlags fileFlags ( FileFlags type = FileInfoAll ) const
    34. { return QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ExeOtherPerm | QAbstractFileEngine::FileType | QAbstractFileEngine::WriteOtherPerm; }
    35. QString fileName ( FileName file = DefaultName ) const { return m_fileName; }
    36. QDateTime fileTime ( FileTime time ) const { return QDateTime(); }
    37. bool mkdir ( const QString & dirName, bool createParentDirectories ) const { return false; }
    38. QString owner ( FileOwner owner ) const { return QString(); }
    39. uint ownerId ( FileOwner owner ) const { return -2; }
    40. bool remove () { return false; }
    41. bool rename ( const QString & newName ) { return false; }
    42. bool rmdir ( const QString & dirName, bool recurseParentDirectories ) const { return false; }
    43. void setFileName ( const QString & file ) { m_fileName = file; }
    44. bool setPermissions ( uint perms ) { return false; }
    45. bool setSize ( qint64 size ) { m_bytes->resize(size); return true; }
    46. qint64 size () const { return m_bytes->size(); }
    47. bool seek ( qint64 offset ) { m_filePos = offset; return true; }
    48. bool open ( QIODevice::OpenMode mode ) { return true; }
    49. bool isRelativePath () const { return false; }
    50. qint64 write ( const char * data, qint64 len );
    51. qint64 read ( char * data, qint64 maxlen );
    52.  
    53. private:
    54. QByteArray* m_bytes;
    55. QString m_fileName;
    56. qint64 m_filePos;
    57. };
    58.  
    59. #endif // TEST14_H
    To copy to clipboard, switch view to plain text mode 
    Source:
    Qt Code:
    1. #include "Test14.h"
    2. #include <QMap>
    3. #include <QPixmap>
    4. #include <QLabel>
    5. #include <QApplication>
    6. #include <QDebug>
    7.  
    8. QAbstractFileEngine * NumbatEngineHandler::create(const QString &fileName) const
    9. {
    10. // We handle all files which start with ???
    11. if (fileName.toLower().startsWith("???"))
    12. return new NumbatEngine(fileName);
    13. else
    14. return 0;
    15. }
    16.  
    17.  
    18. NumbatEngine::NumbatEngine(const QString& fileName)
    19. : QAbstractFileEngine(), m_fileName(fileName), m_filePos(0)
    20.  
    21. {
    22. static QMap<QString, QByteArray*> map;
    23.  
    24. if (map.contains(m_fileName))
    25. {
    26. m_bytes = map.value(m_fileName);
    27. }
    28. else
    29. {
    30. m_bytes = new QByteArray;
    31. map[m_fileName] = m_bytes;
    32. }
    33. }
    34.  
    35. qint64 NumbatEngine::write ( const char * data, qint64 len )
    36. {
    37. if (m_filePos + len > m_bytes->size()) m_bytes->resize(m_filePos + len);
    38.  
    39. qCopy(data, data + len, m_bytes->data() + m_filePos);
    40.  
    41. m_filePos += len;
    42.  
    43. return len;
    44. }
    45.  
    46. qint64 NumbatEngine::read ( char * data, qint64 maxlen )
    47. {
    48. qint64 readBytes;
    49.  
    50. if (m_filePos + maxlen > m_bytes->size())
    51. readBytes = m_bytes->size() - m_filePos;
    52. else
    53. readBytes = maxlen;
    54.  
    55. qCopy(m_bytes->constData() + m_filePos,
    56. m_bytes->constData() + m_filePos + readBytes, data);
    57.  
    58. m_filePos += readBytes;
    59.  
    60. return readBytes;
    61. }
    62.  
    63.  
    64.  
    65. /* Demonstration. */
    66. MainWindow::MainWindow(QWidget *parent)
    67. : QMainWindow(parent)
    68. {
    69. QPixmap pix("image.jpeg");
    70. pix.save("???Hello.jpg");
    71.  
    72. QLabel * lbl = new QLabel;
    73. lbl->setStyleSheet("QLabel {background-image:url(\"???Hello.jpg\");}");
    74. setCentralWidget(lbl);
    75. }
    76.  
    77.  
    78. MainWindow::~MainWindow()
    79. {
    80. }
    81.  
    82. int main(int argc, char **argv)
    83. {
    84. QApplication app(argc, argv);
    85.  
    86. NumbatEngineHandler engine;
    87.  
    88. MainWindow window;
    89. window.show();
    90.  
    91. return app.exec();
    92. }
    To copy to clipboard, switch view to plain text mode 

  5. The following user says thank you to numbat for this useful post:

    PEM (18th June 2010)

  6. #5

    Default Re: Scaling Background Image behind Widgets / dynamic stylesheet resources ?

    Hi,

    for some reason stylesheet doesn't want to display files from NumbatEngine. Copying file back from NumbatEngine to hard disk as following writes the file just fine, i.e. it's not damaged or something:

    Qt Code:
    1. QPixmap pixFromNumbat("???Hello.jpg");
    2. pixFromNumbat.save("pixFromNumbat.jpg");
    To copy to clipboard, switch view to plain text mode 

    Also, stylesheet does display the image if it's read from hard disk (by disabling NumbatEngine from main()).

    I'm using Qt 4.7.2. Please, can anyone confirm that NumbatEngine works for you? I'm desperate

    EDIT
    This works too (taken from):
    Qt Code:
    1. /* Demonstration. */
    2. MainWindow::MainWindow(QWidget *parent)
    3. : QMainWindow(parent)
    4. {
    5. QPixmap pix("image.jpeg");
    6. pix.save("???Hello.jpg");
    7.  
    8. QLabel * lbl = new QLabel;
    9. //lbl->setStyleSheet("QLabel {background-image:url(\"???Hello.jpg\");}");
    10. lbl->setText("<b> this is a test</b><img src=\"???Hello.jpg\" />");
    11. setCentralWidget(lbl);
    12. }
    To copy to clipboard, switch view to plain text mode 

    but it doesn't work for styleSheet. Bug in Qt?
    Last edited by Flakes; 21st March 2011 at 16:27.

  7. #6
    Join Date
    Jun 2012
    Posts
    2

    Default Re: Scaling Background Image behind Widgets / dynamic stylesheet resources ?

    For posterity and because Google return this as the first result, the solution is to edit the widget palette with a brush using a QImage as "stamp".

    Qt Code:
    1. QPalette p = palette();
    2. QBrush brush = QBrush(generateMyQImage());
    3. p.setBrush(QPalette::Base, brush);
    4. p.setBrush(QPalette::Window, brush);
    5. setPalette(p);
    6. setAutoFillBackground(true);
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. background-image on a set of widgets
    By asieriko in forum Qt Programming
    Replies: 4
    Last Post: 22nd May 2010, 08:59
  2. Setting QDial background image using stylesheet
    By dpatel in forum Qt Programming
    Replies: 0
    Last Post: 28th April 2010, 14:13
  3. Zooming effect by scaling widgets
    By Cruz in forum Qt Programming
    Replies: 3
    Last Post: 1st February 2009, 10:43
  4. Resources in dynamic libraries
    By seneca in forum Qt Programming
    Replies: 0
    Last Post: 19th January 2009, 18:26
  5. Replies: 1
    Last Post: 8th October 2007, 00:02

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.