удалить последние два виджета из макета сетки в pyqt - PullRequest
0 голосов
/ 31 марта 2020

У меня есть эта функция, которая удаляет последний QLineEdit виджет из QGridLayout

, он проверяет, является ли индекс виджета последним и является ли виджет экземпляром QLineEdit - -> удаляет виджет

  def deleate_lastlineedit(self):
        widgets = (self.main_layout.itemAt(i).widget() for i in range(self.main_layout.count()))
        for index, widget in enumerate(widgets):
            if index == (self.main_layout.count()-1) and isinstance(widget, (qtw.QLineEdit,qtw.QLabel)):
                widget.deleteLater()
                break

Я добавил виджет Qlabel к той же строке и хочу, чтобы функция удаляла последний виджет Qlabel и Qlinedit одновременно после нажатия кнопки, пока его удаляет по одному, нужно нажать кнопку два раза.

Я попытался вставить счетчик, чтобы итерация останавливалась не на одной итерации, а на двух итерациях, чтобы она получала два виджета, но не имела эффекта.

также вставил две версии функции: одну, которая удаляет редактирование qline, и другую, которая удаляет qlabel и подключала их к той же кнопке, но не работала либо

self.getlistof_button.clicked.connect(self.deleate_lastlineedit)
self.getlistof_button.clicked.connect(self.deleate_lastqlabel)

, так как я могу удалить два виджета одновременно?


полный код

#!/usr/bin/env python

"""
Creates an linedit when button pushed
dleates last linedit


"""

import sys
import sqlite3

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
from PyQt5 import QtSql as qsql

from  PyQt5 import sip



class AddWidget(qtw.QWidget):
    '''
    Interface
    '''

    # Attribut Signal

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # your code will go here


        # interface

        # position
        qtRectangle = self.frameGeometry()
        centerPoint = qtw.QDesktopWidget().availableGeometry().center()
        qtRectangle.moveCenter(centerPoint)
        self.move(qtRectangle.topLeft())
        # size
        self.resize(700, 410)
        # frame title
        self.setWindowTitle("add  Widget")
        # heading
        heading_label = qtw.QLabel('add Widget')
        heading_label.setAlignment(qtc.Qt.AlignHCenter | qtc.Qt.AlignTop)

        # add Button
        self.addwidget_button = qtw.QPushButton("add Widget")
        self.getlistof_button = qtw.QPushButton("deleate")
        self.linedittext_button = qtw.QPushButton("linedit text")

        self.main_layout = qtw.QGridLayout()
        self.main_layout.addWidget(self.getlistof_button,0,0)
        self.main_layout.addWidget(self.addwidget_button, 1, 0)
        self.main_layout.addWidget(self.linedittext_button, 2, 0)



        self.setLayout(self.main_layout)


        self.show()

        # functionality
        self.addwidget_button.clicked.connect(self.add_widget)
        self.getlistof_button.clicked.connect(self.deleate_lastlineedit)
        self.getlistof_button.clicked.connect(self.deleate_lastqlabel)

        self.linedittext_button.clicked.connect(self.count)




    def count(self):
        x = self.main_layout.rowCount()
        print(self.main_layout.rowCount()+1)
        print(type(x))

    def add_widget(self):
        my_lineedit = qtw.QLineEdit()
        x1 = (self.main_layout.rowCount()+1)
        my_dynmic_label = qtw.QLabel("Dynamic")
        self.main_layout.addWidget(my_dynmic_label,x1,0)
        self.main_layout.addWidget(my_lineedit,x1,1)


    def deleate_lastqlabel(self):
        widgets = (self.main_layout.itemAt(i).widget() for i in range(self.main_layout.count()))
        for index, widget in enumerate(widgets):
            if index == (self.main_layout.count()-1) and isinstance(widget, qtw.QLabel):
                # print("yes")
                widget.deleteLater()
                break



    def deleate_lastlineedit(self):
        widgets = (self.main_layout.itemAt(i).widget() for i in range(self.main_layout.count()))
        for index, widget in enumerate(widgets):
            if index == (self.main_layout.count()-1) and isinstance(widget, qtw.QLineEdit):
                widget.deleteLater()
                break




if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    w = AddWidget()
    sys.exit(app.exec_())



1 Ответ

0 голосов
/ 31 марта 2020

Как следует из названия, deleteLater() удаляет объект позже .

Планирует удаление этого объекта.

объект будет удален , когда управление вернется к событию l oop.

Если вы добавите print(self.main_layout.count()) после каждого вызова deleteLater в цикле, вы будете убедитесь, что счетчик все тот же, и это потому, что элемент управления еще не возвращен событию l oop.

Вы должны использовать layout.removeWidget() вместо этого.

Кроме того, этого все равно будет недостаточно.
Вы перебираете весь список, пока не найдете последний элемент, но это означает, что следующий за последним будет не проверить. Возможным решением было бы сделать цикл for дважды , но сделать это было бы не самым умным занятием.

Итак, , как я уже предлагал , вы должны использовать reversed(). Кроме того, вам нужна некоторая форма контроля, так как вы собираетесь удалить два виджета, в противном случае цикл прервется, как только он найдет первое совпадение для isinstance.

def deleate_lastlineedit(self):
    labelRemoved = editRemoved = False
    widgets = [self.main_layout.itemAt(i).widget() for i in range(self.main_layout.count())]
    for widget in reversed(widgets):
        if isinstance(widget, qtw.QLineEdit):
            editRemoved = True
        elif isinstance(widget, qtw.QLabel):
            labelRemoved = True
        else:
            continue
        # in this case, removeWidget is not necessary, since we're not
        # checking the count, but I'll leave it anyway for completeness;
        self.main_layout.removeWidget(widget)
        widget.deleteLater()
        if editRemoved and labelRemoved:
            break

Так как вам нужно только удалить последние виджеты, создание генератора для целых виджетов не требуется. Пока вы всегда вставляете только QLabels и QLineEdits в конце макета, вы можете просто использовать некоторое время l oop.

def deleate_lastlineedit(self):
    labelRemoved = editRemoved = False
    while not (labelRemoved and editRemoved):
        widget = self.main_layout.itemAt(self.main_layout.count() - 1).widget()
        # now here removeWidget *IS* required, otherwise the while loop will
        # never exit
        self.main_layout.removeWidget(widget)
        widget.deleteLater()
        if isinstance(widget, qtw.QLineEdit):
            editRemoved = True
        elif isinstance(widget, qtw.QLabel):
            labelRemoved = True

PS: Я уже предложил вам лучше изучить Python управляющих потоков , пожалуйста, следуйте моему совету: это ваш ЧЕТВЕРТЫЙ вопрос почти с той же проблемой, и Я ответил только потому, что хотел прояснить проблему deleteLater(), но вам даже не нужно было бы ее спрашивать, если бы вы следовали моим предыдущим предложениям и ответам. Пожалуйста, делайте изучайте и практикуйтесь, вы не можете ожидать кодирования GUI, если вы даже не понимаете самых элементарных основ его языка .

...