Настраиваемый виджет типа QFrame в Qt - PullRequest
0 голосов
/ 26 июня 2019

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

enter image description here

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

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, он используется для целей отладки и обучения):

enter image description here

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

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

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

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

1 Ответ

0 голосов
/ 27 июня 2019

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

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

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

...