本文通过将同一个数据集在三种不同的简便项窗口部件中显示。三个窗口的数据得到实时的同步,数据和视图分离。当添加或删除数据行,三个不同的视图均保持同步。数据将保存在本地文件中,而非数据库。对于小型和临时性数据集来说,这些简便窗口部件非常有用,可以用在非单独数据集中-数据自身的显示,编辑和存储。
所使用的数据集:
/home/yrd/eric_workspace/chap14/ships_conv/ships.py
#!/usr/bin/env python3
import platform
from PyQt5.QtCore import QDataStream, QFile,QIODevice,Qt
from PyQt5.QtWidgets import QApplication
NAME, OWNER, COUNTRY, DESCRIPTION, TEU = range(5)
MAGIC_NUMBER = 0x570C4
FILE_VERSION = 1
class Ship(object):
def __init__(self, name, owner, country, teu=0, description=""):
self.name = name
self.owner = owner
self.country = country
self.teu = teu
self.description = description
def __hash__(self):
return super(Ship, self).__hash__()
def __lt__(self, other):
return bool(self.name.lower()<other.name.lower())
def __eq__(self, other):
return bool(self.name.lower()==other.name.lower())
class ShipContainer(object):
def __init__(self, filename=""):
self.filename = filename
self.dirty = False
self.ships = {}
self.owners = set()
self.countries = set()
def ship(self, identity):
return self.ships.get(identity)
def addShip(self, ship):
self.ships[id(ship)] = ship
self.owners.add(str(ship.owner))
self.countries.add(str(ship.country))
self.dirty = True
def removeShip(self, ship):
del self.ships[id(ship)]
del ship
self.dirty = True
def __len__(self):
return len(self.ships)
def __iter__(self):
for ship in self.ships.values():
yield ship
def inOrder(self):
return sorted(self.ships.values())
def inCountryOwnerOrder(self):
return sorted(self.ships.values(),
key=lambda x: (x.country, x.owner, x.name))
def load(self):
exception = None
fh = None
try:
if not self.filename:
raise IOError("no filename specified for loading")
fh = QFile(self.filename)
if not fh.open(QIODevice.ReadOnly):
raise IOError(str(fh.errorString()))
stream = QDataStream(fh)
magic = stream.readInt32()
if magic != MAGIC_NUMBER:
raise IOError("unrecognized file type")
fileVersion = stream.readInt16()
if fileVersion != FILE_VERSION:
raise IOError("unrecognized file type version")
self.ships = {}
while not stream.atEnd():
name = ""
owner = ""
country = ""
description = ""
name=stream.readQString()
owner=stream.readQString()
country=stream.readQString()
description=stream.readQString()
teu = stream.readInt32()
ship = Ship(name, owner, country, teu, description)
self.ships[id(ship)] = ship
self.owners.add(str(owner))
self.countries.add(str(country))
self.dirty = False
except IOError as e:
exception = e
finally:
if fh is not None:
fh.close()
if exception is not None:
raise exception
def save(self):
exception = None
fh = None
try:
if not self.filename:
raise IOError("no filename specified for saving")
fh = QFile(self.filename)
if not fh.open(QIODevice.WriteOnly):
raise IOError(str(fh.errorString()))
stream = QDataStream(fh)
stream.writeInt32(MAGIC_NUMBER)
stream.writeInt16(FILE_VERSION)
stream.setVersion(QDataStream.Qt_5_7)
for ship in self.ships.values():
stream.writeQString(ship.name)
stream.writeQString(ship.owner)
stream.writeQString(ship.country)
stream.writeQString(ship.description)
stream.writeInt32(ship.teu)
self.dirty = False
except IOError as e:
exception = e
finally:
if fh is not None:
fh.close()
if exception is not None:
raise exception
def generateFakeShips():
for name, owner, country, teu, description in (
("Emma M\u00E6rsk", "M\u00E6rsk Line", "Denmark", 151687,
"<b>W\u00E4rtsil\u00E4-Sulzer RTA96-C</b> main engine,"
"<font color=green>109,000 hp</font>"),
("MSC Pamela", "MSC", "Liberia", 90449,
"Draft <font color=green>15m</font>"),
("Colombo Express", "Hapag-Lloyd", "Germany", 93750,
"Main engine, <font color=green>93,500 hp</font>"),
("Houston Express", "Norddeutsche Reederei", "Germany", 95000,
"Features a <u>twisted leading edge full spade rudder</u>. "
"Sister of <i>Savannah Express</i>"),
("Savannah Express", "Norddeutsche Reederei", "Germany", 95000,
"Sister of <i>Houston Express</i>"),
("MSC Susanna", "MSC", "Liberia", 90449, ""),
("Eleonora M\u00E6rsk", "M\u00E6rsk Line", "Denmark", 151687,
"Captain <i>Hallam</i>"),
("Estelle M\u00E6rsk", "M\u00E6rsk Line", "Denmark"