添加新项时如何避免QListWidget列表项被重置?

时间:2019-11-06 08:01:07

标签: python pyqt pyqt5 qlistwidget

我有一个带有QListWidget的GUI,它没有任何条目。使用“添加”按钮添加条目。我的问题是,当您编辑列表项的文本时,如果在按下Enter键或单击鼠标键之前再次单击添加按钮,则会删除您输入的文本(请参阅gif以供参考)

screenshot

另外,还有一个gif显示代码可以正常工作:

screenshot

问题是它不会保存您每次​​击键输入的内容。而是等到您完成操作并更改选择或按Enter键。

有人可以建议解决此问题的方法吗?

代码:

我在GUI类的init函数中声明了以下信号:

self.w_client_list.itemChanged.connect(self.edit_client_name)
self.w_client_list.itemSelectionChanged.connect(self.switching_clients)
self.b_add_client.clicked.connect(self.add_client)

这些是信号连接到的插槽功能:

    def get_index(self):
        """Gets index number of selected client for client details functions"""
        for i in range(self.w_client_list.count()):
            if self.w_client_list.item(i).isSelected():
                index = i
                return index
        index = None
        return index

    @Slot()
    def switching_clients(self):
        index = self.get_index()
        if index == None:
            self.l_email.clear()
            self.c_main_email.setCheckState(Qt.Unchecked)
            self.c_secondary_email.setCheckState(Qt.Unchecked)
            self.w_phone.clear()
            self.l_preferred_name.clear()
            self.w_title.setCurrentText('Mr')
        else:
            # Email
            self.l_email.setText(self.client.individual[index]['email'][0])
            self.c_main_email.setChecked(self.client.individual[index]['email'][1])
            self.c_secondary_email.setChecked(self.client.individual[index]['email'][2])
            # Phone
            self.update_phone_list()
            # Preferred Name
            self.l_preferred_name.setText(self.client.individual[index]['preferred_name'])
            # Title
            self.w_title.setCurrentText(self.client.individual[index]['title'])

    @Slot()
    def edit_client_name(self):
        index = self.get_index()
        self.client.individual[index]['full_name'] = self.w_client_list.item(index).text().strip()
        self.switching_clients()

    @Slot()
    def add_client(self):
        self.client.individual.append({'title': 'Mr', 'first_name': '', 'middle_name': '', 'last_name': '',
                                        'full_name': 'Enter full name',
                                        'preferred_name': '', 'salutation': '', 'postal_salutation': '',
                                        'email': ['', 0, 0], 'address': [], 'phone': [],
                                        'preferred_name_connected': True})
        self.update_client_list()  # Updates the client form to show new address row

    def update_client_list(self):
        self.w_client_list.clear()
        client_list = []
        for client in self.client.individual:
            item = QtWidgets.QListWidgetItem()
            item.setText(client['full_name'])
            item.setFlags(
                QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled)
            self.w_client_list.addItem(item)
        item.setSelected(True)


3 个答案:

答案 0 :(得分:2)

您可以通过setting the focus policy中的按钮NoFocus来解决此问题。这使项目编辑器在单击按钮时保持打开状态(因为它们不会占用焦点)。然后,可以使用列表小部件的isPersistentEditorOpen方法来防止用户仍在编辑时进行不必要的操作。

更新

如果要在添加新项目时提交当前编辑,则可以只调用列表小部件上的setFocus(因为该按钮不会占据焦点)。这也意味着不再需要按照上面的建议检查项目编辑器是否打开。


这是基于您的代码的有效演示:

import sys
from PyQt5 import QtCore, QtWidgets

class Client:
    individual = []

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.client = Client()
        self.b_add_client = QtWidgets.QPushButton('Add')
        self.b_add_client.setFocusPolicy(QtCore.Qt.NoFocus)
        self.w_client_list = QtWidgets.QListWidget()
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.w_client_list)
        layout.addWidget(self.b_add_client)
        self.w_client_list.itemChanged.connect(self.edit_client_name)
        self.b_add_client.clicked.connect(self.add_client)

    def get_index(self):
        selection = self.w_client_list.selectedItems()
        if selection:
            return self.w_client_list.indexFromItem(selection[0]).row()

    def switching_clients(self):
        pass

    def edit_client_name(self):
        index = self.get_index()
        if index is not None:
            text = self.w_client_list.item(index).text().strip()
            if text:
                self.client.individual[index]['full_name'] = text
        self.switching_clients()

    def add_client(self):
        self.w_client_list.setFocus()
        self.client.individual.append({
            'title': 'Mr', 'first_name': '', 'middle_name': '',
            'last_name': '', 'full_name': 'Enter full name',
            'preferred_name': '', 'salutation': '',
            'postal_salutation': '', 'email': ['', 0, 0],
            'address': [], 'phone': [],
            'preferred_name_connected': True,
            })
        self.update_client_list()

    def update_client_list(self):
        if len(self.client.individual):
            self.w_client_list.clear()
            for client in self.client.individual:
                item = QtWidgets.QListWidgetItem()
                item.setText(client['full_name'])
                item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
                self.w_client_list.addItem(item)
            item.setSelected(True)
            self.w_client_list.editItem(item)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

答案 1 :(得分:0)

我要做的是,当用户单击“添加”时,程序首先通过比较“旧”字符串来验证条目是否已更改。 和新的。如果是这样,它将保存新的字符串并将其设置为小部件。否则,它将仅添加新条目。我希望这可以引导您找到解决方案。

答案 2 :(得分:0)

当前行为是预期行为。

您已正确识别出罪魁祸首:用户需要进行编辑更改,而中断编辑过程将取消该更改。如果您希望立即应用更改,则需要一个实现替代行为的自定义委托。 (有关自定义委托的工作方式,请参见this example in Qt docs

请注意,尽管如此,更改基本的UI行为还是被忽略了。您的应用程序看起来将与其他任何应用程序一样,但是在行为上与其他应用程序有所不同。在UI世界中,通常 consistency 为王。自定义此类行为也会产生无法预料的副作用,尤其是在您针对多个平台的情况下。而且还需要维护很多额外的代码。