代码:
# todict
# https://github.com/SiggiGue/qdictionarytree
# 本文
# https://www.learnpyqt.com/courses/model-views/modelview-architecture/
import sys
import json
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtCore import *
import sys
import sys
from PyQt5.QtWidgets import QWidget, QToolTip, QApplication
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
# There is interesting way
# no need to compile...
# I am wondering if this works to exe file..since it's make file less
tick = QtGui.QImage('tick2.png')
class TodoModel(QtCore.QAbstractListModel):
def __init__(self, *args, todos=None, **kwargs):
super(TodoModel, self).__init__(*args, **kwargs)
self.todos = todos or []
def data(self, index, role):
if role == Qt.DisplayRole:
_, text = self.todos[index.row()]
return text
if role == Qt.DecorationRole:
status, _ = self.todos[index.row()]
if status:
return tick
def rowCount(self, index):
return len(self.todos)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setObjectName("MainWindow")
self.resize(461, 476)
self.centralwidget = QtWidgets.QWidget(self)
self.top_layout = QVBoxLayout()
self.centralwidget.setLayout(self.top_layout)
self.completeButton = QtWidgets.QPushButton("Complete")
self.deleteButton = QtWidgets.QPushButton("Delete")
self.addButton = QtWidgets.QPushButton("Add Todo")
self.todoEdit = QtWidgets.QLineEdit()
self.todoView = QtWidgets.QListView()
self.top_layout.addWidget(self.todoView)
self.mid_layout = QHBoxLayout()
self.mid_layout.addWidget(self.completeButton)
self.mid_layout.addWidget(self.deleteButton)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.todoEdit)
self.top_layout.addWidget(self.addButton)
self.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(self)
self.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(self)
self.setStatusBar(self.statusbar)
self.setWindowTitle("Todo")
self.model = TodoModel()
self.load()
self.todoView.setModel(self.model)
self.addButton.pressed.connect(self.add)
self.deleteButton.pressed.connect(self.delete)
self.completeButton.pressed.connect(self.complete)
def add(self):
"""
Add an item to our todo list, getting the text from the QLineEdit .todoEdit
and then clearing it.
"""
text = self.todoEdit.text()
if text: # Don't add empty strings.
# Access the list via the model.
self.model.todos.append((False, text))
# Trigger refresh.
self.model.layoutChanged.emit()
# Empty the input
self.todoEdit.setText("")
self.save()
def delete(self):
# use .selectedIndexes to get index, which is a list with one elt
indexes = self.todoView.selectedIndexes()
if indexes:
# Indexes is a list of a single item in single-select mode.
index = indexes[0]
# Remove the item and refresh.
del self.model.todos[index.row()]
self.model.layoutChanged.emit()
# Clear the selection (as it is no longer valid).
self.todoView.clearSelection()
self.save()
def complete(self):
indexes = self.todoView.selectedIndexes()
if indexes:
index = indexes[0]
row = index.row()
status, text = self.model.todos[row]
self.model.todos[row] = (True, text)
# .dataChanged takes top-left and bottom right, which are equal
# for a single selection.
self.model.dataChanged.emit(index, index)
# Clear the selection (as it is no longer valid).
self.todoView.clearSelection()
self.save()
# how you persist the data
def load(self):
try:
with open('data.json', 'r') as f:
self.model.todos = json.load(f)
except Exception:
pass
def save(self):
with open('data.json', 'w') as f:
data = json.dump(self.model.todos, f)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
tick2.png 图形
data.json 的 内容为:
[[true, "aa"], [true, "bb"], [false, "cc"]]
演示效果:
class TodoModel(QtCore.QAbstractListModel):
里面的def data(self, index, role): 函数