PyQt - menampilkan widget di atas widget

Saya membuat aplikasi yang menampilkan peta suatu area dan saya mencoba menggambar node di atasnya yang dapat mewakili informasi.

Saya membuat semuanya berfungsi, namun melakukannya hanya dengan membuat satu widget khusus yang saya tampilkan dan mencetak semuanya lagi dan lagi setiap kali informasi berubah. Saya juga tidak dapat 'menghubungkan' node ke pendengar, karena itu hanya gambar di widget asli.

Ini membuat saya ingin mereformasi GUI saya dan sekarang saya mencoba menjadikan setiap kelas widget khusus! Tapi ada masalah, MapNodes saya tidak muncul lagi.

Saya mencari stackoverflow dan menemukan thread bermanfaat ini: Cara mengatur posisi absolut widget di qt

Jadi saya harus memberikan induk pada mapnode saya, dan induk = widget yang ditampilkan (?)

Bagaimanapun, inilah cara saya melakukannya, menempelkan kode yang relevan di sini. Petunjuk di mana hal-hal mungkin menjadi salah: semua init

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 - Saya lupa menambahkan kode yang menambahkan node. Jadi setelah sebuah event muncul di node yang perlu dibuat, metode ini akan mengaktifkan pembuatan node:

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()

person Spyral    schedule 14.05.2013    source sumber


Jawaban (1)


Saya akan merekomendasikan Anda untuk menggunakan kelas QGraphicsScene dan QGraphicsItem untuk peta Anda daripada kelas QWidget biasa, karena kelas tersebut dibuat persis dengan tujuan menampilkan sejumlah besar item grafis:

Dari dokumentasi:

Kelas QGraphicsScene menyediakan permukaan untuk mengelola sejumlah besar item grafis 2D.

Kelas berfungsi sebagai wadah untuk QGraphicsItems. Ini digunakan bersama dengan QGraphicsView untuk memvisualisasikan item grafis, seperti garis, persegi panjang, teks, atau bahkan item khusus, pada permukaan 2D. QGraphicsScene adalah bagian dari Kerangka Tampilan Grafis.

QGraphicsScene juga menyediakan fungsionalitas yang memungkinkan Anda menentukan lokasi item secara efisien, dan untuk menentukan item apa yang terlihat dalam area sembarang di tempat kejadian. Dengan widget QGraphicsView, Anda dapat memvisualisasikan keseluruhan pemandangan, atau memperbesar dan melihat sebagian pemandangan saja.

Anda juga dapat menyematkan widget yang berasal dari QWidget ke dalam scene, yang memungkinkan Anda menampilkan hampir semua jenis informasi. Sebagai bonus, Anda akan mendapatkan transformasi yang berlapis, cepat, dan penanganan interaksi mouse yang siap digunakan, yang seharusnya cukup berguna untuk mewujudkan peta interaktif.

person ThePhysicist    schedule 06.08.2013
comment
Tautan di atas sudah usang - person Adrián Kálazi; 27.07.2017
comment
Terima kasih telah melaporkan ini, saya sudah memperbaikinya! - person ThePhysicist; 03.08.2017