久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

如何在 Qt 中制作可展開/可折疊的部分小部件

How to make an expandable/collapsable section widget in Qt(如何在 Qt 中制作可展開/可折疊的部分小部件)
本文介紹了如何在 Qt 中制作可展開/可折疊的部分小部件的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我想在 Qt 中創建一個具有以下功能的自定義小部件:

I would like to create a custom widget in Qt with the following features:

  • 這是一個容器
  • 它可以填充任何 Qt 布局
  • 它可以在任何 Qt 布局中
  • 按鈕允許垂直折疊/折疊內容,因此只有按鈕可見,所有包含的布局都不可見.
  • 上一個按鈕允許將其再次展開/展開到布局內容的大小.
  • 展開/折疊基于尺寸(不是顯示/隱藏)以允許動畫.
  • 可在 QDesigner 中使用

為了提供一個想法,這是一個類似小部件(不是 Qt)的圖像:

To provide an idea, here is an image of a similar widget (not Qt):

我已經有一個框架可以正常工作并在 QDesigner 中公開.我現在需要讓它展開/折疊,這看起來并不那么簡單.

I already have a frame that work correctly and is exposed in QDesigner. I need now to make it to extend/collapse, which does not seem so simple.

我嘗試使用 resize()、sizePolicy()、sizeHint() 但這不起作用:當框架折疊時,我得到以下值:

I tried to play with resize(), sizePolicy(), sizeHint() but that does not work: When the frame is collapsed I got following values:

sizeHint: (500,20)
size    : (500,20)
closestAcceptableSize: (518,150)
Painted size: (518, 150)

QLayout::closestAcceptableSize 不是小部件的一部分,因此我無法更改它.

QLayout::closestAcceptableSize is not part of the widget so I cannot change it.

任何提示或/和代碼片段來實現這一點?

這里有一個簡單的例子.除必要外,我刪除了所有內容.

EDITED: Here a simple example. I removed all except necessary.

main.cpp 示例

main.cpp example

#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>

#include "section.hpp"


using namespace myWidgets;
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


    // Create the main Window
    QWidget window;
    window.resize(500,500);
    window.setStyleSheet("QPushButton:{background-color:rgba(128,128,128,192);}");

    // Create the main window layout
    QVBoxLayout topLayout(&window);
    QWidget *w1 = new QWidget();
    w1->setStyleSheet("background-color:rgba(128,128,128,192);");
    topLayout.addWidget(w1);

    Section section(&window);
    topLayout.addWidget(&section);

    QVBoxLayout inLayout(&section);
    QPushButton *button = new QPushButton();
    button->setMinimumHeight(100);
    inLayout.addWidget(button);

    QWidget *w2 = new QWidget();
    w2->setStyleSheet("background-color:rgba(128,128,128,192);");
    topLayout.addWidget(w2);



    window.show();

    return a.exec();
}

Section.hpp

Section.hpp

#ifndef SECTION_HPP
#define SECTION_HPP

#include <QPushButton> //for the expand/collapse button
#include <QtDesigner/QDesignerExportWidget>
#include <QLayout>
#include <QPainter>
#include <QPaintEvent>
#include <QDebug>


// Compatibility for noexcept, not supported in vsc++
#ifdef _MSC_VER
#define noexcept throw()
#endif

#if defined SECTION_BUILD
    #define SECTION_BUILD_DLL_SPEC Q_DECL_EXPORT
#elif defined SECTION_EXEC
    #define SECTION_BUILD_DLL_SPEC
#else
    #define SECTION_BUILD_DLL_SPEC Q_DECL_IMPORT
#endif

namespace myWidgets
{

class SECTION_BUILD_DLL_SPEC Section : public QWidget
{
    Q_OBJECT

    Q_PROPERTY( bool is_expanded MEMBER isExpanded)

public:
    // Constructor, standard
    explicit Section( QWidget *parent=0 ): QWidget(parent),
        expandButton(this)
    {
        expandButton.resize(20,20);
        expandButton.move(0,0);
        expandButton.connect(&expandButton, &QPushButton::clicked,
                             this, &Section::expandCollapseEvent);

        QMargins m= contentsMargins();
        m.setTop(m.top()+25);
        setContentsMargins(m);
        //setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Minimum);

    }

    virtual void expand( bool expanding ) noexcept
    {
        resize(sizeHint());
        isExpanded = expanding;
        updateGeometry();

qDebug() << (isExpanded? "expanded":"collapsed") << sizeHint() << QWidget::size() <<
            parentWidget()->layout()->closestAcceptableSize(this, size());
    }

    virtual QSize sizeHint() const noexcept override
    {
        if (isExpanded) return QSize(layout()->contentsRect().width(),
                                     layout()->contentsRect().height());
        else return QSize(layout()->contentsRect().width(), 20);
    }

    // Implement custom appearance
    virtual void paintEvent(QPaintEvent *e) noexcept override
    {
        (void) e; //TODO: remove
        QPainter p(this);
        p.setClipRect(e->rect());
        p.setRenderHint(QPainter::Antialiasing );
        p.fillRect(e->rect(), QColor(0,0,255,128));
    }

protected:

    // on click of the expandButton, collapse/expand this widget
    virtual void expandCollapseEvent() noexcept
    {
        expand(!isExpanded);
    }


    bool isExpanded = true; //whenever the section is collapsed(false) or expanded(true)
    QPushButton expandButton; //the expanding/collapsing button
};

}


#endif // SECTION_HPP

推薦答案

我偶然發現了同樣的問題,并通過將可折疊小部件實現為 QScrollArea 來解決它,其最大高度由 動畫>QPropertyAnimation.

I stumbled upon the same problem and solved it by implementing the collapsible widget as a QScrollArea whose maximum height is animated by a QPropertyAnimation.

但因為我不使用 QDesigner,所以我不能告訴你它是否在那里工作.

But since I don't use QDesigner, I can't tell you if it works there.

我仍然有一個問題:可折疊小部件不僅可以向底部方向擴展,還可以向頂部和底部擴展.如果尚未達到其最小高度,這可能會導致位于其上方的小部件縮小.但這與我們必須自己構建這個東西的事實相比確實是一個細節......

I still have one problem: Instead of only expanding towards the bottom direction, the collapsible widget can expand towards the top and bottom. This can cause widgets located above it to shrink if they haven't reached their minimum height, yet. But this is really a detail compared to the fact that we have to build this thing ourselves…

Spoiler.h

#include <QFrame>
#include <QGridLayout>
#include <QParallelAnimationGroup>
#include <QScrollArea>
#include <QToolButton>
#include <QWidget>

class Spoiler : public QWidget {
    Q_OBJECT
private:
    QGridLayout mainLayout;
    QToolButton toggleButton;
    QFrame headerLine;
    QParallelAnimationGroup toggleAnimation;
    QScrollArea contentArea;
    int animationDuration{300};
public:
    explicit Spoiler(const QString & title = "", const int animationDuration = 300, QWidget *parent = 0);
    void setContentLayout(QLayout & contentLayout);
};

Spoiler.cpp

#include <QPropertyAnimation>

#include "Spoiler.h"

Spoiler::Spoiler(const QString & title, const int animationDuration, QWidget *parent) : QWidget(parent), animationDuration(animationDuration) {
    toggleButton.setStyleSheet("QToolButton { border: none; }");
    toggleButton.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toggleButton.setArrowType(Qt::ArrowType::RightArrow);
    toggleButton.setText(title);
    toggleButton.setCheckable(true);
    toggleButton.setChecked(false);

    headerLine.setFrameShape(QFrame::HLine);
    headerLine.setFrameShadow(QFrame::Sunken);
    headerLine.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

    contentArea.setStyleSheet("QScrollArea { background-color: white; border: none; }");
    contentArea.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    // start out collapsed
    contentArea.setMaximumHeight(0);
    contentArea.setMinimumHeight(0);
    // let the entire widget grow and shrink with its content
    toggleAnimation.addAnimation(new QPropertyAnimation(this, "minimumHeight"));
    toggleAnimation.addAnimation(new QPropertyAnimation(this, "maximumHeight"));
    toggleAnimation.addAnimation(new QPropertyAnimation(&contentArea, "maximumHeight"));
    // don't waste space
    mainLayout.setVerticalSpacing(0);
    mainLayout.setContentsMargins(0, 0, 0, 0);
    int row = 0;
    mainLayout.addWidget(&toggleButton, row, 0, 1, 1, Qt::AlignLeft);
    mainLayout.addWidget(&headerLine, row++, 2, 1, 1);
    mainLayout.addWidget(&contentArea, row, 0, 1, 3);
    setLayout(&mainLayout);
    QObject::connect(&toggleButton, &QToolButton::clicked, [this](const bool checked) {
        toggleButton.setArrowType(checked ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
        toggleAnimation.setDirection(checked ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
        toggleAnimation.start();
    });
}

void Spoiler::setContentLayout(QLayout & contentLayout) {
    delete contentArea.layout();
    contentArea.setLayout(&contentLayout);
    const auto collapsedHeight = sizeHint().height() - contentArea.maximumHeight();
    auto contentHeight = contentLayout.sizeHint().height();
    for (int i = 0; i < toggleAnimation.animationCount() - 1; ++i) {
        QPropertyAnimation * spoilerAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(i));
        spoilerAnimation->setDuration(animationDuration);
        spoilerAnimation->setStartValue(collapsedHeight);
        spoilerAnimation->setEndValue(collapsedHeight + contentHeight);
    }
    QPropertyAnimation * contentAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(toggleAnimation.animationCount() - 1));
    contentAnimation->setDuration(animationDuration);
    contentAnimation->setStartValue(0);
    contentAnimation->setEndValue(contentHeight);
}

如何使用:

…
auto * anyLayout = new QVBoxLayout();
anyLayout->addWidget(…);
…
Spoiler spoiler;
spoiler.setContentLayout(*anyLayout);
…

這篇關于如何在 Qt 中制作可展開/可折疊的部分小部件的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: 国产成人精品一区二 | 亚洲一区二区免费电影 | 国产三区视频在线观看 | 欧美日本韩国一区二区 | 日韩电影一区二区三区 | 国产欧美日韩在线观看 | 欧美精品成人一区二区三区四区 | av中文在线| 亚洲午夜在线 | 特级毛片| 亚洲一区视频 | 午夜私人影院在线观看 | 欧美精品久久一区 | 欧美精品一区三区 | 一区二区三区精品在线视频 | 欧美精品久久久 | jizz亚洲人 | 国产欧美日韩视频 | 成人一级毛片 | 麻豆亚洲| 欧美男人亚洲天堂 | 精品九九久久 | 久草中文在线观看 | 久久亚洲一区二区三区四区 | aaa综合国产 | 91看片免费 | 在线播放国产视频 | 色性av| 日本黄色的视频 | 毛片大全 | 在线观看精品 | 99热.com| 男女污污动态图 | 99国内精品久久久久久久 | 精品久久久久久久久亚洲 | 日日操av | 国产韩国精品一区二区三区 | 欧美一级在线 | 黄色免费三级 | 一二三区av | 99精品国产一区二区青青牛奶 |