Qt - 如何自动生成变量名称?

时间:2017-02-15 09:48:46

标签: c++ qt

在我的程序中,我想将2个新的QLineEdit添加到gridLayout,但仅在必要时添加。 因此,如果满足要求,我将添加一个名为lineEdit1的QLineEdit和另一个名为lineEdit2的QLineEdit。 但在寻找解决方案时,我看到有人说这是不可能的,或者使用数组。

所以我的问题是如何在Qt设计师中完成。因为当您在Qt设计器中添加2个相同的新项目时,例如标签,它们将被命名为:labellabel_2。如果您生成ui _ **。h,则会创建QLabel* labelQLabel* label_2

他们是如何做到的?

3 个答案:

答案 0 :(得分:3)

Qt设计器使用类似XML的文件,称为用户界面(UI)文件来表示表单的布局。这些文件以层次结构的方式描述了结构。

在构建过程中,.ui文件由名为User Interface Compiler(uic或uic.exe)的工具使用,为您生成源代码。源代码放在头文件中,该头文件包含在与UI文件相关的类中。

当然,这也可以手动完成。这种方法与您想要实现的目标之间的区别在于决策时间。上述过程使用编译时中已知的信息。所以程序员在编写源代码时就知道有这样的变量,他可以使用他们的名字来访问它们。

您似乎想要在运行时做出决定。这可能是人们建议使用阵列的原因。问题是编译器无法知道您想要多少个对象。因此,您需要某种动态数据结构,将指针存储到您在运行时创建的对象,只是因为您没有用于存储指针的变量。

请注意,您不一定需要持久指向该对象的指针,因为Qt(使用得当)会为您处理内存管理,因此一种可能的解决方案是使用局部变量进行临时使用并将对象添加到网格。假设有一个名为gridLayout的空QGridLayout,您可以执行以下操作:

bool cond1;
bool cond2;
int row = 0;
int column = 0;

/* set cond1 and cond2 based on your decision logic */

if(cond1)
{
    QLineEdit *lineEdit = new QLineEdit("Text for LineEdit 1", this);
    gridLayout->addWidget(lineEdit, row, column);
    row++;
    column++;
}

if(cond2)
{
    QLineEdit *lineEdit = new QLineEdit("Text for LineEdit 2", this);
    gridLayout->addWidget(lineEdit, row, column);
    row++;
    column++;
}

另一个常见的解决方案是静态添加所有可能的窗口小部件(虽然这并非总是可行),并且只能动态切换其可见性,如下所示:

bool cond1;
bool cond2;
lineEdit1->setVisible(cond1); /* Alternatevily show(), hide() */
lineEdit2->setVisible(cond2);

使用这种方法,您甚至可以使用Qt Designer,并且如果要切换的小部件数量很少,则可以使用它。缺点是它不能很好地扩展。

答案 1 :(得分:0)

您是否希望在运行时从代码中动态添加这两个元素?或者您想通过QDesigner将它们添加到UI表单中,默认隐藏然后根据其他规则显示?

以下是一个示例,说明如何隐藏\显示以UI形式预定义的特定元素:

// widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

// widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    bool requirement = true;

    // hide elements based on flag
    if(!requirement)
    {
        ui->lineEdit1->hide();
        ui->lineEdit2->hide();
    }
    else
    {
        ui->lineEdit1->show();
        ui->lineEdit2->show();
    }
}

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

// main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

// widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QLineEdit" name="lineEdit1"/>
   </item>
   <item row="0" column="1">
    <widget class="QLineEdit" name="lineEdit2"/>
   </item>
  </layout>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

答案 2 :(得分:0)

如果你想在运行时动态添加这些对象,那么你需要使用一个对象数组,以便能够在初始化之后及时处理你的对象。

这是一个简单的例子。我刚刚将UI格式的QGridLayout添加为我的按钮的占位符,然后用动态分配的新对象填充它,将它们添加到数组&m;然后在&lt; switchVisibility&#39;中使用此数组。槽。

// widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class QPushButton;

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void switchVisibility();

private:
    bool mFlag;
    QList<QPushButton*> mButtons;

    Ui::Widget *ui;
};

#endif // WIDGET_H

// widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QPushButton>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    mFlag(true),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    int count = 0;

    for(int row=0; row < 4; row++) {
        for(int column = 0; column < 4; column++ ) {
            // count button, for label
            count++;

            // create button
            QPushButton* button = new QPushButton(this);
            button->setText(QString::number(count));

            // add this button to grid layout in our gui
            ui->mLayoutButtons->addWidget(button, row, column);

            // put a pointer to button object into our array (QList)
            // if we need to do something with it later
            mButtons.append(button);
        }
    }

    // connect hide button click to slot
    QObject::connect(ui->mButtonHide, &QPushButton::clicked, this, &Widget::switchVisibility);
}

Widget::~Widget()
{
}

void Widget::switchVisibility()
{
    // flip bool value
    mFlag = !mFlag;

    foreach (QPushButton* button, mButtons) {
        button->setVisible(mFlag);
    }
}

// widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <layout class="QGridLayout" name="mLayoutButtons"/>
   </item>
   <item>
    <widget class="QPushButton" name="mButtonHide">
     <property name="text">
      <string>Click me</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>