Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

implement paintEvent of QAbstractButton



  • I subclassed a widget from QAbstractButton which should be represented by its attached icon. However i dont see anything with my paint impkementation. I already sorted out with a QPushButton, that the ressource icon is really shown (QPushButton shows the icon).

    I tryed this but it does not work:

    #include "cellbutton.h"
    
    #include <QIcon>
    #include <QPainter>
    
    CellButton::CellButton(CellButton::State state, QWidget *parent)
        :QAbstractButton{ parent },
          mHasBomb{ static_cast<bool>(state) }
    {
        setFixedSize(17, 17);
    
        setIcon(QIcon{":ressources/cell_covered"});
    }
    
    void CellButton::paintEvent(QPaintEvent * /*event*/)
    {
        QPainter painter;
        icon().paint(&painter, geometry());
    }
    

  • Moderators

    You need to give the painter something to paint on i.e.
    QPainter painter(this);
    otherwise all draw calls just do nothing.



  • I updated the method to

        QPainter painter{ this };
        icon().paint(&painter, geometry());
    

    still no icon gets painted.


  • Lifetime Qt Champion

    Hi,

    Check that the icon is valid.



  • i did by running this in main:

        QApplication app(argc, argv);
        QPushButton button;
        button.setIcon(QIcon{":ressources/cell_covered"});
        button.show();
        return QApplication::exec();
    

  • Lifetime Qt Champion

    By the way, why not paint the image directly ?



  • i also tryed that

    void CellButton::paintEvent(QPaintEvent * /*event*/)
    {
        QPainter painter{ this };
    
        QImage image{":ressources/cell_covered"};
        qDebug() << image.isNull();
        painter.drawImage(geometry(), image);
    }
    

    to test i run main like this:

    #include <QApplication>
    
    #include "cellbutton.h"
    
    #include <QPushButton>
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
    //    QPushButton button;
    //    button.setIcon(QIcon{":ressources/cell_covered"});
    //    button.show();   
        
        CellButton button(CellButton::State::empty);
        button.show();
        return QApplication::exec();
    }
    

    But nothing i only get a small empty gray window:

    6656fed9-2c6a-41c4-9937-bd49414994f6-image.png


  • Lifetime Qt Champion

    What should appear ?



  • i expected this:

    c084bef1-10f4-4c0e-a88c-2f7016370278-image.png

    this has like the button 17x17 size

    in qPushbutton icon it looks like this:

    dfddb298-4187-4634-8d3d-ea9702de79d6-image.png

    I also checkd the geometry like this:

    void CellButton::paintEvent(QPaintEvent * /*event*/)
    {
        QPainter painter{ this };
    
        QImage image{":ressources/cell_covered"};
        qDebug() << image.isNull();
        qDebug() << geometry().x();
        qDebug() << geometry().y();
        qDebug() << geometry().width();
        qDebug() << geometry().height();
        painter.drawImage(geometry(), image);
    }
    

    Ans it shows that it has the defined size of 17x 17.



  • I still think that you're not loading the icon correctly.
    Typically, an item from the resources has a prefix of ":/"
    so in your case it should probably be ":/ressources/cell_covered.png"



  • i added the / but no difference. Still no display. As you can see at the top i already could load the QPushbutton without it to test.

    I also throw the ressource system away for test and hard linked the image from a dir like this:

    "/mnt/..../cell_uncovered.png"

    Also here it shows in the Pushbutton but not in mine.



  • ok, I whipped a little test as here:

    
    CellButton::CellButton(bool state, QWidget *parent) :
          QAbstractButton {parent}
        , m_hasBomb { state }
    {
        setFixedSize(64, 64);
        setIcon(QIcon{":/images/x.png"});
        connect(this, &CellButton::pressed, this, [=]() {
            setIcon(QIcon{":/images/pressed.png"});
            setFixedSize(60, 60);
        });
        connect(this, &CellButton::released, this, [=]() {
            setIcon(QIcon{":/images/x.png"});
            setFixedSize(64, 64);
        });
    }
    
    void CellButton::paintEvent(QPaintEvent *e)
    {
        Q_UNUSED(e)
        QPainter painter(this);
        icon().paint(&painter, geometry());
    }
    
    

    This looked ok on ubuntu 19.04/Gnome, Qt 5.13.0. The png's are in a resource file under the /images directory.

    here's the MainWindow used to test (note that CellButton is a QScopedPointer...

    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        m_cellButton.reset(new CellButton(true, this));
        m_cellButton->show();
    
        connect(m_cellButton.data(), &CellButton::clicked, this, [=]() {
            qDebug() << "Button Clicked";
        });
        setCentralWidget(m_cellButton.data());
    }
    


  • I changed nothing from the exampel above except adding the widget into the main window and it works.

    So why i couldn't see any result when i directly only show the button in the Application.

    PS: Is QScopedPointer now common for all the pointer types in QMainWindow? I saw example were only the raw pointers are used.


  • Lifetime Qt Champion

    No it's not. The only reason to use a QScopedPointer with a widget would be that you don't want to make the widget a child of its "container".



  • @sandro4912 There was no particular reason to use a scoped pointer. I'm trying to get away from using raw pointers so whenever I throw together a toy app I tend to experiment.


Log in to reply