Доступ к SQL данным из записи списка - PullRequest
1 голос
/ 15 февраля 2020

Сначала я опишу и покажу, как моя мини-программа работает визуально, поэтому мою проблему легко понять

Описание программы

Ниже приведены две вдовы, которые я использую для программы:

Главное окно

Окно ввода

Главное окно отображается в начале программы , Я использовал QListWidget для списка «Макросы», который показывает заголовки каждой записи, прочитанной из базы данных Sqlite (БД). Новое окно ввода отображается при нажатии кнопки «Создать» в главном окне. Кнопка «Сохранить» в окне ввода сохраняет ввод заголовка и описания в БД и обновляет список «Макросы» в главном окне. Это будет выглядеть примерно так:

Введите информацию в окне ввода

Обновлено главное окно

Моя таблица Sqlite

Моя проблема

Я хотел бы иметь возможность выбрать запись в списке «Макросы», нажать кнопку «Редактировать» и показать окно ввода, заполненное данными из БД. Однако, поскольку QListWidget позволяет вводить только строки, я не могу искать, используя его PK ('id').

Я думаю об использовании QTableWidget вместо QListWidget. Я загружу всю таблицу, но скрою все столбцы, кроме столбца заголовка, чтобы в главном окне в списке «Макросы» отображались только заголовки. Для запросов я буду использовать PK записи, получая доступ к 0-му индексу выбранной записи.

Пожалуйста, дайте мне знать, если это правильный шаг. Если нет, опишите, что вы будете использовать для реализации списка, который показывает только заголовок, но позволяет запрашивать его данные. Я новичок в PyQt / PySide и буду очень признателен за любые рекомендации.

Коды

Ниже приведен код, выполняемый при нажатии кнопки «Сохранить» (плюс его вспомогательные функции)

def save_macro(self):

    title = self.lineedit.text()
    description = self.textedit.toPlainText()

    add_sql_query = ''' INSERT INTO Macros (title,description)
                  VALUES(?,?) '''

    # Helper func that creates connection to db
    sqlhelper = SqliteHelper("entry name")

    if sqlhelper is not None:  # If db is connected:
        macro_data = (title, description)
        sqlhelper.insert(add_sql_query, macro_data)  

    self.close()


class SqliteHelper:

    def __init__(self, name=None):
        self.conn = None
        self.cursor = None

        if name:
            self._create_connection(name)

    def _create_connection(self, name):
        try:
            self.conn = sqlite3.connect(name)
            self.cursor = self.conn.cursor()
            print(sqlite3.version)
        except sqlite3.Error as e:
            print(e)

    def insert(self, query, inserts):  # Insert
        c = self.cursor
        c.execute(query, inserts)
        self.conn.commit()

1 Ответ

1 голос
/ 15 февраля 2020

Не изобретайте колесо, Qt предоставляет классы для взаимодействия с базой данных, например, для обработки информации о таблицах, вы можете использовать QSqlQueryModel, QSqlTableModel, et c. Чтобы добавить строку, вы должны создать QSqlRecord и добавить его в модель, для выпуска вы можете использовать QDataWidgetMapper, который отображает и редактирует информацию строки, а для удаления вы должны удалить строку и перезагрузить всю таблицу. Чтобы указать, какое поле должно отображаться в QListView, используйте метод setModelColumn (), который должен быть столбцом поля «title».

from PyQt5 import QtCore, QtGui, QtWidgets, QtSql


def create_connection(database):
    db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(database)
    if not db.open():
        print("Cannot open database")
        print(
            "Unable to establish a database connection.\n"
            "This example needs SQLite support. Please read "
            "the Qt SQL driver documentation for information "
            "how to build it.\n\n"
            "Click Cancel to exit."
        )
        return False

    query = QtSql.QSqlQuery()
    if not query.exec_(
        """CREATE TABLE IF NOT EXISTS Macros (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT,
    "title" TEXT,
    "description" TEXT)"""
    ):
        print(query.lastError().text())
        return False
    return True


class AddMacroDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.title_le = QtWidgets.QLineEdit()
        self.description_te = QtWidgets.QPlainTextEdit()

        button_box = QtWidgets.QDialogButtonBox(self)
        button_box.setOrientation(QtCore.Qt.Horizontal)
        button_box.setStandardButtons(
            QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
        )

        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.title_le)
        lay.addWidget(self.description_te)
        lay.addWidget(button_box)

    @property
    def title(self):
        return self.title_le.text()

    @property
    def description(self):
        return self.description_te.toPlainText()


class EditMacroDialog(QtWidgets.QDialog):
    def __init__(self, model, index, parent=None):
        super().__init__(parent)

        self.title_le = QtWidgets.QLineEdit()
        self.description_te = QtWidgets.QPlainTextEdit()

        mapper = QtWidgets.QDataWidgetMapper(
            self, submitPolicy=QtWidgets.QDataWidgetMapper.ManualSubmit
        )
        mapper.setModel(model)
        mapper.addMapping(self.title_le, model.record().indexOf("title"))
        mapper.addMapping(self.description_te, model.record().indexOf("description"))
        mapper.setCurrentIndex(index)

        button_box = QtWidgets.QDialogButtonBox(self)
        button_box.setOrientation(QtCore.Qt.Horizontal)
        button_box.setStandardButtons(
            QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
        )

        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        button_box.accepted.connect(mapper.submit)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.title_le)
        lay.addWidget(self.description_te)
        lay.addWidget(button_box)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._model = QtSql.QSqlTableModel(self)
        self.model.setTable("Macros")
        self.model.select()

        self.sql_list_view = QtWidgets.QListView()
        self.sql_list_view.setModel(self.model)
        self.sql_list_view.setModelColumn(self.model.record().indexOf("title"))

        self.new_button = QtWidgets.QPushButton(self.tr("New"))
        self.edit_button = QtWidgets.QPushButton(self.tr("Edit"))
        self.remove_button = QtWidgets.QPushButton(self.tr("Remove"))

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)

        grid_layout = QtWidgets.QGridLayout(central_widget)
        grid_layout.addWidget(
            QtWidgets.QLabel(self.tr("Macros"), alignment=QtCore.Qt.AlignCenter)
        )
        grid_layout.addWidget(self.sql_list_view, 1, 0)

        vlay = QtWidgets.QVBoxLayout()
        vlay.addWidget(self.new_button)
        vlay.addWidget(self.edit_button)
        vlay.addWidget(self.remove_button)
        grid_layout.addLayout(vlay, 1, 1)
        self.resize(640, 480)

        self.new_button.clicked.connect(self.new)
        self.edit_button.clicked.connect(self.edit)
        self.remove_button.clicked.connect(self.remove)

        self.sql_list_view.selectionModel().selectionChanged.connect(
            self.onSelectionChanged
        )
        self.onSelectionChanged()

    @property
    def model(self):
        return self._model

    @QtCore.pyqtSlot()
    def new(self):
        d = AddMacroDialog()
        if d.exec_() == QtWidgets.QDialog.Accepted:
            r = self.model.record()
            r.setValue("title", d.title)
            r.setValue("description", d.description)
            if self.model.insertRecord(self.model.rowCount(), r):
                self.model.select()

    @QtCore.pyqtSlot()
    def edit(self):
        ixs = self.sql_list_view.selectionModel().selectedIndexes()
        if ixs:
            d = EditMacroDialog(self.model, ixs[0].row())
            d.exec_()

    @QtCore.pyqtSlot()
    def remove(self):
        ixs = self.sql_list_view.selectionModel().selectedIndexes()
        if ixs:
            self.model.removeRow(ixs[0].row())
            self.model.select()

    @QtCore.pyqtSlot()
    def onSelectionChanged(self):
        state = bool(self.sql_list_view.selectionModel().selectedIndexes())
        self.edit_button.setEnabled(state)
        self.remove_button.setEnabled(state)


if __name__ == "__main__":
    import sys

    database = "entry name"  # ":memory:"
    app = QtWidgets.QApplication(sys.argv)
    if not create_connection(database):
        sys.exit(app.exec_())
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...