Индивидуальный виджет, такой как QFrame в Qt

Я написал свой собственный класс в Qt creator (C++). Я хочу добиться чего-то похожего на изображение, приведенное ниже (см. Метку «Параметры» в левом верхнем углу border) (даже если существуют известные классы, вы можете указать имя этих классов, но я все еще хочу попробовать свой собственный класс, чтобы узнать больше о Qt):

введите здесь описание изображения

Я добился того же, написав свой собственный класс:

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);
}

Мой виджет показан ниже (пожалуйста, игнорируйте QLabel по центру, он используется для отладки и обучения):

введите здесь описание изображения

Я определю такие функции, как setHeader(QString), чтобы установить text в верхнем левом углу границы.

Теперь я должен расширить свой класс, чтобы иметь следующие положения:

  1. Я не хочу, чтобы что-то рисовало на моей границе или за ее заголовком. Этот мой класс будет использоваться позже для добавления в него множества виджетов (будет подклассом). Как этого добиться? Как остановить или ограничить любое рисование или рисование виджетов, которые будут содержаться внутри моего пользовательского виджета?

  2. Я хочу проверить свою реализацию, которой я добился до сих пор. Использую ли я стандартные методы Qt? Могу ли я еще улучшить его?


person abhiarora    schedule 26.06.2019    source источник


Ответы (1)


Вам не нужно беспокоиться о том, что виджеты будут отображаться за пределами границ вашего виджета. Отрисовка виджета автоматически обрезается его родителем, так что Qt сделает это за вас.

Я считаю, что вы хотите добавить пустой QWidget в свой вертикальный макет. Этот виджет будет служить виджетом-контейнером для всего, что захотят добавить подклассы. Вы можете либо предоставить этот виджет вызывающим объектам, чтобы они могли размещать на нем свои собственные макеты (и эти макеты будут содержать любые дочерние виджеты в любом желаемом макете), либо вы можете добавить новый метод, скажем, "setContainerLayout", где вызывающий объект может создать макет и применить его к виджету-контейнеру.

Когда вы размещаете виджет-контейнер во внутреннем макете, вы, вероятно, захотите поэкспериментировать с полями макета, чтобы контейнер оставался внутри вашей границы.

person goug    schedule 26.06.2019