Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt:Widget方法addButtons()无法按需要工作_C++_Qt_User Interface_Button_Widget - Fatal编程技术网

C++ Qt:Widget方法addButtons()无法按需要工作

C++ Qt:Widget方法addButtons()无法按需要工作,c++,qt,user-interface,button,widget,C++,Qt,User Interface,Button,Widget,我正在Windows7上使用Qt5(初学者)。 在我的应用程序的主窗口中,我想显示并删除一些按钮 widget = new ButtonWidget(ui->frame); // frame is a QScrollArea connect(ui->addBtns, SIGNAL(clicked()), widget, SLOT(addButtons())); connect(ui->deleteBtns, SIGNAL(clicked()), widget, SLOT(

我正在Windows7上使用Qt5(初学者)。
在我的应用程序的主窗口中,我想显示并删除一些按钮

widget = new ButtonWidget(ui->frame); // frame is a QScrollArea
connect(ui->addBtns,    SIGNAL(clicked()), widget, SLOT(addButtons()));
connect(ui->deleteBtns, SIGNAL(clicked()), widget, SLOT(deleteButtons()));
下面是
按钮Widget
类:

ButtonWidget::ButtonWidget(QWidget * parent) : QWidget(parent)
{
   //addButtons();
}

void ButtonWidget::addButtons()
{
   QStringList texts{"1\nok", "2\nok", "3\nok", "4\nok", "5\nok", "6\nok"};
   gridLayout = new QGridLayout;
   for(int i = 0; i < texts.size(); i++)
   {
      QPushButton * button = new QPushButton(texts[i]);
      gridLayout->addWidget(button, i / 5, i % 5);
   }
   setLayout(gridLayout);
}

// I'm not sure this method/function is ok... :(
void ButtonWidget::deleteButtons()
{
    QLayoutItem * child;
    while((child = gridLayout->takeAt(0)) != 0)
    {
        gridLayout->removeWidget(child->widget());
        delete child->widget();
        delete child;
    }
    delete gridLayout;
}
ButtonWidget::ButtonWidget(QWidget*parent):QWidget(parent)
{
//添加按钮();
}
void ButtonWidget::addButtons()
{
QStringList文本{“1\nok”、“2\nok”、“3\nok”、“4\nok”、“5\nok”、“6\nok”};
gridLayout=新的QGridLayout;
对于(int i=0;iaddWidget(按钮,i/5,i%5);
}
setLayout(gridLayout);
}
//我不确定此方法/函数是否正常…:(
void ButtonWidget::deleteButtons()
{
QLayoutItem*子项;
而((child=gridLayout->takeAt(0))!=0)
{
gridLayout->removeWidget(子->widget());
删除子->小部件();
删除儿童;
}
删除网格布局;
}
问题是:当我单击“添加按钮”时,我会显示所有按钮,但它们是缩小的、微小的……:

OTOH…如果我从构造函数中的
addButtons()
call中删除注释(因此从构造函数中调用),结果是ok的:

最后,我有两个问题:
1) 如何修复代码以正确添加这些按钮(当单击
add\u按钮时)?

2)
deleteButtons()
方法可以吗?

首先,我建议您这样做

gridLayout = new QGridLayout(this);
在构造函数中。您不需要删除所有网格,重新创建它并将其设置为一个布局,此时您只需删除其内容(例如使用delete按钮),然后再次填充即可


编辑:沃纳·伊拉斯谟的评论:无需设置布局。它有一个父窗口小部件这一事实意味着它将自己设置好

问题是,如果不修改addButtons(),您将在不知道按钮的位置的情况下替换以前的按钮

另外,尝试为QPushButton指定一个父项:

new QPushButton(texts[i],this);

关于你的第二点:

首先,我建议你这样做

gridLayout = new QGridLayout(this);
在构造函数中。您不需要删除所有网格,重新创建它并将其设置为一个布局,此时您只需删除其内容(例如使用delete按钮),然后再次填充即可


编辑:沃纳·伊拉斯谟的评论:无需设置布局。它有一个父窗口小部件这一事实意味着它将自己设置好

问题是,如果不修改addButtons(),您将在不知道按钮的位置的情况下替换以前的按钮

另外,尝试为QPushButton指定一个父项:

new QPushButton(texts[i],this);
关于第二点:

编辑:

经过更多的测试(没有查看源代码,但怀疑删除按钮必须是安全的,否则事情会变得脆弱),我实现了removeButtons,如下所示:

void ButtonWidget::deleteButtons()
{
    while(myLayout->count())
    {
        delete myLayout->itemAt(0)->widget();
    }
}
这是可行的,它证明了删除一个小部件也会从它的父部件中删除该小部件,以及与父部件关联的布局(通过连接到子部件被删除时的插槽)。上面的代码确认这一点,即count(),它表示布局项的数量,减少到零(并且这些布局项由布局管理)。takeAt(x)从未被调用,也不需要被调用——只需删除小部件(按钮)。哇

原始答案

正如我在另一篇文章中提到的,您只需要删除按钮(它会自动从父按钮中删除)。但是,如果将小部件添加到布局中,则该布局的父级将成为小部件的父级,并创建由布局本身管理的关联QLayoutItem。要删除按钮,最安全的方法是获取所有布局项(所有权由接收者负责),删除与小部件关联的每个项,然后删除每个项。我会尽量从资料来源之外找到相关的参考资料

以下代码有效:

//ButtonWidget.h
#include <QWidget>
#include <QScrollArea>
#include <QHBoxLayout>

class ButtonWidget : public QScrollArea
{
    Q_OBJECT

  public:
    ButtonWidget(QWidget *parent = 0);
    ~ButtonWidget();
    void addButtons();
    void deleteButtons();
  private:
    QHBoxLayout* myLayout;
};

//ButtonWidget.cpp

#include "ButtonWidget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QLayoutItem>

ButtonWidget::ButtonWidget(QWidget * parent) :
  QScrollArea(parent),
  myLayout(new QHBoxLayout(this))
{
}

ButtonWidget::~ButtonWidget()
{
}

void ButtonWidget::addButtons()
{
   QStringList texts{"1\nok", "2\nok", "3\nok", "4\nok", "5\nok", "6\nok"};

   for(int i = 0; i < texts.size(); i++)
   {
      myLayout->addWidget(new QPushButton(texts[i]));
   }
}

void ButtonWidget::deleteButtons()
{
    QLayoutItem * child;

    while((child = myLayout->takeAt(0)) != 0)
    {
      delete child->widget();
      delete child;
    }
}

#include "ButtonWidget.h"
#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QGridLayout>
#include <QHBoxLayout>
#include <memory>

std::unique_ptr<QScrollArea> makeArea()
{
  std::unique_ptr<QScrollArea> area(new QScrollArea);
  auto layout = new QGridLayout(area.get());
  auto addButton  = new QPushButton("Add");
  auto removeButton  = new QPushButton("Remove");
  layout->addWidget(addButton, 0, 0);
  layout->addWidget(removeButton, 0, 1);
  auto btnWidget = new ButtonWidget;
  layout->addWidget(btnWidget,1,0,1,2);


  QObject::connect(addButton, &QPushButton::clicked, [=]()
  {
    btnWidget->addButtons();
  });

  QObject::connect(removeButton, &QPushButton::clicked, [=]()
  {
    btnWidget->deleteButtons();
  });
  return move(area);
}

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  auto area = makeArea();
  area->show();
  return a.exec();
}
我已经为你的按钮使用了QHBoxLayout,因为它更好地模拟了你想要的。虽然严格来说没有必要,但我在main中从makeArea返回unique_ptr,因为它没有父项,我不确定它是否得到一些父项,因为它是创建的第一个小部件,但是unique_ptr显示了意图

注:

显然,布局项不是小部件的父项,但与布局相关联的小部件本身是属于其布局项的小部件的父项。

编辑:

经过更多的测试(没有查看源代码,但怀疑删除按钮必须是安全的,否则事情会变得脆弱),我实现了removeButtons,如下所示:

void ButtonWidget::deleteButtons()
{
    while(myLayout->count())
    {
        delete myLayout->itemAt(0)->widget();
    }
}
这是可行的,它证明了删除一个小部件也会从它的父部件中删除该小部件,以及与父部件关联的布局(通过连接到子部件被删除时的插槽)。上面的代码确认这一点,即count(),它表示布局项的数量,减少到零(并且这些布局项由布局管理)。takeAt(x)从未被调用,也不需要被调用——只需删除小部件(按钮)。哇

原始答案

正如我在另一篇文章中提到的,您只需要删除按钮(它会自动从父按钮中删除)。但是,如果将小部件添加到布局中,则该布局的父级将成为小部件的父级,并创建由布局本身管理的关联QLayoutItem。要删除按钮,最安全的方法是获取所有布局项(所有权由接收者负责),删除与小部件关联的每个项,然后删除每个项。我会尽量从资料来源之外找到相关的参考资料

以下代码有效:

//ButtonWidget.h
#include <QWidget>
#include <QScrollArea>
#include <QHBoxLayout>

class ButtonWidget : public QScrollArea
{
    Q_OBJECT

  public:
    ButtonWidget(QWidget *parent = 0);
    ~ButtonWidget();
    void addButtons();
    void deleteButtons();
  private:
    QHBoxLayout* myLayout;
};

//ButtonWidget.cpp

#include "ButtonWidget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QLayoutItem>

ButtonWidget::ButtonWidget(QWidget * parent) :
  QScrollArea(parent),
  myLayout(new QHBoxLayout(this))
{
}

ButtonWidget::~ButtonWidget()
{
}

void ButtonWidget::addButtons()
{
   QStringList texts{"1\nok", "2\nok", "3\nok", "4\nok", "5\nok", "6\nok"};

   for(int i = 0; i < texts.size(); i++)
   {
      myLayout->addWidget(new QPushButton(texts[i]));
   }
}

void ButtonWidget::deleteButtons()
{
    QLayoutItem * child;

    while((child = myLayout->takeAt(0)) != 0)
    {
      delete child->widget();
      delete child;
    }
}

#include "ButtonWidget.h"
#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QGridLayout>
#include <QHBoxLayout>
#include <memory>

std::unique_ptr<QScrollArea> makeArea()
{
  std::unique_ptr<QScrollArea> area(new QScrollArea);
  auto layout = new QGridLayout(area.get());
  auto addButton  = new QPushButton("Add");
  auto removeButton  = new QPushButton("Remove");
  layout->addWidget(addButton, 0, 0);
  layout->addWidget(removeButton, 0, 1);
  auto btnWidget = new ButtonWidget;
  layout->addWidget(btnWidget,1,0,1,2);


  QObject::connect(addButton, &QPushButton::clicked, [=]()
  {
    btnWidget->addButtons();
  });

  QObject::connect(removeButton, &QPushButton::clicked, [=]()
  {
    btnWidget->deleteButtons();
  });
  return move(area);
}

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  auto area = makeArea();
  area->show();
  return a.exec();
}
我已经为你的按钮使用了QHBoxLayout,因为它更好地模拟了你想要的。虽然严格来说没有必要,但我在main中从makeArea返回unique_ptr,因为它没有父项,我不确定它是否得到了一些父项,因为它是第一个小部件c