Ну вот такой приблизительно код.
class AgentLabel(QtGui.QLabel):
def __init__(self):
QtGui.QLabel.__init__(self, "")
self.setStyleSheet("* {background-color: transparent;}")
self.setMouseTracking(True)
...................
def update(self, a):
self.agent = a
self.setText(agent_brief.get_colored(self.agent))
self.show()
self.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) # чтобы размер изменился..
class LabelList:
def __init__(self, scene):
self.scene = scene
self.labels = [self.scene.addWidget(AgentLabel())] # чтобы не было случая с пустым списком
self.hide()
def setlabel(self, y, x, a):
l = self.labels.pop(0)
self.labels.append(l)
if l.isVisible():
l = self.scene.addWidget(AgentLabel())
self.labels.append(l)
l.setPos(x, y)
l.widget().update(a)
return l
def hide(self):
for l in self.labels:
l.hide()
class CellItem(QtGui.QGraphicsItem):
bgcolor = QtGui.QColor(0xeeeeee)
bordercolor = QtGui.QColor(0xaaaaaa)
popcolor = QtGui.QColor(0x7777aa)
foodcolor = QtGui.QColor(0x33cc33)
height_coef = 0.2
def __init__(self, y, x, h, w, scene, labels, cell):
QtGui.QGraphicsItem.__init__(self)
self.x = x
self.y = y
self.setPos(x, y)
self.width = w
self.height = h
self.rect = QtCore.QRectF(0, 0, w, h)
self.scene = scene
self.labels = labels
self.cell = cell
self.setZValue(-1)
self.scene.addItem(self)
def update(self):
alist = agent_list(self.cell)
if len(alist)>0:
dy = self.height/len(alist)
xl = self.x + self.width*0.1
yl = self.y
for a in alist:
l = self.labels.setlabel(yl, xl, a)
yl += self.height*self.height_coef
def paint(self, painter, option, widget=None):
painter.setBrush(self.bgcolor)
painter.setPen(self.bordercolor)
painter.drawRect(1, 1, self.width, self.height)
if self.cell.agent_n>0:
painter.setPen(self.popcolor)
painter.drawText(self.width*0.8, 0+self.height*0.2, str(self.cell.agent_n))
if self.cell.food_present>0:
painter.setPen(self.foodcolor)
painter.drawText(self.width*0.8, 0+self.height*0.9, str(self.cell.food_present))
def boundingRect(self):
return self.rect
class DetailedGui(QtGui.QWidget):
left_column_width = 100
colum_width = 100
row_height = 100
map_rect = [0, 0, 10, 10]
def __init__(self, *args):
QtGui.QWidget.__init__(self,*args)
self.setWindowTitle(u"Detailed map")
self.stats = agent_brief
self.infolabel = QtGui.QLabel("")
self.maplabel = QtGui.QTextEdit(self.stats.get_detailed_map(*self.map_rect))
self.maplabel.document().setDefaultStyleSheet(self.stylestring)
self.scene = QtGui.QGraphicsScene(self)
self.view = QtGui.QGraphicsView(self.scene)
self.labels = LabelList(self.scene)
self.init_map()
self.layout1 = QtGui.QVBoxLayout()
self.layout1.addWidget(self.infolabel)
self.layout0 = QtGui.QHBoxLayout(self)
self.layout0.addLayout(self.layout1)
self.layout0.addWidget(self.view)
def init_map(self):
self.cells = []
x0 = self.map_rect[0]
y0 = self.map_rect[1]
x1 = self.map_rect[2]
y1 = self.map_rect[3]
w = self.colum_width
h = self.row_height
for y in xrange(y0, y1):
for x in xrange(x0, x1):
c = world.cells[y][x]
self.cells.append(CellItem((y-y0)*h, (x-x0)*w, h, w, self.scene, self.labels, c)) #(self, y, x, h, w, scene, cell)
................................
def redraw_map(self):
self.labels.hide()
for c in self.cells:
c.update()
#self.view.repaint()
Вопщем смысл в следующем. Есть QGraphicsScene/QGraphicsView, и в нём собственно имеют место быть некоторое количество объектов типов QLabel и CellItem(QtGui.QGraphicsItem). Клетки всегда одни и те же, а вот лабелы служат для представления объектов (агентов), которых каждый раз переменное количество и они каждый раз в новом месте. DetailedGui.labels (класса LabelList) - это собственно пул лабелов, каковые каждый раз прячутся и извлекаются по мере надобности, а когда их не хватает, то создаются новые.
На каждом шаге вызывается функция DetailedGui.redraw_map(). Она сначала прячет лабелы, а затем вызывает CellItem.update(), каковой вызывает AgentLabel.update() для каждого из агентов, находящихся в оной клетке. А вот функция CellItem.paint(), каковая собственно перерисовывает клетку, вызывается, видимо, каким-то мистическим глубинным механизмом. И чтобы она принудительно перерисовывалась каждый раз, я вижу два варианта - либо вызывать CellItem.paint() самому (это я не знаю как), либо банально весь нужный текст также засовывать в лабелы. Второе, конечно, проще, но я ещё хочу рисовать линии.