简体   繁体   中英

Customized Widget like QFrame in Qt

I have written my own class in Qt creator ( C++ ). I want to achieve something similar to the picture given below (see the Label "Options" at the top left of the border ) (Even if well-known classes exist, you can mention those classes name but I still want to try out my custom class to learn more about Qt):

在此处输入图片说明

I have achieved the same thing by writing my own class:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QFrame>
#include <QLabel>

class Widget: public QFrame {
Q_OBJECT

public:
    void resizeEvent(QResizeEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

public:
    Widget(QWidget *parent = nullptr);
    ~Widget(void) override;

private:
    QLabel *label_ = nullptr;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"

#include <QDebug>
#include <QHBoxLayout>
#include <QResizeEvent>

#include <QPainter>
#include <QPaintEvent>

#include <QString>

Widget::Widget(QWidget *parent): QFrame(parent)
{
    qDebug() << "Creating Widget";

    label_ = new QLabel;
    label_->setText(tr("Size: 0"));

    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->addStretch(1);
    hlayout->addWidget(label_);
    hlayout->addStretch(1);

    QHBoxLayout *vlayout = new QHBoxLayout;
    vlayout->addStretch(1);
    vlayout->addLayout(hlayout);
    vlayout->addStretch(1);

    setLayout(vlayout);
    setFrameStyle(2);
}

Widget::~Widget(void)
{

}

void Widget::resizeEvent(QResizeEvent *event)
{
    QString text = QString("Size: %1 . %2").arg(event->size().width()).arg(event->size().height());
    qDebug() << "Resize Event: Old: " << event->oldSize() << " New: " << event->size() << " Text: " << text;
    label_->setText(text);
}

void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    qDebug() << "Paint Evemt";

    QPainter painter(this);
    painter.setPen(QColor("Red"));
//    painter.setBrush(QColor("Red"));
    int width = size().width();
    int height = size().height();

    double factor = 1.0 / 10.0;
    QLine third = QLine(int(width * (1 - factor)), int(height * factor), int(width * (1 - factor)), int(height * (1 - factor)));

    QString text("Hello Sir");
    QRect textRect = QFontMetrics(painter.font()).boundingRect(text);

    qDebug() << textRect;

    painter.drawLine(int(width * factor) + textRect.width(), int(height * factor), int(width * (1 - factor)), int(height * factor));
    painter.drawLine(int(width * factor), int(height * factor), int(width * (factor)), int(height * (1 - factor)));
    painter.drawLine(third);
    painter.drawLine(int(width * factor), int(height * (1 - factor)), int(width * (1 - factor)), int(height * (1 - factor)));

    painter.drawText(QPoint(int(width * factor), int(height * factor + textRect.height() / 2)), text);
}

My widget is shown below (Please ignore the centered QLabel , it is used for debugging and learning purposes):

在此处输入图片说明

I will define functions like setHeader(QString) to set the text on the top-left corner of the border.

Now, I have to extend my class to have following provisions:

  1. I don't want that anything draws on or beyond my border and it's header. This class of mine will be used later to add many widgets inside it (will be subclassed). How to achieve this? How to stop or restrict any painting or drawing of widgets that will be contained inside my custom widget?

  2. I want to verify my implementation that I have achieved so far. Am I using standard methods of Qt ? Can I further improve it?

You don't need to worry about widgets painting outside your widget's border. Widget painting is automatically clipped by its parent, so Qt handles that for you.

What I believe you want is to add an empty QWidget into your vertical layout. That widget will serve as the container widget for anything that subclasses want to add. You can either expose that widget to callers so that they can place their own layouts on it (and those layouts will contain any child widgets in any layout desired), or you can add a new method--say "setContainerLayout"--where the caller can build a layout and apply it to the container widget.

When you place the container widget into your internal layout, you will probably want to experiment with the layout margins to keep the container within your border.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM