PyQt – отображение виджета поверх виджета

Я делаю приложение, которое показывает карту области, и я пытаюсь нарисовать узлы поверх нее, которые могут представлять информацию.

Я сделал все это, но сделал это просто, создав один пользовательский виджет, который я показывал, и печатал все снова и снова каждый раз, когда информация менялась. Также я не мог «подключить» узлы к слушателям, потому что они были просто изображениями в исходном виджете.

Это заставило меня хотеть реформировать мой графический интерфейс, и теперь я пытаюсь сделать каждый класс обычным виджетами! Но проблема в том, что мои MapNodes больше не появляются.

Я искал stackoverflow и нашел этот полезный поток: как установить абсолютную позицию виджетов в qt

Таким образом, я должен предоставить родительским картам родителям, а parent = виджете, который отображается (?)

Во всяком случае, вот мой бросок, вставив здесь соответствующий код. Подскажите, где вещи могут пойти ужасно неправильно: все inits

app = QtGui.QApplication(list()) mutexbranch = Lock() mutexnode = Lock() def exec(): return app.exec_() #Singleton Pattern: wanneer en object aan iets moet kunnen # waar het inherent door de structuur niet aankon # wordt dit via dit singleton opgelost class GuiInternalCommunication: realmap = 0 class MapView(QtGui.QWidget, listener.Listener): def __init__(self, mapimagepath): QtGui.QMainWindow.__init__(self) listener.Listener.__init__(self) self.map = Map(self, mapimagepath) #self.setCentralWidget(self.map) self.initUI() def initUI(self): self.setWindowTitle('Population mapping') hbox = QtGui.QHBoxLayout() hbox.addWidget(self.map) self.setLayout(hbox) resolution = QtGui.QDesktopWidget().screenGeometry() self.setGeometry(20,20,550,800) self.show() ###################################################################### class Map(QtGui.QWidget): def __init__(self, parent, mapimagepath): QtGui.QWidget.__init__(self, parent) #self.timer = QtCore.QBasicTimer() #coordinaten hoeken NE en SW voor kaart in map graphics van SKO self.realmap = RealMap( mapimagepath, (51.0442, 3.7268), (51.0405, 3.7242), 550, 800) GuiInternalCommunication.realmap = self.realmap self.needsupdate = True self.timelabel = 0 parent.setGeometry(0,0,self.realmap.width, self.realmap.height) self.mapNodes = {} self.mapBranches = {} def paintEvent(self, event): painter = QtGui.QPainter() painter.begin(self) rect = self.contentsRect() #teken achtergrond self.realmap.drawRealMap(painter) #teken branches mutexbranch.acquire() try: for branch, mapBranch in self.mapBranches.items(): mapBranch.drawMapBranch(painter) finally: mutexbranch.release() ###################################################################### class RealMap(QtGui.QWidget): def __init__(self, path, coordRightTop, coordLeftBot, width, height, pixpermet = 2.6): super(RealMap, self).__init__() self.path = path self.mapimage = QtGui.QImage(self.path) self.coordLeftBot = coordLeftBot self.coordRightTop = coordRightTop self.width = width self.height = height self.realdim = self.calcRealDim() self.pixpermet = pixpermet def paintEvent(self, e): painter = QtGui.QPainter() painter.begin(self) self.drawRealMap(self, painter) painter.end() def drawRealMap(self, painter): painter.drawImage(0,0,self.mapimage) ###################################################################### class MapNode(QtGui.QWidget): dangertocolor = {"normal":"graphics//gradients//green.png", "elevated":"graphics//gradients//orange.png", "danger":"graphics//gradients//red.png"} gradimage = {"normal":QtGui.QImage(dangertocolor["normal"]), "elevated":QtGui.QImage(dangertocolor["elevated"]), "danger":QtGui.QImage(dangertocolor["danger"])} btimage = QtGui.QImage("graphics//BT-icon.png") def __init__(self, scanner, x, y, danger = 0, parent = None): # MapNode erft over van QWidget super(MapNode, self).__init__() QtGui.QWidget.__init__(self, parent) self.scanner = scanner self.x = x self.y = y self.danger = 'normal' self.calcDanger(danger) self.grads = {} self.grad = QtGui.QImage(MapNode.dangertocolor[self.danger]) def paintEvent(self, e): painter = QtGui.QPainter() painter.begin(self) self.drawMapNode(painter) painter.end() def drawMapNode(self, painter): realmap = GuiInternalCommunication.realmap radiusm = self.scanner.range radiusp = radiusm*realmap.pixpermet factor = radiusp/200 # basis grootte gradiënten is 200 pixels. grad = MapNode.gradimage[self.danger] grad = grad.scaled(grad.size().width()*factor, grad.size().height()*factor) painter.drawImage(self.x-100*factor,self.y-100*factor, grad) painter.drawImage(self.x-10, self.y-10,MapNode.btimage) painter.drawText(self.x-15, self.y+20, str(self.scanner.sensorid) + '-' + str(self.scanner.name)) ###################################################################### class MapBranch: branchpens = {"normal": QtGui.QPen(QtCore.Qt.green, 3, QtCore.Qt.DashLine), "elevated": QtGui.QPen(QtGui.QColor(255, 51, 0), 3, QtCore.Qt.DashLine), #mandarine orange hex is 255-165-0 "danger": QtGui.QPen(QtCore.Qt.red, 3, QtCore.Qt.DashLine)} def __init__(self, branch, mapnode1, mapnode2, danger = 0): self.mapnode1 = mapnode1 self.mapnode2 = mapnode2 self.branch = branch self.danger = danger self.calcDanger(danger) def drawMapBranch(self, painter): painter.setPen(MapBranch.branchpens[self.danger]) painter.drawLine(self.mapnode1.x, self.mapnode1.y, self.mapnode2.x, self.mapnode2.y) 

EDIT – я забыл добавить код, который добавляет узлы. Поэтому после того, как событие приходит в узел, необходимо создать, этот метод запускает создание узла:

 def addNode(self, scanner): mutexnode.acquire() try: coord = self.realmap.convertLatLon2Pix((scanner.latitude, scanner.longitude)) self.mapNodes[scanner.sensorid] = MapNode(scanner, coord[0], coord[1], parent = self) self.mapNodes[scanner.sensorid].move(coord[0],coord[1]) #self.mapNodes[scanner.sensorid].show() finally: mutexnode.release() 

Я бы рекомендовал вам использовать классы QGraphicsScene и QGraphicsItem для вашей карты вместо обычных классов QWidget, поскольку они сделаны именно с целью отображения большого количества графических элементов:

Из документации:

Класс QGraphicsScene предоставляет поверхность для управления большим количеством 2D-графических элементов.

Класс служит контейнером для QGraphicsItems. Он используется вместе с QGraphicsView для визуализации графических элементов, таких как строки, прямоугольники, текст или даже пользовательские элементы, на 2D-поверхности. QGraphicsScene является частью Graphics View Framework.

QGraphicsScene также предоставляет функциональные возможности, которые позволяют эффективно определять как расположение элементов, так и определять, какие элементы видны в произвольной области на сцене. С помощью виджета QGraphicsView вы можете либо визуализировать всю сцену, либо увеличивать масштаб и просматривать только части сцены.

Вы также можете вставлять виджеты, полученные из QWidget в сцене, что должно позволить вам отображать практически любую информацию. В качестве бонуса вы получите наслаивание, быстрые преобразования и готовую к использованию манипуляцию с мышью, что должно быть весьма полезно для реализации интерактивной карты.