PyQt - แสดงวิดเจ็ตที่ด้านบนของวิดเจ็ต

ฉันกำลังสร้างแอปพลิเคชันที่แสดงแผนที่ของพื้นที่ และฉันกำลังพยายามวาดโหนดที่อยู่ด้านบนซึ่งสามารถแสดงข้อมูลได้

ฉันทำให้มันใช้งานได้ทั้งหมด แต่ทำได้เพียงแค่สร้างวิดเจ็ตแบบกำหนดเองอันเดียวซึ่งฉันแสดงและพิมพ์ทุกอย่างซ้ำแล้วซ้ำอีกทุกครั้งที่ข้อมูลมีการเปลี่ยนแปลง นอกจากนี้ฉันไม่สามารถ 'เชื่อมต่อ' โหนดกับผู้ฟังได้เนื่องจากเป็นเพียงรูปภาพในวิดเจ็ตดั้งเดิม

สิ่งนี้ทำให้ฉันต้องการปฏิรูป GUI ของฉัน และตอนนี้ฉันกำลังพยายามทำให้ทุกคลาสเป็นวิดเจ็ตแบบกำหนดเอง! แต่มีปัญหาอยู่ MapNodes ของฉันไม่แสดงอีกต่อไป

ฉันค้นหา stackoverflow และพบเธรดที่เป็นประโยชน์นี้: วิธีการตั้งค่า ตำแหน่งที่แน่นอนของวิดเจ็ตใน qt

ดังนั้นฉันต้องให้ mapnodes ของฉันเป็น parent และ parent = วิดเจ็ตที่กำลังแสดง (?)

อย่างไรก็ตาม นี่คือสิ่งที่ฉันทำได้ โดยวางโค้ดที่เกี่ยวข้องไว้ที่นี่ คำแนะนำเกี่ยวกับสิ่งที่อาจผิดพลาดร้ายแรง: การเริ่มต้นทั้งหมด

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)

แก้ไข - ฉันลืมเพิ่มโค้ดที่เพิ่มโหนด ดังนั้นหลังจากที่เหตุการณ์มาถึงโหนดจำเป็นต้องสร้างเมธอดนี้จะเริ่มการสร้างโหนด:

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 แหล่งที่มา


คำตอบ (1)


ฉันอยากจะแนะนำให้คุณใช้คลาส QGraphicsScene และ QGraphicsItem สำหรับแผนที่ของคุณแทนคลาส QWidget ปกติ เนื่องจากคลาสเหล่านี้ถูกสร้างขึ้นมาเพื่อจุดประสงค์ในการแสดงรายการกราฟิกจำนวนมาก:

จากเอกสาร:

คลาส QGraphicsScene จัดเตรียมพื้นผิวสำหรับจัดการรายการกราฟิก 2D จำนวนมาก

คลาสทำหน้าที่เป็นคอนเทนเนอร์สำหรับ QGraphicsItems โดยใช้ร่วมกับ QGraphicsView สำหรับการแสดงรายการกราฟิก เช่น เส้น สี่เหลี่ยม ข้อความ หรือแม้แต่รายการแบบกำหนดเอง บนพื้นผิว 2 มิติ QGraphicsScene เป็นส่วนหนึ่งของ Graphics View Framework

QGraphicsScene ยังมีฟังก์ชันการทำงานที่ช่วยให้คุณกำหนดทั้งตำแหน่งของรายการได้อย่างมีประสิทธิภาพ และเพื่อกำหนดว่ารายการใดที่มองเห็นได้ภายในพื้นที่ที่กำหนดเองในฉาก ด้วยวิดเจ็ต QGraphicsView คุณสามารถเห็นภาพทั้งฉาก หรือซูมเข้าและดูเฉพาะบางส่วนของฉากได้

คุณยังสามารถฝังวิดเจ็ตที่ได้รับจาก QWidget ไว้ในฉากได้ ซึ่งจะช่วยให้คุณแสดงข้อมูลได้แทบทุกประเภท เป็นโบนัส คุณจะได้รับการแบ่งชั้น การแปลงที่รวดเร็ว และการจัดการการโต้ตอบของเมาส์ที่พร้อมใช้งาน ซึ่งน่าจะมีประโยชน์มากในการสร้างแผนที่เชิงโต้ตอบ

person ThePhysicist    schedule 06.08.2013
comment
ลิงค์ด้านบนล้าสมัยแล้ว - person Adrián Kálazi; 27.07.2017
comment
ขอบคุณสำหรับการรายงานสิ่งนี้ ฉันแก้ไขแล้ว! - person ThePhysicist; 03.08.2017