动态调整两个QLabel实现的大小

时间:2017-09-19 12:08:09

标签: c++ qt qt5

我正在尝试用Qt和一些文本在Qt中创建一个简单的框架。我做了两个新的标签实现,因为我希望标签动态填充所有可用空间,但是当我调整窗口大小时,大小关闭,如qDebug输出所示,它表示图像标签的大小:

Resized:  244 ,  244 <-- Window first created
Resized:  305 ,  305 <-- Window maximized
Resized:  135 ,  135 <-- Window restored to original size

如您所见,当窗口恢复到原始大小时,图像不会恢复。最后一个大小应该是244,244。

描述两个小部件行为的代码如下:

“widgets.h”:

    /*
 * This file includes many custom widgets.
 */

#ifndef APOCRYPHA_WIDGETS
#define APOCRYPHA_WIDGETS

#include <QWidget>
#include <QLabel>
#include <QTimer>
#include <QPixmap>
#include <QResizeEvent>
#include <QPaintEvent>

class AutoTextLabel : public QLabel {

    Q_OBJECT

public:
    explicit AutoTextLabel(QWidget* parent);
    AutoTextLabel(QWidget* parent, QString text);

protected:
    void resizeEvent(QResizeEvent* event) override;

private:
    QTimer* resizeTimer;

private slots:
    void onResizeEnd();

};

class AutoImageLabel : public QLabel {

    Q_OBJECT

public:
    explicit AutoImageLabel(QWidget* parent);
    AutoImageLabel(QWidget* parent, const QPixmap& pixmap);
    void setFillOrientation(int orientation);
    QSize sizeHint() const override;

public slots:
    void setPixmap(const QPixmap &newPix);
    void resizeEvent(QResizeEvent* event) override;


protected:
//    void paintEvent(QPaintEvent* event) override;

private:
    int fillOrientation;

    int widthForHeight(int h) const;
    int heightForWidth(int w) const override;
    QPixmap scaledPixmap() const;

    QPixmap labelPixmap;

};

#endif //APOCRYPHA_WIDGETS

“widgets.cpp”:

/*
 * This file includes many custom widgets.
 */

#include "widgets.h"
#include <QPainter>
#include <QDebug>


AutoTextLabel::AutoTextLabel(QWidget *parent, QString text) : QLabel(text, parent){

    // Enable antialiasing
    QFont aaFont(font());
    aaFont.setStyleStrategy(QFont::PreferAntialias);
    setFont(aaFont);

    // This timer is used to fire a slot when a window is resized
    resizeTimer = new QTimer();
    resizeTimer->setSingleShot(true);
    connect(resizeTimer, SIGNAL(timeout()), SLOT(onResizeEnd()));

}

AutoTextLabel::AutoTextLabel(QWidget *parent) : AutoTextLabel(parent, "") {}

void AutoTextLabel::resizeEvent(QResizeEvent *event) {
    QWidget::resizeEvent(event);

    // Only fire when 25ms have passed since the last resize.
    resizeTimer->start(25);
}

void AutoTextLabel::onResizeEnd() {

    QFont updatedFont(font());

    // Resize Text
    if (!text().isEmpty()){

        int fontSize = 1;

        updatedFont.setPixelSize(fontSize);
        QRect boundingRectangle;

        // Update bounding rectangle
        if (wordWrap())
            boundingRectangle = QFontMetrics(updatedFont).boundingRect(contentsRect(), Qt::TextWordWrap, text());
        else
            boundingRectangle = QFontMetrics(updatedFont).boundingRect(text());

        while (boundingRectangle.height() <= contentsRect().height()) {
            fontSize++;
            updatedFont.setPixelSize(fontSize);

            // Update bounding rectangle
            if (wordWrap())
                boundingRectangle = QFontMetrics(updatedFont).boundingRect(contentsRect(), Qt::TextWordWrap, text());
            else
                boundingRectangle = QFontMetrics(updatedFont).boundingRect(text());

        }

        updatedFont.setPixelSize(fontSize - 1);
        setFont(updatedFont);

    }

}

/* Auto Image Label */

AutoImageLabel::AutoImageLabel(QWidget *parent, const QPixmap &pixmap) : QLabel(parent) {
    setMinimumSize(1, 1);
    setScaledContents(false);
    setPixmap(pixmap);
}

AutoImageLabel::AutoImageLabel(QWidget *parent) : QLabel(parent) {
    setScaledContents(false);
}

void AutoImageLabel::resizeEvent(QResizeEvent *event) {
    QWidget::resizeEvent(event);

    if(!labelPixmap.isNull())
        QLabel::setPixmap(scaledPixmap());
    qDebug() << "Resized: " << scaledPixmap().width() << ", " << scaledPixmap().height();

}

int AutoImageLabel::widthForHeight(int h) const {
    return labelPixmap.isNull() ? width() : (labelPixmap.width() * h) / labelPixmap.height();
}

int AutoImageLabel::heightForWidth(int w) const {
    return labelPixmap.isNull() ? height() : (labelPixmap.height() * w) / labelPixmap.width();
}

void AutoImageLabel::setFillOrientation(int orientation) {
    this->fillOrientation = orientation;
}

QSize AutoImageLabel::sizeHint() const {

    if (fillOrientation == Qt::Horizontal)
        return QSize(width(), heightForWidth(width()));
    else
        return QSize(widthForHeight(height()), height());
}

QPixmap AutoImageLabel::scaledPixmap() const {
    return labelPixmap.scaled(sizeHint(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}

void AutoImageLabel::setPixmap(const QPixmap &newPix) {
    labelPixmap = newPix;
    QLabel::setPixmap(scaledPixmap());
}

“other_frames.h”:

//
// Created by Riccardo on 18/09/2017.
//

#ifndef APOCRYPHA_OTHER_FRAMES_H
#define APOCRYPHA_OTHER_FRAMES_H

#include <QFrame>
#include <QLabel>
#include <QGridLayout>
#include <QWidget>
#include <QResizeEvent>
#include <QPixmap>
#include <QTimer>
#include "widgets.h"

class ConfirmationFrame : public QFrame {

    Q_OBJECT

public:
    explicit ConfirmationFrame(QWidget* parent);
    ConfirmationFrame(QWidget* parent, const QString& text);

private:

    QGridLayout* layout;

    AutoImageLabel* imageLabel;
    AutoTextLabel* textLabel;

};

#endif //APOCRYPHA_OTHER_FRAMES_H

“other_frames.cpp”:

//
// Created by Riccardo on 18/09/2017.
//

#include "other_frames.h"
#include <QDebug>

ConfirmationFrame::ConfirmationFrame(QWidget* parent, const QString &text) : QFrame(parent) {

    textLabel = new AutoTextLabel(this, text);

    QPixmap pix(":/images/check-tick.png");
    imageLabel = new AutoImageLabel(this, pix);

    textLabel->setAlignment(Qt::AlignCenter);
    imageLabel->setAlignment(Qt::AlignCenter);

    textLabel->setWordWrap(true);

    // Green Background
    setStyleSheet("background-color: rgba(106, 242, 94, 1);");

    layout = new QGridLayout();
    layout->setSpacing(0);
    layout->setContentsMargins(32, 32, 32, 32);
    layout->setRowStretch(0, 1);
    layout->setRowStretch(1, 1);

    layout->addWidget(imageLabel, 0, 1);
    layout->addWidget(textLabel, 1, 1);

    setLayout(layout);

}

ConfirmationFrame::ConfirmationFrame(QWidget *parent) : ConfirmationFrame(parent, "") {
}

“window_main.h”:

#ifndef WINDOW_MAIN_H
#define WINDOW_MAIN_H

#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QGridLayout>
#include <QFrame>
#include <QScreen>

class MainWindow : public QMainWindow {

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);

    QFrame *mainFrame;

    void center(QScreen* screen);
    void autoSetSize(QScreen* screen);

private:
    void createMenu();

    // Components
    QGridLayout *mainLayout;
    QMenuBar *menuBar;
    QMenu *fileMenu;


};

#endif // WINDOW_MAIN

“window_main.cpp”:

#include "window_main.h"


MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    mainFrame = new QFrame();
    mainLayout = new QGridLayout();

    mainLayout->setSpacing(0);
    mainLayout->setContentsMargins(0, 0, 0, 0);

    createMenu();

    mainFrame->setStyleSheet("background-color: red;");
    mainFrame->setLayout(mainLayout);
    setCentralWidget(mainFrame);

}

void MainWindow::createMenu(){
    menuBar = new QMenuBar;
    fileMenu = new QMenu(tr("&File"), this);
    menuBar->addMenu(fileMenu);
    setMenuBar(menuBar);
}

void MainWindow::center(QScreen *screen) {
    QSize size = screen->availableSize();
    int x = size.width() / 2 - width() / 2;
    int y = size.height() / 2 - height() / 2;
    move(x, y);
}

void MainWindow::autoSetSize(QScreen *screen) {
    QSize screenSize = screen->availableSize();
    // TODO Math.round
    setMinimumSize(QSize((int)(screenSize.width() / 1.25), (int)(screenSize.height() / 1.25)));
}

“的main.cpp”:

#include <QApplication>
#include <iostream>
#include <QFile>
#include "quiz/choice.h"
#include "quiz/question.h"
#include "quiz/quizmaker.h"
#include <QSettings>
#include <QStandardPaths>
#include <QDebug>
#include <src/user_interface/other_frames.h>
#include "user_interface/window_main.h"
#include <QScreen>
#include <QFontDatabase>

int main(int argc, char *argv[]) {

    QApplication a(argc, argv);

    // Set Application Parameters
    QCoreApplication::setOrganizationName("Riccardo Fagiolo");
    QCoreApplication::setOrganizationDomain("kopharex.me");
    QCoreApplication::setApplicationName("Apocrypha");

    // Set application font
    const int id = QFontDatabase::addApplicationFont(":/fonts/montserrat/Montserrat-Regular.otf");
    QString family = QFontDatabase::applicationFontFamilies(id).at(0);
    QFont font(family);
    font.setStyleStrategy(QFont::PreferAntialias);
    a.setFont(font);

    // App Settings
    QSettings settings;
    settings.setValue("data_dir", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));

    // Create UI
    auto* window = new MainWindow();

    ConfirmationFrame* cframe = new ConfirmationFrame(window, "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?");
    window->mainFrame->layout()->addWidget(cframe);

    window->autoSetSize(a.primaryScreen());
    //cframe->updateTextLabel();
    window->show();
    window->center(a.primaryScreen());

    // [...] - Nothing related to user interface.

    return a.exec();

}

以下是当前MainWindow和ConfirmationFrame的屏幕截图,让您了解我正在努力实现的目标:

窗口截图

欢迎所有关于代码的评论。

感谢您的帮助,

的Riccardo

1 个答案:

答案 0 :(得分:0)

您好我试图通过黑客修复调整大小问题。 在启动计时器以调整文本大小之前,只需将其字体缩小为1像素字体:

void AutoTextLabel::resizeEvent(QResizeEvent *event) {
    QWidget::resizeEvent(event);

    // set a very small font, then start the timer
    QFont updatedFont(font());
    updatedFont.setPixelSize(1);
    setFont(updatedFont);
    // Only fire when 25ms have passed since the last resize.
    resizeTimer->start(25);
}

您认为效果可以接受吗?