制作一个自定义弹出窗口,根据内容更改高度,并在需要时添加滚动条

问题描述 投票:0回答:1

下面是我用油漆制作的两个模型,以展示我想要制作的东西。我想构建符合以下标准的版本:

  • 水平尺寸应固定。
  • 垂直尺寸应最小,但可以根据需要扩大。
  • 如果弹出窗口的说明(白色部分)增大到不再适合屏幕的尺寸(有一些边距),则应该出现滚动条。
  • 标题(黄色部分)的大小不应改变。
  • 描述可以是任何内容,有时是文本,有时是另一个小部件,有时是图像。

这是我到目前为止所做的:

  • 我将白色部分设置为 QWidget,以便更轻松地将子小部件替换为另一个子小部件。
  • 我通过为主框架填充来固定水平宽度。

我不知道从这里该去哪里。我不想使用 QMessageBox,因为我想完全控制设计并了解一切是如何工作的。 这是 .ui 文件:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Popup</class>
 <widget class="QFrame" name="Popup">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>480</width>
    <height>800</height>
   </rect>
  </property>
  <property name="maximumSize">
   <size>
    <width>480</width>
    <height>800</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Frame</string>
  </property>
  <property name="windowOpacity">
   <double>0.000000000000000</double>
  </property>
  <property name="styleSheet">
   <string notr="true">background-color: rgba(0, 0, 0, 0.5);</string>
  </property>
  <property name="frameShape">
   <enum>QFrame::NoFrame</enum>
  </property>
  <property name="frameShadow">
   <enum>QFrame::Plain</enum>
  </property>
  <property name="lineWidth">
   <number>0</number>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0">
   <property name="leftMargin">
    <number>72</number>
   </property>
   <property name="rightMargin">
    <number>72</number>
   </property>
   <item>
    <spacer name="verticalSpacer">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>0</width>
       <height>254</height>
      </size>
     </property>
    </spacer>
   </item>
   <item>
    <widget class="QWidget" name="widget" native="true">
     <property name="enabled">
      <bool>true</bool>
     </property>
     <property name="minimumSize">
      <size>
       <width>336</width>
       <height>80</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>336</width>
       <height>800</height>
      </size>
     </property>
     <property name="styleSheet">
      <string notr="true">.QWidget{
    border-radius: 10px;
    background-color: rgba(255, 255, 255,1);
}</string>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout">
      <property name="spacing">
       <number>0</number>
      </property>
      <property name="sizeConstraint">
       <enum>QLayout::SetMinAndMaxSize</enum>
      </property>
      <property name="leftMargin">
       <number>0</number>
      </property>
      <property name="topMargin">
       <number>0</number>
      </property>
      <property name="rightMargin">
       <number>0</number>
      </property>
      <property name="bottomMargin">
       <number>0</number>
      </property>
      <item>
       <widget class="QLabel" name="lblTitle">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Ignored" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>80</height>
         </size>
        </property>
        <property name="font">
         <font>
          <family>Sans Serif</family>
          <pointsize>18</pointsize>
          <bold>true</bold>
         </font>
        </property>
        <property name="styleSheet">
         <string notr="true">background-color: #FFBF00;
padding:10px;
border-top-right-radius: 10px;
border-top-left-radius: 10px;</string>
        </property>
        <property name="text">
         <string>Lorem Ipsum</string>
        </property>
        <property name="alignment">
         <set>Qt::AlignCenter</set>
        </property>
        <property name="wordWrap">
         <bool>true</bool>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QWidget" name="widget_2" native="true">
        <property name="styleSheet">
         <string notr="true">background-color:white</string>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_3">
         <item>
          <widget class="QTextEdit" name="teDescription">
           <property name="verticalScrollBarPolicy">
            <enum>Qt::ScrollBarAsNeeded</enum>
           </property>
           <property name="horizontalScrollBarPolicy">
            <enum>Qt::ScrollBarAlwaysOff</enum>
           </property>
           <property name="sizeAdjustPolicy">
            <enum>QAbstractScrollArea::AdjustToContents</enum>
           </property>
           <property name="readOnly">
            <bool>true</bool>
           </property>
           <property name="html">
            <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
           </property>
           <property name="textInteractionFlags">
            <set>Qt::NoTextInteraction</set>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item>
    <spacer name="verticalSpacer_2">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>0</width>
       <height>254</height>
      </size>
     </property>
    </spacer>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

弹出类: 标题:

#ifndef POPUP_H
#define POPUP_H

#include <QFrame>

namespace Ui {
class Popup;
}

class Popup : public QFrame
{
    Q_OBJECT

public:
    explicit Popup(QWidget *parent = nullptr);
    void setDescription(const QString &text);
    ~Popup();

private:
    Ui::Popup *ui;
};

#endif // POPUP_H

来源:

#include "popup.h"
#include "ui_popup.h"

Popup::Popup(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::Popup)
{
    ui->setupUi(this);
    ui->teDescription->setFrameStyle(QFrame::NoFrame);
    ui->teDescription->setAlignment(Qt::AlignCenter);
}

void Popup::setDescription(const QString &text)
{
    ui->teDescription->setText(text);
}

Popup::~Popup()
{
    delete ui;
}

主要.cpp:

#include "mainwindow.h"

#include <QApplication>

#include "popup.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    Popup pop;
    pop.setDescription("This is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\nThis is a \nTest\nto\nsee\n\nhow\nwell it works\n");
    // w.show();
    pop.show();
    w.setGeometry(0,0,480, 800);
    return a.exec();
}

主窗口是默认且未使用的。

这是目前的样子

html c++ css qt qt5
1个回答
0
投票

我理解你的问题的方式,你应该能够进行一次尺寸计算;然而,在我看来,如果每当文本编辑内容发生变化时重新计算足够的大小,它会更干净/灵活。

先决条件:

  • 从任何预定义文本中清除
    ui->teDescription

    似乎从
    .ui
    文件中设置了空格/制表符/换行符(至少,这发生在我身上,但我还没有彻底检查你的文件)。
  • 定义
    ui->teDescription
    的最小/最大高度。
    2 个变量
    minHeight
    maxHeight
    将驱动
    ui->teDescription
    如何缩小/增长;当然,您可以更改它们的定义以使用您已经为
    Popup
    的其他小部件定义的最小/最大尺寸。
  • 如果您打算将
    ui->teDescription
    设置为非只读,请取消注释我标记的代码行。这将使编辑在键入第一个字符时采用最小大小。
  • 将构造函数更改为下面的代码。
    根据我写的旧答案(并针对您的用例进行了简化),任何时候修改文本,都会触发高度计算。
    sizeCalculation
    lambda 是神奇发生的地方:使用
    ui->teDescription
    (其
    document()
    、其
    contentsMargins()
    (顶部和底部)及其初始
    minimumHeight()
    maximumHeight()
    ),足够的高度是 c。
Popup::Popup(QWidget* parent) :
    QFrame(parent),
    ui(new Ui::Popup),
    sizeEventFilter(new SizeEventFilter(this))
{
    ui->setupUi(this);
    ui->teDescription->setFrameStyle(QFrame::NoFrame);
    ui->teDescription->setAlignment(Qt::AlignCenter);

// Additional code starts here
    QMargins margins = ui->teDescription->contentsMargins();
    qreal verticalmarginSize = margins.top() + margins.bottom();
    int minHeight = ui->teDescription->minimumHeight(),
        maxHeight = ui->teDescription->maximumHeight();

    // To uncomment for nicer behavior when the text edit is not read only.
    //ui->teDescription->setFixedHeight(minHeight); 

    auto sizeCalculation = [this, minHeight, maxHeight, verticalmarginSize]() {
        auto document = ui->teDescription->document();
        int height = document->size().height() + verticalmarginSize;
        height = std::clamp(height, minHeight, maxHeight); // #include <algorithm>

        if (height != ui->teDescription->height()) // Better to avoid resizing when unnecessary.
            ui->teDescription->setFixedHeight(height);
    };
    QObject::connect(ui->teDescription, &QTextEdit::textChanged, sizeCalculation);
}
© www.soinside.com 2019 - 2024. All rights reserved.