在 QFormLayout 中动态创建的 QWidget 没有框架,即使明确要求这样做

Posted

技术标签:

【中文标题】在 QFormLayout 中动态创建的 QWidget 没有框架,即使明确要求这样做【英文标题】:Dynamically created QWidget in QFormLayout does not have frame, even if explicitly asked to do so 【发布时间】:2016-06-15 09:53:05 【问题描述】:

我对这段代码有点问题:

DatasetWidget::DatasetWidget(QWidget *parent) : QWidget(parent),
ui(new Ui::DatasetWidget)

    ui->setupUi(this);

    // cut non-ui related stuff here ...

    // Add widgets
    for(int loop=0;loop<theAmountOfItemsWeAdd;++loop)
    
        QLabel * ql=new QLabel("Caption");
        QLineEdit * qle=new QLineEdit(this);
        qle->setSizePolicy(QSizePolicy::Policy::Expanding,QSizePolicy::Policy::Fixed);
        ui->formDisp->addRow(ql,qle); // ui->formDisp is of type QFormLayout*
    

// more non-UI related code

我正在创建一个 QLineEdit 小部件并将其添加到 QFormLayout,“formDisp”。由于一些我无法弄清楚的奇怪原因,创建的 QLineEdit 没有任何框架并且 setFrame 没有启用它。

我还在此处附加了 .ui 文件的相关部分:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>DatasetWidget</class>
 <widget class="QWidget" name="DatasetWidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>723</width>
    <height>591</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string>Datensatz</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
      <widget class="QLabel" name="lblCaptionDatensatz">
       <property name="text">
        <string>Datensatz:</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="lblDatensatz">
       <property name="font">
        <font>
         <weight>75</weight>
         <bold>true</bold>
         <underline>true</underline>
        </font>
       </property>
       <property name="text">
        <string>C-XXXX-XXX</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLineEdit" name="leDescriptor">
       <property name="sizePolicy">
        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
         <horstretch>0</horstretch>
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
       <property name="toolTip">
        <string extracomment="ServiceTag"/>
       </property>
       <property name="maxLength">
        <number>7</number>
       </property>
      </widget>
     </item>
     <item>
      <spacer name="horizontalSpacer">
       <property name="orientation">
        <enum>Qt::Horizontal</enum>
       </property>
       <property name="sizeHint" stdset="0">
        <size>
         <width>40</width>
         <height>20</height>
        </size>
       </property>
      </spacer>
     </item>
     <item>
      <widget class="QPushButton" name="cmdDelete">
       <property name="text">
        <string/>
       </property>
       <property name="icon">
        <iconset resource="hawams.qrc">
         <normaloff>:/icons/res/trash-3x.png</normaloff>:/icons/res/trash-    3x.png</iconset>
       </property>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <layout class="QFormLayout" name="formDisp"/>
   </item>
   <item>
    <widget class="Line" name="line">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
<connections/>
</ui>

由于 QtCreator 中添加的小部件看起来与它们应有的外观完全相同,我想我的代码一定有问题。

更新: 问题已解决:在 QListView 中使用了环绕 QWidget,它取代了旧的固定大小版本的小部件。在用项目填充 QListView 的代码中,有一个硬编码的大小提示,它迫使 Qt 调整 QWidget 的新(更大)版本的大小并垂直“挤压”它。 结论:当您将 QWidget 派生嵌入到错误的旧代码中并调整其大小时,没有足够的空间来显示 QWidget 布局内的所有项目,事情就会变得一团糟。

【问题讨论】:

请显示更多您的代码,因为这 4 行还不够 由于我不知道代码的哪些部分是相关的,所以我附加了一些上下文信息。 可能是一个愚蠢的问题,但是......你确定 QLineEdit 没有框架吗?在我所在的系统上几乎察觉不到差异。 你使用样式表吗? @G.M.我绝对确定 - QLineEdit 在白色背景上(我的系统上 QListWidget 内的 QWidget 的默认背景颜色,我们正在谈论的小部件就是这种情况)。它绝对没有框架。 【参考方案1】:

setFrame(true) 是无操作的,因为框架是默认设置的。

唉,我无法重现 - 以下两个行编辑看起来相同,除了它们的大小,并且它们的最小大小设置为不同的值,第二个大于第一个。 QFormLayout 不强制固定行高!

// https://github.com/KubaO/***n/tree/master/questions/lineedit-frame-37831979
#include <QtWidgets>
#include <QtUiTools>

const char ui[] = R"EOF(
  <ui version="4.0">
   <class>DatasetWidget</class>
   <widget class="QWidget" name="DatasetWidget">
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QLabel" name="lblCaptionDatensatz">
       <property name="text">
        <string>Datensatz:</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="lblDatensatz">
       <property name="text">
        <string>C-XXXX-XXX</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLineEdit" name="leDescriptor">
       <property name="maxLength">
        <number>7</number>
       </property>
      </widget>
     </item>
     <item>
      <layout class="QFormLayout" name="formDisp"></layout>
     </item>
    </layout>
   </widget>
  <connections/>
  </ui>)EOF";

int main(int argc, char ** argv) 
   QApplication appargc, argv;
   QBuffer buf;
   buf.setData(ui, sizeof(ui));
   auto w = QUiLoader().load(&buf);
   auto & layout = *w->findChild<QFormLayout*>("formDisp");
   QLineEdit edit1, edit2;
   layout.addRow("Edit1", &edit1);
   layout.addRow("Edit2", &edit2);
   edit1.setMinimumHeight(50);
   edit2.setMinimumHeight(100);
   w->show();
   return app.exec();

【讨论】:

您好,感谢您的回复。是的,setFrame(true) 是无操作的,但如屏幕截图所示,我的代码生成的 QLineEdits 没有框架。我期望的是带有可见框架的 QLineEdit,例如屏幕截图顶部的 QLineEdit,上面写着“123ABCD”,并且不是由我自己的代码生成的。也许这可以澄清我的问题。【参考方案2】:

问题解决了。添加到 QFormLayout 的第一个 Widget 是一个 QLabel。然后将行高设置为标签的高度。以下所有小部件都被塞入“太窄”的行中,如果 Qt 试图在它们周围画一个框架,文本行将不再适合它们 - 所以没有框架。解决方案:例如setMinimumHeight(32) 在添加到 QFormLayout 的第一个元素上。

还有第二个错误。整个 QWidget 是数据集的图形表示,在主应用程序中,此小部件的许多实例在 QListView 中用于显示数据库查询的结果。在使用动态创建的 QWidget 之前,我使用了一个固定大小的静态小部件。这个大小在填充 QListView 的代码中用作 sizeHint,我完全忘记了这一点。删除应用程序主窗口代码中错误的 sizeHint 后,也不再需要 setMinimumHeight(someInt)

【讨论】:

表单布局中没有固定的行高。它适应每个小部件的要求。你还在做其他错误的事情。请参阅我的答案的编辑。您使用的确切平台和样式是什么?也许您正在使用一种损坏的样式,它没有为小部件提供正确的 sizeHints 或最小尺寸。 感谢您的承诺。是的,事实证明还有其他问题。我在 Linux 桌面上,当您在 QtCreator 中从头开始创建新的 Qt 项目时,我使用 Qt 应用程序使用的默认样式,我认为在 Linux 中这是 Plastique 样式,但我不确定。但是,我确实犯了第二个错误,我会在一分钟后将其附加到我的答案中。 那么你的问题完全不够。请修改它以清楚地展示您遇到的问题,或将其删除。如果不像我那样从最小的测试用例开始,你会浪费很多时间。我猜如果他们的提问者愿意遵循他们的问题应该遵守并在How to Ask 中详细说明的要求,那么 50% 以上的 SO 问题将是不必要的。我超过 10% 的回答只是简单地强调了“为我工作”的问题的不足之处。这不好。 @KubaOber 对不起,这是我第一个关于 SO 的问题。开发一个会出现相同问题的最小测试用例并不容易 - 我不知道小部件的实际大小与它是否绘制框架之间存在联系这一事实,我认为也在调整有一个完全工作的测试用例不会指向我。但我感谢您的承诺,查看 uic 生成的代码将我引向了正确的方向。 “开发一个会出现相同问题的最小测试用例并不容易”这就是重点:只要你不能问,你就不应该问,因为你不知道不知道你在寻求什么问题的帮助!当你了解问题的根源时,你手头可能也有解决方案。只有你不这样做,你才问。这与询问 SO 无关,这就是您有效解决问题的方式。如果您没有测试用例,您自己甚至都不知道问题是什么!然后它会显示为“嘿,发生了这样的事情,不知道有什么,帮助”。

以上是关于在 QFormLayout 中动态创建的 QWidget 没有框架,即使明确要求这样做的主要内容,如果未能解决你的问题,请参考以下文章

QFormLayout的PyQt5顶行没有响应鼠标点击

3.1.3 QFormLayout表单布局(窗体布局)

控制PyQt QFormLayout中的Widget放置

如何为 QFormLayout 的第一列设置最小宽度?

我不能 clicked.connect() QFormLayout 上的 QPushButton [重复]

QHBoxLayout QFormLayout 遍历子部件,查找QLineEdit控件