2017-09-19 26 views
1

저는 Pyside를 사용하여 sqlite 데이터베이스에서 가져온 콤보 박스를 만듭니다. 사용자는 기존 항목 중 하나를 선택하거나 새 항목을 추가 할 수 있습니다. 사용자는 항목 이름 ("param")을 볼 수 있지만 데이터베이스에서 항목 ID에 액세스해야합니다. 따라서 두 단계가 있습니다.편집 가능한 QComboBox를 데이터베이스에 연결하는 방법

독서 환경 : 데이터베이스에서 읽을 수는 있지만 항목 뒤에는 항목 ID를 액세스하는 동안 항목 이름을 표시 할 수 없습니다.

항목 추가 : 콤보 상자의 변경 사항을 감지 한 다음 SQL 삽입 명령을 사용해야합니까? 아니면 모델이이 문제를 해결합니까?

이 코드는 데이터베이스에서 읽고 있지만 제대로 표시되지 않습니다

param_model = QSqlQueryModel() 
param_model.setQuery("select id, param from partable order by param") 
param_model.setHeaderData(0, Qt.Horizontal,"id") 
param_model.setHeaderData(1, Qt.Horizontal,"param") 

param_view = QTableView() 
param_view.setColumnHidden(0,True) 

self.paramfield = QComboBox() 
self.paramfield.adjustSize() 
self.paramfield.setEditable(True) 
self.paramfield.setModel(param_model) 
self.paramfield.setView(param_view) 

답변

1

이 코드와 몇 가지 문제가 있습니다. 첫째, 읽기 전용 인 QSqlQueryModel이 아닌 QSqlTableModel을 편집 할 수 있어야합니다. 두 번째로, 헤더 또는 콤보 상자에 대한보기를 설정할 필요가 없습니다. 세 번째로 적절한 값을 표시하려면 콤보 상자에 올바른 모델 열을 설정해야합니다.

항목 추가에 대한 질문 : 모델을 통해 변경 사항을 제출하기 만하면됩니다. 그러나 (예 : 현재 색인을 재설정하기 위해) 추가 된 항목의 ID 또는 색인을 찾는 것이 좋습니다. 모델을 정렬하거나 중복 항목을 허용하는 경우 약간 힘들 수 있습니다.

import sys 
from PySide import QtCore, QtGui, QtSql 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE') 
     self.db.setDatabaseName(':memory:') 
     self.db.open() 
     self.db.transaction() 
     self.db.exec_(
      'CREATE TABLE partable' 
      '(id INTEGER PRIMARY KEY, param TEXT NOT NULL)' 
      ) 
     self.db.exec_("INSERT INTO partable VALUES(1, 'Red')") 
     self.db.exec_("INSERT INTO partable VALUES(2, 'Blue')") 
     self.db.exec_("INSERT INTO partable VALUES(3, 'Green')") 
     self.db.exec_("INSERT INTO partable VALUES(4, 'Yellow')") 
     self.db.commit() 
     model = QtSql.QSqlTableModel(self) 
     model.setTable('partable') 
     column = model.fieldIndex('param') 
     model.setSort(column, QtCore.Qt.AscendingOrder) 
     model.select() 
     self.combo = QtGui.QComboBox(self) 
     self.combo.setEditable(True) 
     self.combo.setModel(model) 
     self.combo.setModelColumn(column) 
     self.combo.lineEdit().returnPressed.connect(self.handleComboEdit) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.combo) 

    def handleComboEdit(self): 
     if self.combo.lineEdit().isModified(): 
      model = self.combo.model() 
      model.submitAll() 
      ID = model.query().lastInsertId() 
      if ID is not None: 
       index = model.match(
        model.index(0, model.fieldIndex('id')), 
        QtCore.Qt.EditRole, ID, 1, QtCore.Qt.MatchExactly)[0] 
       self.combo.setCurrentIndex(index.row()) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(800, 50, 200, 50) 
    window.show() 
    sys.exit(app.exec_()) 

PS :

model = self.combo.model() 
index = self.combo.currentIndex() 
ID = model.index(index, model.fieldIndex('id')).data() 
: 여기에 현재 인덱스를 사용하여 콤보 상자에서 id을 얻을하는 방법

아래의 데모 스크립트는 어떻게 위에서 언급 한 모든 문제를 처리하는 방법을 보여줍니다

+0

이 설명과 예제에 감사드립니다. 내 코드를 조정하고 작동하는 경우 다시보고합니다. – davideps

+0

코드가 아름답게 작동합니다. 제안에 따라 코드를 조정하면 새 콤보 상자 항목이 NULL ID가있는 데이터베이스에 추가되고이 오류가 발생합니다. "handleComboEdit Qt.EditRole, ID, 1, Qt.MatchExactly) [0] IndexError : list index 범위를 벗어났습니다. " 그러나 "ID = model.query(). lastInsertId()"의 결과는 정수입니다. 그래서 아직 작동하지 않을 가능성이있는 model.match입니다. 곧 다시보고 드리겠습니다. – davideps

+0

사실, 문제는 제가 sqlite 테이블을 잘못 정의하고있는 것 같습니다. "ID INT PRIMARY KEY"는 올바르게 보이지만 올바르게 작동하지 않는 테이블을 생성합니다. "id INTEGER PRIMARY KEY"는 올바르게 작동합니다. 고맙습니다! – davideps