Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Разработка GUI > PyQt5 проблемы


Автор: kapbepucm 3.3.2017, 13:23
Добрый день! У меня возникла проблема с переводом кода с pyqt4 на pyqt5. Беру стандартный пример "sqlwidgetmapper" из документации Qt (код при переводе из C++ слегка модифицирован). Вот мой код:
Код
import sys

from PyQt5.QtWidgets import *
from PyQt5.QtSql import *
from PyQt5.QtCore import *

#from PyQt4.QtGui import *
#from PyQt4.QtSql import *
#from PyQt4.QtCore import *

class Window(QWidget):
  def __init__(self, parent):
    super(Window, self).__init__(parent)

    self.setupModel()

    nameLabel = QLabel("Na&me:")
    nameEdit = QLineEdit()
    addressLabel = QLabel("&Address:")
    addressEdit = QTextEdit()
    typeLabel = QLabel("&Type:")
    typeComboBox = QComboBox()
    self.nextButton = QPushButton("&Next")
    self.previousButton = QPushButton("&Previous")

    nameLabel.setBuddy(nameEdit)
    addressLabel.setBuddy(addressEdit)
    typeLabel.setBuddy(typeComboBox)

    relModel = self.model.relationModel(self.typeIndex)
    typeComboBox.setModel(relModel)
    typeComboBox.setModelColumn(relModel.fieldIndex("description"))

    mapper = QDataWidgetMapper(self)
    mapper.setModel(self.model)
    mapper.setItemDelegate(QSqlRelationalDelegate(self))
    mapper.addMapping(nameEdit, self.model.fieldIndex("name"))
    mapper.addMapping(addressEdit, self.model.fieldIndex("address"))
    mapper.addMapping(typeComboBox, self.typeIndex)

    self.previousButton.clicked.connect(mapper.toPrevious)
    self.nextButton.clicked.connect(mapper.toNext)
    mapper.currentIndexChanged.connect(self.updateButtons)

    layout = QGridLayout(self)
    layout.addWidget(nameLabel, 0, 0, 1, 1)
    layout.addWidget(nameEdit, 0, 1, 1, 1)
    layout.addWidget(self.previousButton, 0, 2, 1, 1)
    layout.addWidget(addressLabel, 1, 0, 1, 1)
    layout.addWidget(addressEdit, 1, 1, 2, 1)
    layout.addWidget(self.nextButton, 1, 2, 1, 1)
    layout.addWidget(typeLabel, 3, 0, 1, 1)
    layout.addWidget(typeComboBox, 3, 1, 1, 1)

    mapper.toFirst()
#-------------------------------------------------------------------------
  def setupModel(self):
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(":memory:")
    db.open()

    query = QSqlQuery()
    query.exec_("create table person (id int primary key, name varchar(10), address varchar(10), typeid int)")
    query.exec_("insert into person values(1, 'Name1', 'address1', 101)")
    query.exec_("insert into person values(2, 'Name2', 'address2', 102)")
    query.exec_("insert into person values(3, 'Name3', 'address3', 103)")
    query.exec_("insert into person values(4, 'Name4', 'address4', 104)")
    query.exec_("insert into person values(5, 'Name5', 'address5', 105)")

    query.exec_("create table addresstype (id int, description varchar(10))")
    query.exec_("insert into addresstype values(101, 'Type 1')")
    query.exec_("insert into addresstype values(102, 'Type 2')")
    query.exec_("insert into addresstype values(103, 'Type 3')")
    query.exec_("insert into addresstype values(104, 'Type 4')")
    query.exec_("insert into addresstype values(105, 'Type 5')")

    self.model = QSqlRelationalTableModel(self)
    self.model.setTable("person")
    self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)

    self.typeIndex = self.model.fieldIndex("typeid")

    self.model.setRelation(self.typeIndex,QSqlRelation("addresstype", "id", "description"))
    self.model.select()
#-------------------------------------------------------------------------
  def updateButtons(self, row):
    self.previousButton.setEnabled(row > 0)
    self.nextButton.setEnabled(row < self.model.rowCount() - 1)
#-------------------------------------------------------------------------
app = QApplication(sys.argv)
app.setStyle("GTK+")

MainWindow = Window(None)
MainWindow.show()

sys.exit(app.exec_())
Проблема возникает после запуска. Приведу 2 примера неадекватного поведения:
алгоритм первого примера
1. запускаем скрипт
2. кликаем 4 раза "Next" (до конца таблицы)
3. кликаем 1 раз "Previous" (1 шаг вверх)
4. кликаем 1 раз "Next" (опять до конца таблицы)
в данном случае наблюдаю, что Type магическим образом меняется с "Type 5" на "Type 4"

алгоритм второго примера
1. запускаем скрипт
2. меняем "Type 1" на "Type 5"
3. кликаем 1 раз "Next"
4. кликаем 1 раз "Previous"
в данном случае наблюдаю, что Type магическим образом меняется с "Type 5" на "Type 2"

если использовать pyqt4 вместо pyqt5, разкоментировав в моем коде секцию импорта, то всё работает логично.

Автор: kapbepucm 3.3.2017, 14:06
Весии Qt 5.3.2 и 4.8.6

Автор: kapbepucm 6.3.2017, 10:41
Прошу модов (если есть, кто живой) удалить эту тему. Насколько я понял, к python это мало относится. Видимо, проблема в глючной работе QDataWidgetMapper.

Проверил на Qt 5.8.0- глючит аналогично

Автор: макс12345 18.2.2018, 21:38
алгоритм второго примера
1. запускаем скрипт
2. меняем "Type 1" на "Type 5"
3. кликаем 1 раз "Next"
4. кликаем 1 раз "Previous"
в данном случае наблюдаю, что Type магическим образом меняется с "Type 5" на "Type 2"    http://dolan.info

Автор: kapbepucm 22.2.2018, 10:07
На самом деле разгадка проста. После изменения значения typeComboBox в поле int "person.typeid" пишется значение типа varchar из поля "addresstype.description" вместо, как это реализовано в qt4, значения int "addresstype.id". Причём движок sqlite это позволяет делать. Тему не удаляйте, вдруг кому пригодится smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)