如何使用列表迭代地添加带有删除按钮的标签,可以删除它们

Posted

技术标签:

【中文标题】如何使用列表迭代地添加带有删除按钮的标签,可以删除它们【英文标题】:How to use a list to iteratively add qlabels with delete buttons that can remove them 【发布时间】:2020-12-31 15:15:11 【问题描述】:

这里有很多关于使用 QButton 创建 QLabel 以删除它们的问题。但是,没有任何关于如何使用字符串列表迭代地创建这些标签并将删除按钮附加到它们的信息。

我已经使用下面的代码进行了尝试。它会生成一个 lineEdit,您可以将多个文件放入其中,它将生成这些文件的列表,这些文件将迭代地变成标签和相应的删除按钮。它可以工作,但是,当我按下每个标签上的删除按钮时,我得到“运行时错误:QLabel 类型的包装 C/C++ 对象已被删除”。我想这是因为我设法创建了标签列表,但删除按钮仅附加到其中一个标签上。

请参阅下面的代码:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLineEdit, QLabel, QApplication, QWidget, QPushButton, QMainWindow, QHBoxLayout, QVBoxLayout


global search_list
search_list = []

class LocationDrag(QLineEdit):

    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
    
    
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        print(event)
        if event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()
                
    def dropEvent(self, event):
        if event.mimeData().hasText():
            event.setDropAction(Qt.CopyAction)
            
            dragged_files = event.mimeData().urls()
            dragged_files_paths = [url.toLocalFile() for url in event.mimeData().urls()]
            
            global search_list
            search_list.extend(dragged_files_paths)
            for item in search_list:
                name = QtWidgets.QLabel(item)
                name.setStyleSheet('QLabel width:90; height:30; background-color: rgb(27, 29, 35); border-radius: 5px; border: 2px solid rgb(27, 29, 35); padding: 5px;')

                deletebutton = QtWidgets.QPushButton("x")
                deletebutton.setStyleSheet('QPushButton color: red; font-weight:bold; padding:5px')

                deletebutton.clicked.connect(lambda:delete_location(self, (name, deletebutton), item))

                demo.mainLayout.addWidget(name, alignment=QtCore.Qt.AlignLeft)
                demo.mainLayout.addWidget(deletebutton)
                    
        

def delete_location(self, widgets, search_item):
    if search_list:
        name, deletebutton = widgets
        name.deleteLater()
        deletebutton.deleteLater()
        search_list.remove(search_item)
        

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.setAcceptDrops(True)
 
        self.mainLayout = QVBoxLayout()

        self.lineEdit_2 = LocationDrag()
        self.lineEdit_2.setGeometry(10,35,350,30)
        self.lineEdit_2.setStyleSheet("QLineEdit \n"
        "    background-color: rgb(27, 29, 35);\n"
        "    border-radius: 5px;\n"
        "    border: 2px solid rgb(27, 29, 35);\n"
        "    padding-left: 10px;\n"
        "\n"
        "QLineEdit:hover \n"
        "    border: 2px solid rgb(64, 71, 88);\n"
        "\n"
        "QLineEdit:focus \n"
        "    border: 2px solid rgb(91, 101, 124);\n"
        "")

        self.mainLayout.addWidget(self.lineEdit_2)
        self.setLayout(self.mainLayout)
 
app = QApplication(sys.argv)
demo = AppDemo()
demo.show()
sys.exit(app.exec_())

【问题讨论】:

请提供minimal reproducible example @eyllanesc 我已经更新了这个问题。希望现在更清楚了。如果您需要我做其他事情,请说。 @goodaytar 是的,我们需要您提供一个实际最小可重现的示例。我们必须能够复制、粘贴和运行您的代码。请仔细阅读并遵循 eyllanesc 分享的链接中的建议。 @goodaytar 那段代码不是 MRE,因为如果我复制并粘贴它,我将无法启动应用程序,因此我将无法分析错误在哪里 谢谢你们。 @eyllanesc 。仍然掌握所有这一切。我现在更新了我的代码。如果您运行它并将文件拖入 QlineEdit。它们生成正常,但是当您单击“x”尝试删除它们时会出现问题。 【参考方案1】:

你太复杂了,因为你把很多任务留给了几个类,例如 LocationDrag 应该只获取路线,它不应该将它添加到窗口中。另一方面,最好创建一个代表 QLabel + QPushButton 行的小部件,然后每次按下按钮时都会消除该行小部件,这种消除意味着它将从布局中删除。

import sys
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import (
    QLineEdit,
    QLabel,
    QApplication,
    QWidget,
    QPushButton,
    QMainWindow,
    QHBoxLayout,
    QVBoxLayout,
)


class LocationDrag(QLineEdit):
    filesChanged = pyqtSignal(list)

    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasText():
            event.setDropAction(Qt.CopyAction)
            files = []
            for url in event.mimeData().urls():
                if url.isLocalFile():
                    files.append(url.toLocalFile())
            if files:
                self.filesChanged.emit(files)


class RowWidget(QWidget):
    def __init__(self, name, parent=None):
        super().__init__(parent)
        nameLabel = QLabel(name)
        nameLabel.setStyleSheet(
            "QLabelbackground-color: rgb(27, 29, 35); border-radius: 5px; border: 2px solid rgb(27, 29, 35); padding: 5px;"
        )
        deletebutton = QPushButton("x")
        deletebutton.setStyleSheet(
            "QPushButton color: red; font-weight:bold; padding:5px"
        )

        lay = QVBoxLayout(self)
        lay.addWidget(nameLabel, alignment=Qt.AlignLeft)
        lay.addWidget(deletebutton)
        self.setContentsMargins(0, 0, 0, 0)

        deletebutton.clicked.connect(self.deleteLater)


class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.setAcceptDrops(True)

        self.mainLayout = QVBoxLayout(self)

        self.lineEdit = LocationDrag()
        self.lineEdit.setStyleSheet(
            "QLineEdit "
            "    background-color: rgb(27, 29, 35);"
            "    border-radius: 5px;"
            "    border: 2px solid rgb(27, 29, 35);"
            "    padding-left: 10px;"
            ""
            "QLineEdit:hover "
            "    border: 2px solid rgb(64, 71, 88);"
            ""
            "QLineEdit:focus "
            "    border: 2px solid rgb(91, 101, 124);"
            ""
        )

        self.mainLayout.addWidget(self.lineEdit, alignment=Qt.AlignTop)
        self.lineEdit.filesChanged.connect(self.handle_files_changed)

    def handle_files_changed(self, files):
        for file in files:
            rowWidget = RowWidget(file)
            self.mainLayout.addWidget(rowWidget, alignment=Qt.AlignTop)


app = QApplication(sys.argv)
demo = AppDemo()
demo.show()
sys.exit(app.exec_())

【讨论】:

以上是关于如何使用列表迭代地添加带有删除按钮的标签,可以删除它们的主要内容,如果未能解决你的问题,请参考以下文章

带有 HTML 表单的 Laravel 删除按钮

如何使用标签属性删除动态添加的控件

如何从 plotly 中删除图中的轴刻度线?

如果注释是由用户登录后如何显示删除按钮?

如何从 R 中的 ngram 标记列表中有效地删除停用词

如何向列表添加编辑按钮,就像在向左滑动列表项时删除按钮一样