Use QLCDNumber in editor



  • Hello everyone,

    I am currently working on a graphical editor that should use Qt controls next to other elements.
    Via a menu the user can drag/drop elements onto a canvas and parameterize them.

    I found this to be fairly easy to realize for eg. QPushButton:
    @void GfxButtonItem::drawContent(QPainter *painter, const QRect &targetRect, Qt::AspectRatioMode ratio, const QStyleOptionGraphicsItem *option)
    {
    Q_UNUSED(option);

    QStyleOptionButton button;
    button.state = QStyle::State_Active | QStyle::State_Enabled;
    button.rect = m_rect.toAlignedRect();
    button.text = m_buttonText;
    
    painter->save();
    painter->setFont(m_font);
    painter->setPen(m_pen);
    
    painter->beginNativePainting();
    qApp->style()->drawControl(QStyle::CE_PushButton, &button, painter);
    painter->endNativePainting();
    painter->restore();
    

    }@

    How can I achieve the same for QLCDNumber?



  • I found a possible solution involving QPixmap:

    @void GfxLCDItem::drawContent(QPainter *painter, const QRect &targetRect, Qt::AspectRatioMode ratio, const QStyleOptionGraphicsItem *option)
    {
    Q_UNUSED(option);

    QLCDNumber *lcd = new QLCDNumber();
    lcd->setFixedWidth(m_rect.width());
    lcd->setFixedHeight(m_rect.height());
    lcd->display(m_value);
    
    QPixmap pm = QPixmap::grabWidget(lcd, m_rect.toAlignedRect());
    
    painter->drawPixmap(m_rect.toAlignedRect(), pm);
    

    }@

    This works, but it just does not look right. Is there any better way to achieve this?


  • Moderators

    [quote author="weirdal" date="1384348988"]
    This works, but it just does not look right. Is there any better way to achieve this?[/quote]
    IIRC QLCDWidget is a custom widget, meaning it is not part of the style mechanism. So the drawing only happens in the widget's paint method.

    Thus there is basically no other way like you did. Except that you don't need the extra step of an QPixmap and could draw directly to the QPainter by using QWidget::render().

    Also i wouldn't create a instance in every paint() call. Also your current implementation leaks.



  • Thank you for responding, raven-worx.

    I was not aware that I could draw the widget directly by QWidget::render(), thanks for the hint. I found the current solution using a pixmap somewhere in the web.

    Meanwhile, I also extracted the creation of the pixmap to an external method, calling it only when changes have been made. But I will change that to QWidget::render() asap...

    I am originally a C# developer and pretty new to C++ as well as Qt. So please excuse any noob mistakes and questions :)

    @GfxLCDItem::~GfxLCDItem()
    {
    delete m_lcdNumber;
    }

    void GfxLCDItem::drawContent(QPainter *painter, const QRect &targetRect, Qt::AspectRatioMode ratio, const QStyleOptionGraphicsItem *option)
    {
    Q_UNUSED(option);

    // draw the item
    m_lcdNumber->render(painter, QPoint(0, 0));
    

    }

    void GfxLCDItem::updateLCDItem()
    {
    if (!m_lcdNumber)
    m_lcdNumber = new QLCDNumber();

    m_lcdNumber->setFixedWidth(m_rect.width());
    m_lcdNumber->setFixedHeight(m_rect.height());
    m_lcdNumber->display(m_value);
    

    }@

    Does that look any better to you?


  • Moderators

    i wouldn't create and delete a object everytime you need it. Instead create it the first time and keep it for future use:
    @
    void GfxLCDItem::createLCDPixmap()
    {
    static QLCDNumber *lcd = new QLCDNumber(parentWidget); //declaring the variable static ensures that it is only executed on the first time. Also setting a parent widget so Qt takes care of deletion at the appropriate time
    lcd->hide(); //since we set a parent-widget and don't want it to show up there
    lcd->ensurePolished(); //just make sure all style attributes are set
    lcd->setFixedWidth(m_rect.width());
    lcd->setFixedHeight(m_rect.height());
    lcd->display(m_value);

    m_lcdPixmap = QPixmap::grabWidget(lcd, m_rect.toAlignedRect());
    

    }
    @

    Alternatively to the "static" varaint you can also create the widget as a member and delete it in the destructor.
    Also it's probably the best that not every graphics item hold it's own widget for rendering. Instead create the widget on a central place and get it from there, initialize it's properties and paint it.

    Keeping the allocations in the memory at a minimum leads to a better performance. You probably won't notice this in a small application though...



  • Sorry, I just updated my previous post with the altered code.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.