Как избежать сброса элемента списка QListWidget при добавлении нового элемента? - PullRequest
1 голос
/ 06 ноября 2019

У меня есть графический интерфейс с QListWidget, который начинается без записей. Записи добавляются с помощью кнопки «Добавить». У меня проблема в том, что когда вы редактируете текст элемента списка, если вы нажимаете кнопку «Добавить» еще раз, прежде чем нажать «Ввод» или «Уход», введенный вами текст стирается (см. Рисунок в формате gif)

screenshot

Кроме того, еще один gif, чтобы показать, что код работает иначе:

screenshot

Проблема в том, что он не сохраняет то, что вы печатаете с каждымнажатие клавиши. Вместо этого он ожидает, пока вы не закончите и не измените выбор или не нажмете клавишу ввода.

Может кто-нибудь предложить способ исправить это?

Код:

У меня есть следующие сигналы, объявленные в функции init моего класса GUI:

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 ]

2 голосов
/ 06 ноября 2019

Вы можете исправить это, установив политику фокусировки кнопок на 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_())
0 голосов
/ 06 ноября 2019

Текущее поведение - это ожидаемое поведение.

Вы правильно определили виновника: редактирование изменений должно быть зафиксировано пользователем, а прерывание процесса редактирования отменит его. Если вы хотите, чтобы изменения были применены немедленно, вам нужен пользовательский делегат, который реализует ваше альтернативное поведение. (Смотрите этот пример в документации Qt , чтобы узнать, как работают пользовательские делегаты).

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

0 голосов
/ 06 ноября 2019

Что я хотел бы сделать, так это то, что когда пользователь нажимает «добавить», программа сначала проверяет, была ли запись изменена, сравнивая «старую» строку. и новый. если это так, он сохранит новую строку и установит ее в виджет. В противном случае он просто добавит новую запись. Я надеюсь, что это может привести вас к решению.

...