Qt-레이아웃에서 모든 위젯을 제거 하시겠습니까?
이것은 쉽지 않은 것 같습니다. 기본적으로 QPushButton
함수를 통해 s를 레이아웃에 추가하고, 함수가 실행될 때 먼저 레이아웃을 지우고 싶습니다 (모든 QPushButton
s 및 다른 모든 항목 제거 ). 더 많은 버튼이 scrollview
.
머리글
QVBoxLayout* _layout;
cpp
void MainWindow::removeButtonsThenAddMore(const QString &item) {
//remove buttons/widgets
QVBoxLayout* _layout = new QVBoxLayout(this);
QPushButton button = new QPushButton(item);
_layout->addWidget(button);
QPushButton button = new QPushButton("button");
_layout->addWidget(button);
QWidget* widget = new QWidget();
widget->setLayout(_layout);
QScrollArea* scroll = new QScrollArea();
scroll->setWidget(widget);
scroll->show();
}
나는 같은 문제가 있었다. 메인 윈도우 클래스가 QMainWindow를 상속받는 게임 앱이있다. 생성자는 부분적으로 다음과 같습니다.
m_scene = new QGraphicsScene;
m_scene->setBackgroundBrush( Qt::black );
...
m_view = new QGraphicsView( m_scene );
...
setCentralWidget( m_view );
게임 레벨을 표시하고 싶을 때 QGridLayout을 인스턴스화하여 QLabels를 추가 한 다음 픽스맵을 특정 그림 (투명 부분이있는 픽스맵)으로 설정합니다. 첫 번째 레벨은 잘 표시되지만 두 번째 레벨로 전환 할 때 첫 번째 레벨의 픽스맵은 여전히 새 레벨 뒤에 표시 될 수 있습니다 (픽스맵이 투명 함).
이전 위젯을 삭제하기 위해 여러 가지를 시도했습니다. (a) QGridLayout을 삭제하고 새 인스턴스화를 시도했지만 레이아웃을 삭제해도 추가 된 위젯이 삭제되지 않는다는 것을 알게되었습니다. (b) 나는 새로운 픽스맵에서 QLabel :: clear ()를 호출하려고 시도했지만, 물론 그것은 좀비가 아닌 새로운 픽스맵에만 영향을 미쳤습니다. (c) m_view와 m_scene을 삭제하고 새 레벨을 표시 할 때마다 재구성을 시도했지만 여전히 운이 없습니다.
그런 다음 (d) 위에 주어진 해결책 중 하나를 시도했습니다.
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
delete wItem;
하지만 그것도 작동하지 않았습니다.
그러나 더 나아가 인터넷 검색 에서 작동하는 답변을 찾았습니다 . (d)에서 누락 된 것은에 대한 호출이었습니다 delete item->widget()
. 이제 다음이 저에게 효과적입니다.
// THIS IS THE SOLUTION!
// Delete all existing widgets, if any.
if ( m_view->layout() != NULL )
{
QLayoutItem* item;
while ( ( item = m_view->layout()->takeAt( 0 ) ) != NULL )
{
delete item->widget();
delete item;
}
delete m_view->layout();
}
그런 다음 첫 번째 수준과 마찬가지로 새 QGridLayout을 인스턴스화하고 새 수준의 위젯을 추가합니다.
Qt는 여러면에서 훌륭하지만이 문제는 여기서 일이 조금 더 쉬울 수 있음을 보여줍니다.
Qt 도움말의 레이아웃 관리 페이지는 다음과 같이 설명합니다.
레이아웃은 레이아웃이 설치된 위젯의 자식이되도록 (QWidget :: setParent () 사용) 위젯의 상위 항목을 자동으로 다시 지정합니다.
내 결론 : 위젯은 수동으로 또는 레이아웃이 아닌 상위 WIDGET을 제거하여 제거해야합니다.
레이아웃의 위젯은 레이아웃 자체가 아니라 레이아웃이 설치된 위젯의 자식입니다. 위젯은 레이아웃이 아닌 다른 위젯 만 부모로 가질 수 있습니다.
내 결론 : 위와 동일
"모순"에 대해 @Muelner에게 "항목의 소유권이 레이아웃으로 이전되며이를 삭제하는 것은 레이아웃의 책임입니다." -이것은 WIDGET을 의미하는 것이 아니라 레이아웃의 상위 항목이며 나중에 레이아웃에 의해 삭제 될 ITEM입니다. 위젯은 여전히 레이아웃이 설치된 위젯의 하위이며 수동으로 또는 전체 상위 위젯을 삭제하여 제거해야합니다.
레이아웃에서 모든 위젯과 항목을 제거하고 완전히 비워 두어야하는 경우 다음과 같은 재귀 함수를 만들어야합니다.
// shallowly tested, seems to work, but apply the logic
void clearLayout(QLayout* layout, bool deleteWidgets = true)
{
while (QLayoutItem* item = layout->takeAt(0))
{
if (deleteWidgets)
{
if (QWidget* widget = item->widget())
widget->deleteLater();
}
if (QLayout* childLayout = item->layout())
clearLayout(childLayout, deleteWidgets);
delete item;
}
}
나는이 질문이 오래되었고 대답했다는 것을 알고 있지만, QtAlgorithms
offers 이후 qDeleteAll
모든 하위 항목을 한 줄로 삭제하는 것을 포함하여 레이아웃을 삭제할 수 있습니다. 이 코드는 layout
, 모든 자식 및 레이아웃 내부의 모든 것을 삭제합니다 .
qDeleteAll(yourWidget->children());
다음은 오버로드 된 함수에 대한 설명입니다.
void qDeleteAll (ForwardIterator 시작, ForwardIterator 끝)
C ++ delete> 연산자를 사용하여 [begin, end] 범위의 모든 항목을 삭제합니다. 항목 유형은 포인터 유형이어야합니다 (예 : QWidget *).
주의 qDeleteAll
요구가 그 위젯 (안 그 레이아웃)에서 용기로 공급한다. 그리고 그것은 qDeleteAll
삭제되지 않습니다 yourWidget
-단지 그 자식들만.
이제 새 레이아웃을 설정할 수 있습니다.
시도하지 않음 : 새 레이아웃을 생성하고 기존 레이아웃으로 교체 한 다음 기존 레이아웃을 삭제하지 않는 이유는 무엇입니까? 이렇게하면 레이아웃이 소유 한 모든 항목이 삭제되고 나머지 항목은 그대로 유지됩니다.
편집 : 내 대답, 문서 및 Qt 소스에 대한 주석을 연구 한 후 더 나은 솔루션을 찾았습니다.
여전히 Qt3 지원이 활성화되어 있으면 QLayout :: takeAt에 대한 문서의 힌트와 기본적으로 동일한 QLayout :: deleteAllItems ()를 사용할 수 있습니다.
다음 코드 조각은 레이아웃에서 모든 항목을 안전하게 제거하는 방법을 보여줍니다.
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
편집 : 추가 조사 후 위의 두 버전이 모두 동일한 것으로 보입니다. 부모가없는 하위 레이아웃과 위젯 만 삭제됩니다. 부모가있는 위젯은 특별한 방식으로 처리됩니다. TeL의 솔루션이 작동하는 것처럼 보이지만 최상위 위젯을 삭제하지 않도록주의해야합니다. 또 다른 방법은 위젯 계층을 사용하여 위젯을 삭제하는 것입니다. 부모없이 특수 위젯을 만들고이 특수 위젯의 자식으로 제거 가능한 모든 위젯을 만듭니다. 레이아웃을 정리 한 후이 특별한 위젯을 삭제하십시오.
또한 스페이서와 QWidget이 아닌 것을 제거해야합니다. 레이아웃의 유일한 항목이 QWidgets라고 확신하는 경우 이전 답변은 괜찮습니다. 그렇지 않으면 다음을 수행해야합니다.
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
delete wItem;
지우려는 레이아웃이 더 큰 레이아웃의 일부인 경우 레이아웃을 파괴하고 싶지 않기 때문에이를 수행하는 방법을 아는 것이 중요합니다. 레이아웃이 나머지 창과의 위치 및 관계를 유지하는지 확인하고 싶습니다.
또한주의해야합니다.이 메서드를 호출 할 때마다 많은 개체를 만들고 정리되지 않습니다. 첫째, 아마도 QWidget과 QScrollArea를 다른 곳에 생성하고 참조를 위해 그들을 가리키는 멤버 변수를 유지해야합니다. 그러면 코드는 다음과 같이 보일 수 있습니다.
QLayout *_layout = WidgetMemberVariable->layout();
// If it is the first time and the layout has not been created
if (_layout == 0)
{
_layout = new QVBoxLayout(this);
WidgetMemberVariable->setLayout(_layout);
}
// Delete all the existing buttons in the layout
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
delete wItem;
// Add your new buttons here.
QPushButton button = new QPushButton(item);
_layout->addWidget(button);
QPushButton button = new QPushButton("button");
_layout->addWidget(button);
You do not write about going the other way, but you could also just use a QStackedWidget
and add two views to this, one for each arrangement of buttons that you need. Flipping between the two of them is a non issue then and a lot less risk than juggling various instances of dynamically created buttons
None of the existing answers worked in my application. A modification to Darko Maksimovic's appears to work, so far. Here it is:
void clearLayout(QLayout* layout, bool deleteWidgets = true)
{
while (QLayoutItem* item = layout->takeAt(0))
{
QWidget* widget;
if ( (deleteWidgets)
&& (widget = item->widget()) ) {
delete widget;
}
if (QLayout* childLayout = item->layout()) {
clearLayout(childLayout, deleteWidgets);
}
delete item;
}
}
It was necessary, at least with my hierarchy of widgets and layouts, to recurse and to delete widgets explicity.
only works for my buttonlist, if the widgets themeselves are deleted, too. otherwise the old buttons are still visible:
QLayoutItem* child;
while ((child = pclLayout->takeAt(0)) != 0)
{
if (child->widget() != NULL)
{
delete (child->widget());
}
delete child;
}
I had a similar case where I have a QVBoxLayout
containing dynamically created QHBoxLayout
objects containing a number of QWidget
instances. For some reason I couldn't get rid of the widgets either by deleting neither the top level QVBoxLayout or the individual QHBoxLayouts. The only solution I got to work was by going through the hierarchy and removing and deleting everything specifically:
while(!vbox->isEmpty()) {
QLayout *hb = vbox->takeAt(0)->layout();
while(!hb->isEmpty()) {
QWidget *w = hb->takeAt(0)->widget();
delete w;
}
delete hb;
}
If you want to remove all widgets, you could do something like this:
foreach (QObject *object, _layout->children()) {
QWidget *widget = qobject_cast<QWidget*>(object);
if (widget) {
delete widget;
}
}
I have a possible solution for this problem (see Qt - Clear all widgets from inside a QWidget's layout). Delete all widgets and layouts in two seperate steps.
Step 1: Delete all widgets
QList< QWidget* > children;
do
{
children = MYTOPWIDGET->findChildren< QWidget* >();
if ( children.count() == 0 )
break;
delete children.at( 0 );
}
while ( true );
Step 2: Delete all layouts
if ( MYTOPWIDGET->layout() )
{
QLayoutItem* p_item;
while ( ( p_item = MYTOPWIDGET->layout()->takeAt( 0 ) ) != nullptr )
delete p_item;
delete MYTOPWIDGET->layout();
}
After step 2 your MYTOPWIDGET should be clean.
If you don't do anything funny when adding widgets to layouts and layouts to other layouts they should all be reparented upon addition to their parent widget. All QObject
s have a deleteLater()
slot which will cause the QObject
to be deleted as soon as control is returned to the event loop. Widgets deleted in this Manor also delete their children. Therefore you simply need to call deleteLater()
on the highest item in the tree.
in hpp
QScrollArea * Scroll;
in cpp
void ClearAndLoad(){
Scroll->widget()->deleteLater();
auto newLayout = new QVBoxLayout;
//add buttons to new layout
auto widget = new QWidget;
widget->setLayout(newLayout);
Scroll->setWidget(widget);
}
또한 귀하의 예제에서는 _layout
지역 변수이며 _layout
헤더 파일 ( QVBoxLayout*
부분 제거 ) 과 동일하지 않습니다 . 로 시작하는 이름 _
은 표준 라이브러리 구현자를 위해 예약되어 있습니다. 나는 지역 변수를 보여주기 위해 후행 _
을 사용하는데 var_
, 많은 취향이 있지만 선행 _
하고 __
기술적으로 예약되어 있습니다.
참조 URL : https://stackoverflow.com/questions/4272196/qt-remove-all-widgets-from-layout
'IT TIP' 카테고리의 다른 글
HAML 내의 Javascript 내의 Ruby 메서드 (0) | 2020.12.15 |
---|---|
OpenCV : IplImage와 Mat, 어떤 것을 사용해야합니까? (0) | 2020.12.15 |
리플렉션 (Java)을 사용하여 개인 정적 메서드를 어떻게 호출합니까? (0) | 2020.12.15 |
setup.py 및 / bin /에 파일 추가 (0) | 2020.12.15 |
부호있는 문자에서 부호없는 문자로 변환하고 다시 되 돌리시겠습니까? (0) | 2020.12.15 |