Tank widget problem...



  • Hi All,

    My customer wants to see some values not by QProgressBar.. So I tried to make a widget for a week...

    I achived to make a widget that runs that I wanted... but I have some problematic areas..

    I draw a roudedrect first than I paint another empty rounded rect on it... then I fill the edge with a rect.. to make it clear..

    Tha problemmatic areas are rouded red at the picture that I attached..
    0_1511171424781_widgetproblem.png

    cedaTank.h

    #ifndef CEDATANK_H
    #define CEDATANK_H
    
    #include <QWidget>
    
    class cedaTank : public QWidget
    {
        Q_OBJECT
    public:
        explicit cedaTank(QWidget *parent = 0);
    
        int MaxValue = 10000;
        int MinValue = 0;
        int Padding = 5;
        QString Deger1Suffix = "kg";
        QString Deger2Suffix = "cm";
        bool ShowDeger2 = false;
        int Deger2 = 0;
    
    protected:
        void paintEvent(QPaintEvent *);
    signals:
        void valuechanged(int value);
    
    public slots:
        void setValue(int value);
    private:
       int w_value = 24;
       QRectF outlineRect;
       QRectF inlineRect;
       QRectF makeRect;
       QRectF Deger1Rect;
       QRectF Deger2Rect;
    
       int PenWidth = 5;
       QColor outColor = Qt::darkGray;
       QColor inColor = Qt::green;
       QColor EmptyColor = Qt::gray;
       QFont NameFont;
       void Calculate_inlineRect();
       void Calculate_outlineRect();
    };
    
    #endif // CEDATANK_H
    
    

    and the cedaTank.cpp

    #include "cedaTank.h"
    #include <QPainter>
    #include <QDebug>
    
    cedaTank::cedaTank(QWidget *parent) : QWidget(parent)
    {
      NameFont.setFamily("Arial");
      NameFont.setBold(true);
      NameFont.setPointSize(12);
    }
    
    void cedaTank::paintEvent(QPaintEvent *)
    {
    
      QPainter myPainter(this);
      myPainter.setRenderHint(QPainter::Antialiasing);
    
      QPen BorderPen(outColor);
      QBrush inlineBrush(inColor);
      //Dış Çerçeve
      BorderPen.setWidth(PenWidth);
      myPainter.setPen(BorderPen);
      myPainter.setBrush(inlineBrush);
      Calculate_outlineRect();
      myPainter.drawRoundedRect(outlineRect, 25.0, 25.0);
      //İç Dolum
      BorderPen.setColor(outColor);
      BorderPen.setWidth(0);
      myPainter.setPen(BorderPen);
    
      inlineBrush.setColor(EmptyColor);
      myPainter.setBrush(EmptyColor);
      Calculate_inlineRect();
      myPainter.drawRoundedRect(inlineRect, 25.0, 25.0);
    
      myPainter.fillRect(makeRect,EmptyColor);
      //iç Yazı
      BorderPen.setColor(Qt::black);
      myPainter.setPen(BorderPen);
      myPainter.setFont(this->font());
      myPainter.drawText(Deger1Rect,Qt::AlignCenter,QString(QString::number(w_value) + " %1").arg(Deger1Suffix));
      if (ShowDeger2)
      myPainter.drawText(Deger2Rect,Qt::AlignCenter,QString(QString::number(Deger2) + " %1").arg(Deger2Suffix));
      Deger2Rect =  QRectF(outlineRect.x(),
                           outlineRect.y() + PenWidth,
                           outlineRect.width() ,
                           this->fontMetrics().height() + 5);
      BorderPen.setColor(Qt::red);
      myPainter.setPen(BorderPen);
      myPainter.setFont(NameFont);
      myPainter.drawText(Deger2Rect,Qt::AlignCenter,this->objectName());
    
    }
    
    void cedaTank::setValue(int value)
    {
        if (w_value != value){
            if (value <= MaxValue){
                w_value = value;
                emit valuechanged(w_value);
            } else {
                value = MaxValue;
                emit valuechanged(w_value);
            }
    
        }
        repaint();
    }
    
    void cedaTank::Calculate_inlineRect()
    {
    
        qreal carpan,theYOffset,Yukseklik,Genislik;
    //    if ((w_value - MinValue) > 0){
            carpan = qreal(w_value - MinValue) / qreal(MaxValue - MinValue);
            theYOffset = outlineRect.y() + (outlineRect.height() - (carpan * outlineRect.height())) + qreal(PenWidth/2);
            Genislik = outlineRect.width() - qreal(PenWidth);
            //Yukseklik = (outlineRect.height() - (carpan * outlineRect.height()))-PenWidth;
            Yukseklik = (outlineRect.height() - (carpan * outlineRect.height()));
    //    } else {
    //        carpan = 0;
    //        Yukseklik = 0;
    //        Genislik = 0;
    //    }
    
        if (Yukseklik >= (0.2 * outlineRect.height()) ) {
            Genislik = outlineRect.width() - (outlineRect.height()-Yukseklik);
        }
    
        inlineRect =  QRectF(outlineRect.x() , outlineRect.y() ,outlineRect.width(),Yukseklik );
        if ((Yukseklik >= (0.95 * outlineRect.height())) ||  (Yukseklik <= (0.07 * outlineRect.height())) ){
            makeRect = QRectF(inlineRect.x(), inlineRect.y() + (inlineRect.height() - 25 ),0,0);
        } else {
            makeRect = QRectF(inlineRect.x(), inlineRect.y() + (inlineRect.height() - 25 ),inlineRect.width(),26);
        }
        qDebug() << "outlineRect.x() :" << outlineRect.x() << "outlineRect.y() :" << outlineRect.y() << "outlineRect.width() :" << outlineRect.width() << "outlineRect.height() :" << outlineRect.height();
    
        qDebug() << "inlineRect.x() :" << inlineRect.x() << "inlineRect.y() :" << inlineRect.y() << "inlineRect.width() :" << inlineRect.width() << "inlineRect.height() :" << inlineRect.height();
    
    }
    
    void cedaTank::Calculate_outlineRect()
    {
        outlineRect = QRectF(Padding,Padding,this->width() - (Padding * 2 ) , this->height()- (Padding * 2 ));
        Deger1Rect = QRectF(outlineRect.x(),
                            outlineRect.y() + (outlineRect.height() - (outlineRect.height() /4)),
                            outlineRect.width() ,
                            this->fontMetrics().height() + 5);
        Deger2Rect = QRectF(outlineRect.x(),
                            outlineRect.y() + (outlineRect.height() /4),
                            outlineRect.width() ,
                            this->fontMetrics().height() + 5);
    }
    
    

    is there an easy or better way to correct these.. An Idea to solve this?

    Thanks Community..



  • You are trying to reinvent the wheel. That's just a vertical QProgressBar with a stylesheet, a larger minimum width and a child label



  • @zeroptr I was about to write some examples and ideas how to improve your QWidget, but, @VRonin is right.

    Subclass QProgressbar and add a Label to display your value and such. And add the rounded egdes via the stylesheet.



  • 0_1511174844259_8985ede9-3d8a-474e-a8d2-17f46137b13f-image.png

    border-radius: 25;

    has no effect on bottom side...



  • @zeroptr try this

    QProgressBar{border: none; margin:10px; text-align:center;}
    QProgressBar::chunk {background-color: green; border-radius:12px; margin: 2px;}
    


  • 0_1511176978225_3850727f-10e9-48b0-b2b7-151a4873a51a-image.png

    same issiue with my widget. at bottom :)

    QProgressBar{
    	border: solid;
    	border-width:2px;
    	margin:10px ;
    	border-color:darkgray;
    	text-align:center; 
    	border-radius:20px;
    	background-color: lightgrey; }
    QProgressBar::chunk {
    	background-color:rgb(0, 255, 0) ; 
    	
    	border-radius:20px
     }
    

    //your code here



  • @zeroptr Fascinating, it works fine for horizontal layout, but does not in vertival alignment.
    If there's not a stylesheet option that I'm missing, I would label this as a bug.



  • Clipping is the answer to your problems:

    #include "widget.h"
    
    #include <QRectF>
    #include <QPainter>
    #include <QPainterPath>
    #include <QPaintEvent>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {}
    
    Widget::~Widget(){}
    
    QSize Widget::sizeHint() const {
        return QSize(200,200);
    }
    
    void Widget::paintEvent(QPaintEvent *event){
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
    
        QRectF rect(event->rect().adjusted(10,10,-10,-10));
        QPainterPath painterPath;
        painterPath.addRoundedRect(rect,10,10);
        painter.setClipPath(painterPath);
    
        painter.setPen(Qt::NoPen);
        painter.setBrush(Qt::white);
        painter.drawRect(rect);
    
        QRectF levelRect=rect.adjusted(0,rect.height()/2,0,0);
        painter.setBrush(Qt::green);
        painter.drawRect(levelRect);
    
        painter.strokePath(painterPath, QPen(Qt::black));
    
        painter.setClipping(false);
    
        painter.end();
    }
    

    Tank Widget Example

    Setting the clipping path means that no pixels will be drawn outside the specified area (event if you tell it to!). In this case I set the clipping path to have the rounded corners and then draw normal square rectangles; the clipping path ensures the corners are not rendered.

    Hope this helps :)



  • @jazzycamel said in Tank widget problem...:

    thanks @jazzycamel the problem solved...

    And this is the new code maybe some one need this kind of thing..

    #ifndef CEDATANK_H
    #define CEDATANK_H
    
    #include <QWidget>
    
    class cedaTank : public QWidget
    {
        Q_OBJECT
    public:
        explicit cedaTank(QWidget *parent = 0);
    
        int MaxValue = 10000;
        int MinValue = 0;
        int Padding = 5;
        QString Deger1Suffix = "kg";
        QString Deger2Suffix = "cm";
        bool ShowDeger2 = false;
        int Deger2 = 0;
    
    protected:
        void paintEvent(QPaintEvent *);
    signals:
        void valuechanged(int value);
    
    public slots:
        void setValue(int value);
    private:
       int w_value = 24;
       QRectF outlineRect;
       QRectF inlineRect;
    
       QRectF Deger1Rect;
       QRectF Deger2Rect;
    
       int PenWidth = 5;
       QColor outColor = Qt::darkGray;
       QColor inColor = Qt::green;
       QColor EmptyColor = Qt::gray;
       QFont NameFont;
       void Calculate_inlineRect();
       void Calculate_outlineRect();
    };
    
    
    #endif // CEDATANK_H
    
    

    and the cpp

    #include "cedaTank.h"
    #include <QPainter>
    #include <QDebug>
    #include <QPaintEvent>
    
    cedaTank::cedaTank(QWidget *parent) : QWidget(parent)
    {
      NameFont.setFamily("Arial");
      NameFont.setBold(true);
      NameFont.setPointSize(12);
    }
    
    void cedaTank::paintEvent(QPaintEvent *)
    {
    
      QPainter myPainter(this);
      myPainter.setRenderHint(QPainter::Antialiasing);
    
      QPen BorderPen(outColor);
      QBrush inlineBrush(inColor);
      //Dış Çerçeve
      BorderPen.setWidth(PenWidth);
      myPainter.setPen(BorderPen);
      myPainter.setBrush(inlineBrush);
      Calculate_outlineRect();
      myPainter.drawRoundedRect(outlineRect, 25.0, 25.0);
      QPainterPath painterPath;
      painterPath.addRoundedRect(outlineRect,25,25);
      myPainter.setClipPath(painterPath);
    
      //İç Dolum
      BorderPen.setColor(outColor);
      BorderPen.setWidth(0);
      myPainter.setPen(BorderPen);
    
      inlineBrush.setColor(EmptyColor);
      myPainter.setBrush(EmptyColor);
      Calculate_inlineRect();
      myPainter.drawRect(inlineRect);
    
      //myPainter.fillRect(makeRect,EmptyColor);
      //iç Yazı
      BorderPen.setColor(Qt::black);
      myPainter.setPen(BorderPen);
      myPainter.setFont(this->font());
      myPainter.drawText(Deger1Rect,Qt::AlignCenter,QString(QString::number(w_value) + " %1").arg(Deger1Suffix));
      if (ShowDeger2)
      myPainter.drawText(Deger2Rect,Qt::AlignCenter,QString(QString::number(Deger2) + " %1").arg(Deger2Suffix));
      Deger2Rect =  QRectF(outlineRect.x(),
                           outlineRect.y() + PenWidth,
                           outlineRect.width() ,
                           this->fontMetrics().height() + 5);
      BorderPen.setColor(Qt::red);
      myPainter.setPen(BorderPen);
      myPainter.setFont(NameFont);
      myPainter.drawText(Deger2Rect,Qt::AlignCenter,this->objectName());
      myPainter.setClipping(false);
      myPainter.end();
    }
    
    void cedaTank::setValue(int value)
    {
        if (w_value != value){
            if (value <= MaxValue){
                w_value = value;
                emit valuechanged(w_value);
            } else {
                value = MaxValue;
                emit valuechanged(w_value);
            }
    
        }
        repaint();
    }
    
    void cedaTank::Calculate_inlineRect()
    {
    
        qreal carpan,theYOffset,Yukseklik,Genislik;
        carpan = qreal(w_value - MinValue) / qreal(MaxValue - MinValue);
        theYOffset = outlineRect.y() + (outlineRect.height() - (carpan * outlineRect.height())) + qreal(PenWidth/2);
        Genislik = outlineRect.width() - qreal(PenWidth);
        Yukseklik = (outlineRect.height() - (carpan * outlineRect.height()));
    
        inlineRect =  QRectF(outlineRect.x() , outlineRect.y() ,outlineRect.width(),Yukseklik );
    
    //    qDebug() << "outlineRect.x() :" << outlineRect.x() << "outlineRect.y() :" << outlineRect.y() << "outlineRect.width() :" << outlineRect.width() << "outlineRect.height() :" << outlineRect.height();
    //    qDebug() << "inlineRect.x() :" << inlineRect.x() << "inlineRect.y() :" << inlineRect.y() << "inlineRect.width() :" << inlineRect.width() << "inlineRect.height() :" << inlineRect.height();
    
    }
    
    void cedaTank::Calculate_outlineRect()
    {
        outlineRect = QRectF(Padding,Padding,this->width() - (Padding * 2 ) , this->height()- (Padding * 2 ));
        Deger1Rect = QRectF(outlineRect.x(),
                            outlineRect.y() + (outlineRect.height() - (outlineRect.height() /4)),
                            outlineRect.width() ,
                            this->fontMetrics().height() + 5);
        Deger2Rect = QRectF(outlineRect.x(),
                            outlineRect.y() + (outlineRect.height() /4),
                            outlineRect.width() ,
                            this->fontMetrics().height() + 5);
    }
    
    
    

    0_1511188553500_da3b8d24-14cf-4c55-b39f-e9925f214e45-image.png

    0_1511188570655_85848222-0c16-4804-9a94-56721bfbdc87-image.png


Log in to reply
 

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