テーブルデータの編集ができるようにする
前回までに、QTableViewにデータを表示するところまではできました。
しかし、現状はテーブル内のデータを編集することができません。今回の目標として、 テーブルからデータの値を編集できるようになる ことを目指します。
CustomDataの編集
カスタムデータクラスを少し編集して、データをセットできるような関数を作ります。
今回のCustomDataはdataclassになっていますので、単純にメンバ変数に代入するだけで良いのですが、「与えられた値をバリデートし、正しければ代入する」ということをやりたかったので、このクラスを以下のように改造しました。
@dataclasses.dataclass
class CustomData:
name: str
age: int
country: str
def toList(self) -> list:
return [self.name, self.age, self.country]
@classmethod
def toHeaderList(cls) -> List[str]:
return ["NAME", "AGE", "COUNTRY"]
def validateAndSetName(self, name) -> bool:
if str(name) != "": # Non-empty string is OK.
self.name = str(name)
return True
return False
def validateAndSetAge(self, age) -> bool:
try:
val_int = int(age)
if val_int >= 0: # int, and greater than 0 or equal 0 is OK.
self.age = val_int
return True
except ValueError:
pass # Non-integer value is invalid.
return False
def validateAndSetCountry(self, country) -> bool:
if str(country) in ["USA", "Japan", "US", "Russia", "Canada"]: # Only 5 countries
self.country = str(country)
return True
return False
前回から増えているところは、
validateAndSetName(...)
- 空文字でなければOK
validateAndSetAge(...)
- 0以上のint(整数)であればOK
validateAndSetCountry(...)
- "USA", "Japan", "US", "Russia", "Canada"のいずれかであればOK
の3つの関数です。バリデーターが「正常な値」と判断する基準は、関数名の下に記したとおりです。
SimpleTableModelの編集
さて、ここからはいよいよモデルの編集を行っていきます。
追加するメソッド
今回追加するメソッドは次の2つです。
setData(self, index: QModelIndex, value, role: int) -> bool
flags(self, index: QModelIndex) -> Qt.ItemFlags
setData(self, index: QModelIndex, value, role: int) -> bool
この関数は、QTableViewの編集状態が終了したタイミングで呼び出されます。「index
で指定された項目の、role
に対する値をvalue
に更新するよ」という感じです。
今回は、role
はQt.EditRole
というロールにのみ対応します。
また、与えられた値valueが受理できないような値の場合は、関数の戻り値としてFalse
を返すと、変更が破棄され、変更前の状態に戻ります。よって、バリデータにかけて、失敗した場合はFalse
を返し、テーブル上の値をもとに戻すようにしています。
def setData(self, index: QModelIndex, value, role: int) -> bool:
# Returning true means the value was accepted.
if index.isValid() and role == Qt.EditRole:
if index.column() == 0:
return self.custom_data[index.row()].validateAndSetName(value)
elif index.column() == 1:
return self.custom_data[index.row()].validateAndSetAge(value)
elif index.column() == 2:
return self.custom_data[index.row()].validateAndSetCountry(value)
return False # Not Accepted.
flags(self, index: QModelIndex) -> Qt.ItemFlags
この関数は、指定されたindexの要素に対する、フラグを宣言できます。フラグとは具体的に、「選択可能」や、「要素が有効である」「編集可能である」といったものです。立てるフラグが複数ある場合は、それらをビットOR演算子である|
で繋げて値を戻します。
今回は、「要素が有効」「選択可能」「編集可能」の3つのフラグを立てます。
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
if index.isValid():
return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
return Qt.NoItemFlags
完成
実際に動かしてみましょう。
セルをダブルクリックすることで編集ができるようになります。
年齢の欄も、同じように編集できますが
年齢の欄に文字列を入れてEnterを押すと、変更は反映されずに50歳のままとなります。
国の欄に「MyCountry」と指定しても、これらは有効な「国」として登録されていないため、Enterを押すことで元の「Japan」に戻されます。
全コード
次回
この表に、次は要素の追加と削除を実装したいと思います。