Russian Qt Forum
Октябрь 01, 2024, 12:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QComboBox + mapper сохраняет в таблицу индекс записи вместо значения из записи.  (Прочитано 12303 раз)
Пытон
Гость
« : Февраль 10, 2013, 11:29 »

Код
Python
from PyQt4 import QtGui,  QtSql,  QtCore
import os.path
 
class window1(QtGui.QWidget):
   def __init__(self,  titletext):
       QtGui.QWidget.__init__(self)
       self.resize(800,  600)
       self.setWindowTitle(titletext)
 
       self.OpenOrCreateDB() #подключаемся к БД или создаём новую БД
 
       self.layout1 = QtGui.QVBoxLayout() # создаём контейнер для расположения в нём других виджетов
       self.setLayout(self.layout1) # назначаем его основным для нашей формы (окна)
 
       self.model1 = QtSql.QSqlTableModel(None,  self.DB) #создаём модель для хранения строк из БД, указываем с какой БД ей работать
       self.model1.setTable("table1") # указываем нужную таблицу из БД
       self.model1.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit) # данные сохраняются в БД посредством этой модели, только по команде
       self.model1.select() # запускаем комаду select, для выборки всех записей из указанной таблицы БД
       self.tableView1 = QtGui.QTableView() # создаём грид (таблицу для отображения данных из модели) для формы
       self.tableView1.setModel(self.model1) # указываем гриду из какой модели брать данные для отображения
       self.tableView1.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) #таким зашибенным способом запрещается редактирование ячеек пользователем
       self.layout1.addWidget(self.tableView1)
 
       self.btnNew = QtGui.QPushButton("Добавить новую строку в БД") #создаём кнопку
       self.btnNew.clicked.connect(self.btnNewClicked) # связываем событие нажатия на кнопку с обработчиком для этого события
       self.layout1.addWidget(self.btnNew) # добавляем её в контейнер на форме
 
       self.btnEdit = QtGui.QPushButton("Редактировать текущую строку БД")
       self.btnEdit.clicked.connect(self.btnEditClicked)
       self.layout1.addWidget(self.btnEdit)
 
   def btnNewClicked(self):
       self.OpenEditWindow("NEW")
 
   def btnEditClicked(self):
       self.OpenEditWindow("EDIT")
 
   def OpenEditWindow(self, NewOrEdit):
       secondwindow = window2(NewOrEdit,  self.tableView1.currentIndex().row())
       result = secondwindow.exec() # если здесь использовать show, то окно не будет модальным! Т.е. из него можно будет спокойно перейти в другое окно.
       print (result)
 
   def OpenOrCreateDB(self):
       #создаём объект для работы с БД
       self.DB = QtSql.QSqlDatabase.addDatabase("QSQLITE", "Base")
       self.DB.setDatabaseName("./SQLiteBase/Lesson16DB.db")
 
       existDB = os.path.exists("./SQLiteBase/Lesson16DB.db")  #проверяем физичиское наличие БД
       if not existDB: print ("БД не существует. Попытка создать новую БД...")
 
       if not self.DB.open(): #попытка открыть БД (она же создание новой БД, если файла БД не существует)
           print("БД не открылась! Ошибка:",  self.DB.lastError().text())
       else: #подключение к БД произошло. Если при этом была создана новая БД, нужно создать в ней таблицы
           if not existDB: self.CreateStructureOfNewDB()
 
   def CreateStructureOfNewDB(self):
       query = QtSql.QSqlQuery(self.DB)
       querytext = ("CREATE TABLE table1 ("
                                          "id INTEGER, "
                                          "fam VARCHAR(20), "
                                          "im VARCHAR(20), "
                                          "ot VARCHAR(20), "
                                          "dr DATE, "
                                          "pol VARCHAR(1), "
                                          "gorod VARCHAR(20)"
                                          ")")
       #print (querytext)
       errors = 0
       tmp = query.exec(querytext)
       if not tmp:
           errors = errors + 1
 
       querytext = ("CREATE TABLE spisok1 ("
                    "id INTEGER, "
                    "text VARCHAR(20)"
                    ")")
 
       tmp = query.exec(querytext)
       if not tmp:
           errors = errors + 1
 
       return tmp
       if errors > 1:
           print ("БД не создана! Ошибка: ",  self.DB.lastError().text())
           return False
       else: return True
 
class window2(QtGui.QDialog): # создаём окно типа Диалог
   def __init__(self,  NewOrEdit,  currentIndex_):
       QtGui.QDialog.__init__(self)
 
       self.mapper = QtGui.QDataWidgetMapper() #маппер для связки данных из модели с контролами
       self.mapper.setModel(windowmain.model1) #связываем его с моделью данных из объекта windowmain
       self.mapper.setSubmitPolicy(QtGui.QDataWidgetMapper.ManualSubmit) #обновление данных в модели будет произведено только по команде
 
       tmpstr = NewOrEdit
       if NewOrEdit == "NEW":
           tmpstr = "Добавление новой записи в БД"
           Record = windowmain.model1.record() #создаём объект типа рекорд для добавления строки в модель
           windowmain.model1.insertRecord(-1,  Record) #insertRow использовать не стоит! Он не поддерживает связанные таблицы!
           self.mapper.toLast() #маппер тоже передвигаем к последней записи!
       elif NewOrEdit == "EDIT":
           tmpstr = "Редактирование записи"
       self.setWindowTitle(tmpstr)
       #self.setWindowModality(QtCore.Qt.WindowModal)
 
       self.layout2 = QtGui.QHBoxLayout()
       self.layout2_1 = QtGui.QVBoxLayout()
       self.layout2.addLayout(self.layout2_1)
       self.layout2_2 = QtGui.QVBoxLayout()
       self.layout2.addLayout(self.layout2_2)
       self.layout2_3 = QtGui.QHBoxLayout()
       self.layout2.addLayout(self.layout2_3)
       self.setLayout(self.layout2)
 
 
       Alignment = QtCore.Qt.AlignTop
 
       self.id_label = QtGui.QLabel("Номер")
       self.id_ = QtGui.QLineEdit()
       self.layout2_1.addWidget(self.id_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.id_,  alignment = Alignment)
       self.mapper.addMapping(self.id_,  windowmain.model1.fieldIndex("id")) #связываем контрол id_ с полем id из маппера, который передаст значение в модель, которая передаст в БД (вот такие тут все передасты!)
 
       self.fam_label = QtGui.QLabel("Фамилия")
       self.fam_ = QtGui.QLineEdit()
       self.layout2_1.addWidget(self.fam_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.fam_,  alignment = Alignment)
       self.mapper.addMapping(self.fam_,  windowmain.model1.fieldIndex("fam"))
 
       self.im_label = QtGui.QLabel("Имя")
       self.im_ = QtGui.QLineEdit()
       self.layout2_1.addWidget(self.im_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.im_,  alignment = Alignment)
       self.mapper.addMapping(self.im_,  windowmain.model1.fieldIndex("im"))
 
       self.ot_label = QtGui.QLabel("Отчество")
       self.ot_ = QtGui.QLineEdit()
       self.layout2_1.addWidget(self.ot_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.ot_,  alignment = Alignment)
       self.mapper.addMapping(self.ot_,  windowmain.model1.fieldIndex("ot"))
 
       self.dr_label = QtGui.QLabel("Дата рождения")
       self.dr_ = QtGui.QLineEdit()
       self.layout2_1.addWidget(self.dr_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.dr_,  alignment = Alignment)
       self.mapper.addMapping(self.dr_,  windowmain.model1.fieldIndex("dr"))
 
       self.pol_label = QtGui.QLabel("Пол")
       self.pol_ = QtGui.QLineEdit()
       self.layout2_1.addWidget(self.pol_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.pol_,  alignment = Alignment)
       self.mapper.addMapping(self.pol_,  windowmain.model1.fieldIndex("pol"))
 
       self.gorod_label = QtGui.QLabel("Город")
       self.gorod_ = QtGui.QComboBox()
       #создаём модель для комбобокса
       self.gorodModel = QtSql.QSqlTableModel(None,  windowmain.DB)
       self.gorodModel.setTable("spisok1")
       self.gorodModel.select()
       self.gorod_.setModel(self.gorodModel)
       self.gorod_.setModelColumn(1)
       self.layout2_1.addWidget(self.gorod_label,  alignment = Alignment)
       self.layout2_2.addWidget(self.gorod_,  alignment = Alignment)
       self.mapper.addMapping(self.gorod_,  windowmain.model1.fieldIndex("gorod"))
 
       self.btnSave = QtGui.QPushButton("Запомнить")
       self.btnSave.clicked.connect(self.SaveData)
       self.layout2_3.addWidget(self.btnSave,  alignment = QtCore.Qt.AlignRight)
 
 
       self.btnCancel = QtGui.QPushButton("Отменить")
       self.btnCancel.clicked.connect(self.Cancel)
       self.layout2_3.addWidget(self.btnCancel,  alignment = QtCore.Qt.AlignRight)
 
       if NewOrEdit == "EDIT":
           self.mapper.setCurrentIndex(currentIndex_) # Этот способ выбора текущей строки из модели нужно проерить. Что будет, если данные в модели будут отсортированы?
 
   def SaveData(self):
       self.mapper.submit() #сохраняем изменения в модели
       windowmain.model1.submitAll() # а теперь сохраняем изменения из модели в БД
       self.close()
 
   def Cancel(self):
       windowmain.model1.revertAll() #отменяем изменения в модели. Иначе вновь добавленная строка останется.
       self.close() #закрываем окно
 
if __name__ == "__main__":
   import sys
   app = QtGui.QApplication(sys.argv)
   windowmain = window1("Первое окно")
   windowmain.show()
   sys.exit(app.exec_())
 
 

Смотрим на строку self.mapper.addMapping(self.gorod_, windowmain.model1.fieldIndex("gorod"))

Как указать мапперу, что в поле gorod таблицы table1 нужно записать значение поля text из таблицы spisok1? Чего он мне туда индекс записывает?

Я не использую реляционную модель!
Записан
Пытон
Гость
« Ответ #1 : Февраль 10, 2013, 16:07 »

Ну тут же явно нужно как-то указать, что комбобокс должен возвратить значение из своего списка, а не его индекс. Ну как это сделать-то?
Записан
Пытон
Гость
« Ответ #2 : Февраль 24, 2013, 11:42 »

Ненавижу QT. Ничего непонятно и никто помочь не может.
Записан
Bepec
Гость
« Ответ #3 : Февраль 24, 2013, 13:15 »

А ты поменьше такими словами кидайся Веселый

Связка Qt + python не очень популярна на данный момент.

Я не могу сказать практически ничего, изза незнания синтаксиса и способа испльзования pyQt, но на мой взгляд у вас всё усложнено. Особенно передасты Веселый
Записан
Пытон
Гость
« Ответ #4 : Февраль 24, 2013, 17:58 »

Связка Qt + C++ тоже не распространена?
Мне и помощь нарисованная в коде для С++ подойдёт. Уж как-нибудь я её перенесу в питон (алгоритм-то весь тот же), тем более, что на питоне писать проще из-за отсутствия лишних точек-запятучек-закорючек-скобочек-стрелочек и предварительных объявлений типов данных.

Если мой пример на питоне не понятен, то объясню то, что мне надо просто словами:
Имеется таблица (НЕ связанная ни с какой другой, первичных ключей не имеет). Имеется модель для этой таблицы. Имеется маппер, который работает с этой моделью. Нужно: чтобы этот чёртов маппер брал данные из второй таблицы и сохранял их в первую. И чтобы сохранял он не индекс записи, не первичный ключ, а именно текстовые данные из второй таблицы. Т.е. в первой таблице должен храниться не ключ, а одно из слов из второй таблицы.

Первая таблица:
fam          im         ot                  gorod
хрюкин   хрюка   хрюкович     бердск - в этом поле храним ТЕКСТ, никакой не ключ!

вторая таблица:
gorod
бердск - вот прямо это значение и записываем в поле gorod первой таблицы
братск
салатск
урюпинск
Записан
Bepec
Гость
« Ответ #5 : Февраль 24, 2013, 19:48 »

Попытаюсь посмотреть завтра, если будет свободное время на работе ( Веселый ).

 
Записан
panAlexey
Гипер активный житель
*****
Offline Offline

Сообщений: 864

Акцио ЗАРПЛАТА!!!!! :(


Просмотр профиля
« Ответ #6 : Февраль 25, 2013, 11:28 »

Ненавижу QT. Ничего непонятно и никто помочь не может.
Ты не на Qt лабаешь, а на купитоне.
Qt без прослоек весьма съедобна.
Записан

Win Xp SP-2, Qt4.3.4/MinGW. http://trdm.1gb.ru/
Bepec
Гость
« Ответ #7 : Февраль 25, 2013, 17:47 »

Времени на работе не було к сожалению. Понял в принципе ваш код, попытаюсь воссоздать на плюсах.
Записан
Пытон
Гость
« Ответ #8 : Февраль 25, 2013, 18:49 »

Ненавижу QT. Ничего непонятно и никто помочь не может.
Ты не на Qt лабаешь, а на купитоне.
Qt без прослоек весьма съедобна.


Я в курсе на чём я лабаю. С прослойками, без прослоек ли, а виджеты и объекты Qt одни и те же вне зависимости от прослоек. Что писал бы я на С++, что пишу сейчас на питоне - одинаково непонятно как заставить маппер делать то, что мне нужно.

Или от прослоек у виджетов и объектов Qt вдруг изменяются свойства, методы, сигналы, слоты и т.д?
Записан
panAlexey
Гипер активный житель
*****
Offline Offline

Сообщений: 864

Акцио ЗАРПЛАТА!!!!! :(


Просмотр профиля
« Ответ #9 : Февраль 25, 2013, 18:58 »

Я в курсе на чём я лабаю. С прослойками, без прослоек ли, а виджеты и объекты Qt одни и те же вне зависимости от прослоек.
Не одни и те же а бинденные. Т.е. с налетиком...
Записан

Win Xp SP-2, Qt4.3.4/MinGW. http://trdm.1gb.ru/
Bepec
Гость
« Ответ #10 : Февраль 25, 2013, 19:03 »

update:

У вас уникальное стечение обстоятельств, что хоть что-то работает Улыбающийся

У вас комбобокс изменяется при хождении по записям? У меня лично нет (хотя мб это фишка пикуте).

Стандартное значение комбобокса - индекс. Вот его он туда и записывает. Чтобы записывал текст, необходимо написать вот так
Код:
mapper_->addMapping(ui.comboBox, 2, "currentText");
или если на пикуте, если я не ошибаюсь, вот так
Код:
self.mapper.addMapping(self.gorod_,  windowmain.model1.fieldIndex("gorod"), "currentText")

Единственно что, у меня при таком раскладе не отображается текст при хождении через маппер (пропертя только для чтения, он не может её установить). Но, думаю, это вполне обходится, если отнаследоваться от комбобокса и чуточку изменить его проперти (сомнения есть, что это возможно, не пробовал).

PS Искреннее спасибо вам за тему. Этот компонент мной был не охвачен, но ОЧЕНЬ ОЧЕНЬ нужен в ближайшее время Веселый Теперь во всеоружии Веселый
Записан
Пытон
Гость
« Ответ #11 : Февраль 26, 2013, 18:54 »

Ткните мне, пожалуйста, нерадивому пальцем, и хде вы нашли этот самый "currentText"?
В qt ассистенте я такого не видел. Где это можно увидеть, чтобы я не лазил по форумам и сайтам?
currentText - это, получается, свойство самого комбобокса.
Записан
Пытон
Гость
« Ответ #12 : Февраль 26, 2013, 18:57 »

update:

У вас уникальное стечение обстоятельств, что хоть что-то работает Улыбающийся

PS Искреннее спасибо вам за тему. Этот компонент мной был не охвачен, но ОЧЕНЬ ОЧЕНЬ нужен в ближайшее время Веселый Теперь во всеоружии Веселый

Бесконечно рад, что смог доставить вам удовольствие в возможности поупражняться в сарказме. Это было целью всей моей жизни до сего момента. Теперь не знаю, что и делать, как дальше жить... Подмигивающий

П.С. За потраченное на меня время конечно же спасибо.
Записан
Пытон
Гость
« Ответ #13 : Февраль 26, 2013, 19:05 »

update:

так
Код:
mapper_->addMapping(ui.comboBox, 2, "currentText");
или если на пикуте, если я не ошибаюсь, вот так
Код:
self.mapper.addMapping(self.gorod_,  windowmain.model1.fieldIndex("gorod"), "currentText")
На PyQt можно написать практически также как в вашем варианте для C++. Просто я не использовал конструктор форм, и вместо прямого указания индекса поля, велел PyQt определять индекс поля по его имени.

П.С. self'ы меня тоже раздражают, но ещё больше раздражает синтаксис С++ с его фигурными скобками, стрелочками, двойными двоеточиями и командами типа: типобъекта имяобъекта = новый типобъекта (указано ж заразе один раз, какой тип у объекта, нафига после new снова его указывать?)
Записан
Пытон
Гость
« Ответ #14 : Февраль 26, 2013, 19:17 »

А можно вопрос не по теме?
Почему для model = SqlRelationalTableModel не срабатывает model.insertRecord(Record), где Record = model.record()?

При этом в БД появляется новая запись (это видно через сторонний просмотрщик SQLite и даже новое значение первичного ключа генерируется), заполненная null, но эта запись не отображается во view связанной с model!

Кто-нибудь вообще использует SqlRelationalTableModel или все дружно используют для работы с БД исключительно SQL-запросы?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.114 секунд. Запросов: 23.