Форум сайта python.su
Здравствуйте!
Есть у меня QLabel, а в ней периодически меняется текст. Однако она остаётся прежнего размера, посему текст порой в неё не вписывается. Как сделать, чтобы её размер менялся автоматически?
Также у меня есть QGraphicsItem, который я также хочу, чтобы периодически обновлялся. И он обновляется, вот только не всегда. Я даже пробовал делать QGraphicsView.repaint(), но это не помогло. Как мне добиться желаемого?
Заранее благодарен.
Офлайн
C QLabel можно сделать len() на строку с текстом, и потом обновлять размер вместе с воодом текста.
Офлайн
SlonНичего не понял.
C QLabel можно сделать len() на строку с текстом, и потом обновлять размер вместе с воодом текста.
Офлайн
Обсуждение сферического коня В Вакууме. Покажите хоть какой-нибудь код:) Скорость зависит не только от Видеокарты но и от других компонент. Непостоянство работы говорит 0 неявной ошибке.
Офлайн
Ну вот такой приблизительно код.
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()
Отредактировано (Сен. 17, 2011 00:10:28)
Офлайн
Признаюсь разобраться в коде мне толком не удалось. Скажу сразу конкретных рецептов я дать не могу. Но считаю, что код можно переработать в более-менее приемлемый, что в конечном итоге должно привести к более полному понимаю механизмов отрисовки элементов и самой проблемы, да и вообще это полезно для развития.
Итак, если вы со мной согласны и у вас достаточно времени, то…
self.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) лучше делать в конструкторе, т.к. она задает политику обновления размера.
цель метода setlabel в LabelList для меня осталась загадкой (чутьем чую, что можно сделать проще)
Главный вопрос: зачем вообще нужны QGraphicsView и QGraphicsItem? Точнее почему именно они? Насколько я понимаю, у вас динамическое добавление/удаление Label? Для этих целей не обязательно использовать QGraphicsView (он предназначен как раз для рисования линий, кружочков, квадратиков:))
И если вас не затруднит изложите (переработайте) модель предметной области (задачи) в терминах объектов. С ООП знакомы? Тогда будет проще совместить вашу объектную модель с (любым) объектным фреймворком.
Как я вижу есть объекты Агенты (которые должны быть представлены на форме, в вашем случае с помошью Label) и совершенно неведомое (для меня) их взаимодействие…
Офлайн
dartNNNЯ так пробовал - не получается должного эффекта.
self.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) лучше делать в конструкторе, т.к. она задает политику обновления размера.
dartNNNВсё очень просто. Сначала извлекается из пула незанятый лабел, а коли они все заняты (о чём свидетельствует то, что извлечённый лабел видимый) - создаётся ещё один и снова помещается в пул. А затем он перемещается на нужное место, снабжается нужным текстом и делается видимым (две последние операции производятся в AgentLabel.update()).
цель метода setlabel в LabelList для меня осталась загадкой (чутьем чую, что можно сделать проще)
dartNNNВот этот вопрос меня тоже интересует. Только я не смог найти примеров, как это сделать без QGraphicsView.
Главный вопрос: зачем вообще нужны QGraphicsView и QGraphicsItem? Точнее почему именно они? Насколько я понимаю, у вас динамическое добавление/удаление Label? Для этих целей не обязательно использовать QGraphicsView (он предназначен как раз для рисования линий, кружочков, квадратиков)
dartNNNНе только, ещё у меня надо рисовать клетки и линии (причём линии также надо перерисовывать каждый раз).
Насколько я понимаю, у вас динамическое добавление/удаление Label?
dartNNNА у меня разве нет объектов? Что я делаю не так? Объединять в одном объекте механику и отрисовку не буду, даже не уговаривайте.
И если вас не затруднит изложите (переработайте) модель предметной области (задачи) в терминах объектов. С ООП знакомы? Тогда будет проще совместить вашу объектную модель с (любым) объектным фреймворком.
dartNNNНу их взаимодействие в данном случае не столь важно. Важно то, что они периодически перемещаются, появляются и исчезают.
Как я вижу есть объекты Агенты (которые должны быть представлены на форме, в вашем случае с помошью Label) и совершенно неведомое (для меня) их взаимодействие…
есть прямоугольная сетка, на ней некоторое множество модельных организмов (т. н. агентов). Внутри каждого агента нейронная сеть. И каждый агент может передвигаться из клетки в клетку, общаться с другими агентами, размножаться (попутно мутируя) и умирать. То бишь получается навроде генетического алгоритма (такие вещи ещё называют “искусственной жизнью”, хотя данная конкретная модель не сказать чтобы уж очень живая).
Офлайн
> AgentLabel.update()
update это метод QLabel, а вы его переопределили.
Офлайн
Переименовал оба update, ничего принципиально не изменилось.
Офлайн
Эх, давно я за питон не брался:) хорошо то как:)
Итак
Обедающий философЯ имел ввиду предметную область разложить по объектам, чтобы правильно и без хаков (извращения) организовать код.
А у меня разве нет объектов?
class MyWidget(QtGui.QWidget):
def __init__(self):
super(QtGui.QWidget, self).__init__()
button = QtGui.QPushButton("Push me!")
button.clicked.connect(self.button_click)
self.layout = QtGui.QGridLayout()
self.layout.addWidget(button, 0,0)
self.layout.setHorizontalSpacing(0) #убираем расстояния между ячейками
self.layout.setVerticalSpacing(0)
self.setLayout(self.layout)
self.lines = 1
def some_magic_func(self, label, newText, line):
self.layout.addWidget(label, line, 0)
label.setText(newText)
def button_click(self):
self.lines += 1
label = Magic(self.layout)
self.some_magic_func(label, "Initial text", self.lines)
alph = list(map(chr, range(97, 123))) # делаем алфавит
class Magic(QtGui.QLabel):
def __init__(self, layout): # принимаем layout, по которому будем бегать
super(QtGui.QLabel, self).__init__()
self.layout = layout
def mousePressEvent(self, event): #переопределенный метод, вызывается при клике на лабел
index = self.layout.indexOf(self)
row, column, row_span, column_span = self.layout.getItemPosition(index)
self.init_mooooving(row, column + 1) # пляшем в право
def init_mooooving(self, row, column):
self.layout.removeWidget(self) # вот тебе и динамическое добавление/удаление - так и бежим
self.layout.addWidget(self, row, column)
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
for column in range(self.layout.columnCount()):
self.layout.setColumnMinimumWidth(column, 100) # чтобы ячейки не сжимались до нуля.
for row in range(self.layout.rowCount()):
rect = self.layout.cellRect(row, column)
painter.drawRect(rect)
painter.end()
Офлайн