2017-09-19 14 views
1

私はPysideを使用して、sqliteデータベースから描画するコンボボックスを作成しています。ユーザーは既存のアイテムの1つを選択したり、新しいアイテムを追加することができます。ユーザーはアイテム名(「param」と呼ばれます)を表示しますが、データベースからアイテムIDにアクセスする必要があります。したがって、2つのステップがあります:編集可能な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を使用する必要があります。これは読み取り専用です。次に、コンボボックスにヘッダーやビューを設定する必要はありません。第3に、適切な値を表示するには、コンボボックスに正しいモデル列を設定する必要があります。

項目を追加する際は、変更をモデルから送信するだけで済みます。ただし、追加されたアイテムの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:ここでは、現在のインデックスを使用して、コンボボックスからidを取得する方法は次のとおりです。

model = self.combo.model() 
index = self.combo.currentIndex() 
ID = model.index(index, model.fieldIndex('id')).data() 
+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

関連する問題