首页 > 解决方案 > Qt 中的自定义小部件,如 QFrame

问题描述

我在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吗?我可以进一步改进它吗?

标签: c++qtwidgetqframe

解决方案


您无需担心小部件会在小部件边框之外绘制。控件绘画会自动被其父级裁剪,因此 Qt 会为您处理。

我相信您想要的是在您的垂直布局中添加一个空的 QWidget。该小部件将用作子类想要添加的任何内容的容器小部件。您可以将该小部件公开给调用者,以便他们可以在其上放置自己的布局(并且这些布局将包含任何所需布局中的任何子小部件),或者您可以添加一个新方法——比如“setContainerLayout”——其中调用者可以构建布局并将其应用于容器小部件。

当您将容器小部件放入内部布局时,您可能希望尝试使用布局边距以将容器保持在边框内。


推荐阅读