Qt:Widget方法addButtons()不工作,根据需要 [英] Qt: Widget method addButtons() does NOT work as needed

查看:288
本文介绍了Qt:Widget方法addButtons()不工作,根据需要的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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()));

并且 ButtonWidget / p>

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

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

//我不确定这个方法/函数是否确定... :(
void ButtonWidget :: deleteButtons()
{
QLayoutItem * child;
while((child = gridLayout-> takeAt(0))!= 0)
{
gridLayout-> removeWidget(child-&widget; widget ;
delete child-> widget();
delete child;
}
delete gridLayout;
}

问题是:当我点击 add_buttons 时,显示所有按钮, >收缩,微小或某事...:



OTOH ..如果我从 addButtons()中删除​​注释(因此从构造函数中调用),结果是确定:



因此,最后我有两个问题:

1)修复代码以便能够正确添加这些按钮(单击 add_buttons 时)?

2) deleteButtons()方法ok?

解决方案

b
$ b

经过一些更多的测试(没有查看源代码,但怀疑它必须是安全的删除按钮,否则事情会脆),我实现removeButtons如下: p>

  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();
私人:
QHBoxLayout * myLayout;
};

//ButtonWidget.cpp

#includeButtonWidget.h
#include< QGridLayout>
#include< QPushButton>
#include< QLayoutItem>

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

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

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

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

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

#includeButtonWidget.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 $ b});

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()
}

您需要在配置(.pro)中启用c ++ 11获得lambdas工作。

  CONFIG + = c ++ 11 

我使用QHBoxLayout为你的按钮,因为它更好地模型你想要的。虽然严格没有必要,我返回unique_ptr从makeArea在主,因为它没有父,我不知道它是否得到一些父,因为它是第一个小部件创建,但unique_ptr显示意图。



注意:



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


I am using Qt5 (beginner) on Windows7.
In the main window of my app I want to display and remove some push-buttons.

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()));

And the ButtonWidget class is here:

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;
}

Problem is: when I click on add_buttons, I get all buttons displayed, but they are shrunk, tiny or something... :

OTOH... if I remove the comment from addButtons() call in the constructor (hence calling from within the constructor), the result is ok:

So, finally I have 2 questions:
1) How to fix the code to be able to add those buttons properly (when add_buttons is clicked)?
2) Is the deleteButtons() method ok?

解决方案

EDIT:

After some more testing (without looking at the source code, but suspecting that it must be safe to delete button, else things would be brittle), I've implemented removeButtons as follows:

void ButtonWidget::deleteButtons()
{
    while(myLayout->count())
    {
        delete myLayout->itemAt(0)->widget();
    }
}

This works, and it proves that deleting a widget also removes the widget from it's parent, and layouts associated with the parent (by slots hooked up to when a child widget is deleted). The above code confirms this, as count(), which refers to number of layout items, decrease to zero (and those layout items are managed by the Layout). takeAt(x) is never called, and doesn't need to be - simply delete the widgets (buttons). Wholla!

ORIGINAL ANSWER

As mentioned in my other post, you only need to delete the buttons (it is removed from its parent automatically). However, if a widget was added to a layout, the parent of that layout becomes the parent of the widget, and an associated QLayoutItem is created that is managed by the layout itself. To the delete the buttons, the safest way is to take all the layout items (ownership the taker's responsibility), delete each items associated widget, and the delete each item. I'll try and find relevant references apart from the sources...

The following code works:

//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();
}

You need to enable c++11 in your config (.pro) to get the lambdas working.

CONFIG += c++11

I've used QHBoxLayout for your buttons, as it better models what you want. Although strictly not necessary, I'm returning unique_ptr from the makeArea in main, as it has not parent, I'm not sure whether it gets some parent because it is the first widget created, but unique_ptr shows intent.

NOTE:

Apparently the layout item is not the parent of the widget, but the widget associated with the layout itself is the parent of widgets belonging to its layout item.

这篇关于Qt:Widget方法addButtons()不工作,根据需要的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆