繁体   English   中英

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

[英]Dynamically resizing two QLabel implementations

我试图在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的屏幕截图,可让您大致了解我要完成的工作:

窗口截图

欢迎提供有关代码的所有注释。

谢谢你的帮助,

里卡多

您好,我尝试通过黑客解决调整大小的问题。 在启动计时器调整文本大小之前,只需将其字体减小为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);
}

您认为效果可以接受吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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