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

Draw a QFrame-like rectangle



  • I am trying to draw a rectangle that is QFrame-like with 3D border, but I only ever get a simple 1-pixel rectangle.

    When testing the simplest case, that of a box with a 10-pixels border, my simplified test-code :

    void Win::paintEvent(QPaintEvent * event)
    {
      QWidget::paintEvent(event);
      QPainter painter(this);
      QStyleOptionFrame  option;
      option.initFrom(this);
      option.rect = QRect(100,100,100,100);
      option.lineWidth = 10;
      option.frameShape = QFrame::Box;
      style()->drawPrimitive(QStyle::PE_Frame,  &option,  &painter,  this);
    }
    

    The above draws a 1-pixel rectangle. If I replace the drawPrimitive call with :

    painter.setPen(QPen(Qt::red, 10));
    painter.drawRect(QRect(100,100,100,100));
    

    then the rectangle is correct.

    What am I doing wrong ?


  • Lifetime Qt Champion

    Hi
    Might need
    Option.state = QStyle::State_Sunken; // or what ever
    Since values might be random (not all set by initFrom) ,
    you must set all used for a PE_X style.

    If still not working, check out QFrame source for what it really needs.

    This works for me. ( for line)

           QStyleOptionFrame option;
            option.initFrom(this);
            option.state = QStyle::State_Sunken;
            option.frameShape = QFrame::HLine;
            style()->drawPrimitive(QStyle::PE_Frame, &option, &painter, this);
    


  • @mrjj :

    I have tried to assign every possible documented member variable, but no go.
    The code now looks like :

    void Win::paintEvent(QPaintEvent * event)
    {
      QWidget::paintEvent(event);
      QPainter painter(this);
      QStyleOptionFrame  option;
      option.initFrom(this);
      option.rect = QRect(100,100,100,100);
      option.lineWidth = 10;
      option.frameShape = QFrame::Box;
      option.state = QStyle::State_Sunken;
      option.direction = Qt::LeftToRight;
      option.features = QStyleOptionFrame::Rounded;
      option.fontMetrics = QFontMetrics(QFont("Arial"));
      option.midLineWidth = 4;
      option.type = QStyleOption::SO_Frame;
      style()->drawPrimitive(QStyle::PE_Frame,  &option,  &painter,  this);
    }
    

    I have also tried to take out the call to option.initFrom(this);, but this changed nothing.
    I have even changed option.frameShape = QFrame::HLine;, but I still get a 1-pixel rectangle/line.


  • Moderators

    You are using the wrong drawing function and element. It should be

    style()->drawControl(QStyle::CE_ShapedFrame, &option, &painter, this);
    


  • @Chris-Kawa :

    YES! This was it.
    Unfortunate that drawPrimitive was wrongly recommended so many times on StackOverflow and elsewhere.
    Many thanks.


Log in to reply