Pyqt在Widget中嵌入Graphics对象

时间:2015-05-13 13:51:32

标签: python layout widget pyqt

所以我有一个主窗口。我使用setCentralWidget将它设置为一个名为mainWindowWidget的类来处理UI。

我现在正在尝试添加我制作的图形视图小部件,但似乎无法显示任何内容。如果我将图形视图设置为中央窗口小部件,我可以看到它并且我的所有行为都正常工作。

我是否需要做任何事情才能让图形视图显示在另一个小部件中?

以下是我认为与整个应用程序所遵循的问题相关的代码部分。我是PyQt的新手,任何指导都会受到赞赏。

class mainWindowWidget(QtGui.QWidget):
    grid = None
    scene = None
    def __init__(self):
        self.initScene()
        QtGui.QWidget.__init__(self)

    def initScene(self):

        self.grid = QtGui.QGridLayout()

        '''Node Interface'''

        self.scene = Scene(0, 0, 1280, 720, self)
        self.view = QtGui.QGraphicsView()
        self.view.setScene(self.scene)

        self.grid.addWidget(self.view)




        '''AttributeWindow'''

class MainWindowUi(QtGui.QMainWindow):
    def __init__(self):
        mainDataGraber = ind.dataGraber()
        QtGui.QMainWindow.__init__(self)
        self.setWindowTitle('RIS RIB Generator')


        mainwindowwidget = mainWindowWidget()
        self.setCentralWidget(mainwindowwidget)

这是应用程序的主GUI文件

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
This is the base py file for the GUI

Todo list
-----------------
- Pop up menu for adding new Nodes
- node connectivity
- create data structure for storing
"""

#import code mods
import sys
import uuid 
import gtk, pygtk
from PyQt4 import QtGui, QtCore
from array import *

#import StyleMod
import RRG_NodeInterfaceGUIStyle as ns
import RRG_importNodeData as ind

"""
Base class for a node. Contains all the inilization, drawing, and containing inputs and outputs
"""
class node(QtGui.QGraphicsRectItem):

    nid = 0
    width = ns.nodeWidth
    height = ns.nodeHeight
    color = ns.nodeBackgroundColor
    alpha = ns.nodeBackgroundAlpha
    x = 90
    y = 60
    inputs=[]
    outputs=[]
    viewObj = None
    isNode = True
    scene = None

    def __init__(self, n_x, n_y, n_width,n_height, n_scene):
        QtGui.QGraphicsRectItem.__init__(self, n_x, n_y, n_width, n_height)
        self.width = n_width
        self.height = n_height
        self.x = n_x
        self.y = n_y
        self.scene = n_scene
        self.nid = uuid.uuid4()
        print(self.nid)
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.iniNodeData()

    def mousePressEvent(self, e):
        print("Square got mouse press event")
        print("Event came to us accepted: %s"%(e.isAccepted(),))
        a = []
        self.scene.selectedNodes = a
        self.scene.selectedNodes.append(self)
        self.scene.selectedNodeID = self.nid
        QtGui.QGraphicsRectItem.mousePressEvent(self, e)

    def mouseReleaseEvent(self, e):
        #print("Square got mouse release event")
        #print("Event came to us accepted: %s"%(e.isAccepted(),))
        QtGui.QGraphicsRectItem.mouseReleaseEvent(self, e)

    """
    This is where inputs and outputs will be created based on node type
    """ 
    def iniNodeData(self):
        print('making node data')
        for j in range(5):
            this = self
            x = input(this,0, 0+(j*10),self.scene)
            self.inputs.append(x)

        for k in range(5):
            this = self
            x = output(this, self.width-10, 0+(k*10),self.scene)
            self.outputs.append(x)

    def mouseMoveEvent(self, event):
        self.scene.updateConnections()
        QtGui.QGraphicsRectItem.mouseMoveEvent(self, event)

    def nid(self):
        return self.nid

"""
Nodes will evaluate from the last node to the first node, therefore inputs are evaluted
"""
class input(QtGui.QGraphicsRectItem):
    currentConnectedNode = None
    currentConnectedOutput = None
    parentNode = None
    width = 10
    height = 10
    x = 1
    y = 1
    color = 1
    drawItem = None
    isOutput = False
    isNode = False
    scene = None
    points = []
    line = None

    def __init__(self, pnode, posX, posY, n_scene):
        self.parentNode = pnode
        self.x = posX
        self.y = posY
        self.color = 1
        self.scene = n_scene
        QtGui.QGraphicsRectItem.__init__(self, self.x+self.parentNode.x, self.y+self.parentNode.y, self.width, self.height, self.parentNode)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)

    '''
    This will handel connections. It determins if a connection is allowed aswell as creates them
    '''
    def mousePressEvent(self, e):
        #print("Square got mouse press event")
        #print("Event came to us accepted: %s"%(e.isAccepted(),))
        emptyArray = []
        if len(self.scene.selectedNodes) > 0 or len(self.scene.selectedNodes) > 1:
            a = self.scene.selectedNodes[0]
            if a.isNode == False:
                if a.parentNode != self.parentNode:

                    if a.isOutput == True and self.isOutput == False:
                        print('Output and Input! line test runnin....')

                        currentConnectedOutput = a
                        currentConnectedNode = a.parentNode


                        if self.line != None:
                            self.line = None

                        self.scene.addConnection(self, a)

                    elif a.isOutput == True and self.isOutput == True:
                        print('Output and Output')

                    elif a.isOutput == False and self.isOutput == False:
                        print('Input and Input')

                    self.scene.selectedNodes = emptyArray

                else:
                    self.scene.selectedNodes = emptyArray

            else:
                self.scene.selectedNodes = emptyArray
                self.scene.selectedNodes.append(self) 
        else:
            self.scene.selectedNodes.append(self)

        QtGui.QGraphicsRectItem.mousePressEvent(self, e)

'''
Output value from a node
'''
class output(QtGui.QGraphicsRectItem):
    parentNode = None
    width = 10
    height = 10
    x = 0
    y = 0
    isOutput = True
    isNode = False
    scene = None

    def __init__(self, pnode, posX, posY, n_scene):
        self.parentNode = pnode
        self.x = posX
        self.y = posY
        self.color = 1
        self.scene = n_scene
        QtGui.QGraphicsRectItem.__init__(self, self.x+self.parentNode.x, self.y+self.parentNode.y, self.width, self.height, self.parentNode)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)


    '''
    This will handel connections. It determins if a connection is allowed aswell as creates them
    '''
    def mousePressEvent(self, e):
        #print("Square got mouse press event")
        #print("Event came to us accepted: %s"%(e.isAccepted(),))
        emptyArray = []
        if len(self.scene.selectedNodes) > 0 or len(self.scene.selectedNodes) > 1:
            a = self.scene.selectedNodes[0]
            if a.isNode == False:
                if a.parentNode != self.parentNode:

                    if a.isOutput == False and self.isOutput == True:
                        print('Input and Output!')
                        a.currentConnectedOutput = self
                        a.currentConnectedNode = self.parentNode



                    elif a.isOutput == True and self.isOutput == False:
                        print('Output and Input!')


                    elif a.isOutput == True and self.isOutput == True:
                        print('Output and Output')


                    elif a.isOutput == False and self.isOutput == False:
                        print('Input and Input')

                    self.scene.selectedNodes = emptyArray

                else:
                    self.scene.selectedNodes = emptyArray

            else:
                self.scene.selectedNodes = emptyArray
                self.scene.selectedNodes.append(self) 

        else:
            self.scene.selectedNodes.append(self)


        QtGui.QGraphicsRectItem.mousePressEvent(self, e)


class connection(QtGui.QGraphicsLineItem):

    usedNodeIDs = []
    inputItem = None
    outputItem = None
    x1 = 0.0
    y1 = 0.0   
    x2 = 0.0
    y2 = 0.0
    nid = None
    scene = None

    def __init__(self, n_inputItem, n_outputItemm, n_scene):
        self.inputItem = n_inputItem
        self.outputItem = n_outputItemm
        self.usedNodeIDs.append(self.inputItem.parentNode.nid)
        self.usedNodeIDs.append(self.outputItem.parentNode.nid)
        self.updatePos()
        QtGui.QGraphicsLineItem.__init__(self, self.x1, self.y1, self.x2, self.y2)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        self.scene = n_scene
        self.nid = uuid.uuid4()

    def update(self):
        self.updatePos()
        self.setLine(self.x1, self.y1, self.x2, self.y2)

    def updatePos(self):
        scenePosInput = QtGui.QGraphicsItem.pos(self.inputItem)
        scenePosOutput = QtGui.QGraphicsItem.pos(self.outputItem)
        scenePosInputNode = QtGui.QGraphicsItem.pos(self.inputItem.parentNode)
        scenePosOutputNode = QtGui.QGraphicsItem.pos(self.outputItem.parentNode)

        self.x1 = (scenePosInputNode.x()+self.inputItem.parentNode.x)+(scenePosInput.x()+self.inputItem.x) + ns.inputWidth/2
        self.y1 = (scenePosInputNode.y()+self.inputItem.parentNode.y)+(scenePosInput.y()+self.inputItem.y) + ns.inputHeight/2

        self.x2 = (scenePosOutputNode.x()+self.outputItem.parentNode.x)+(scenePosOutput.x()+self.outputItem.x) + ns.outputWidth/2
        self.y2 = (scenePosOutputNode.y()+self.outputItem.parentNode.y)+(scenePosOutput.y()+self.outputItem.y) + ns.outputHeight/2

    def mousePressEvent(self, e):
        self.scene.selectedNodeID = self.nid
        QtGui.QGraphicsLineItem.mousePressEvent(self, e)

'''
Check Click events on the scene Object
Also Stores the node data
'''
class Scene(QtGui.QGraphicsScene):

    nodes = []
    connections = []
    selectedNodeID = None

    def __init__(self, x, y, w, h, p):
        super(Scene, self).__init__()
        self.width = w
        self.height = h


    def mousePressEvent(self, e):
        #print("Scene got mouse press event")
        #print("Event came to us accepted: %s"%(e.isAccepted(),))

        QtGui.QGraphicsScene.mousePressEvent(self, e)

    def mouseReleaseEvent(self, e):
        #print("Scene got mouse release event")
        #print("Event came to us accepted: %s"%(e.isAccepted(),))
        QtGui.QGraphicsScene.mouseReleaseEvent(self, e)

    def dragMoveEvent(self, e):
        QtGui.QGraphicsScene.dragMoveEvent(self, e)   

    def updateConnections(self):
        for connect in self.connections:
            connect.update()

    def addNode(self):
        newNode = node(250,250,100,150, self)
        self.addItem(newNode)
        self.nodes.append(newNode)

    def addPatternNode(self):
        newNode = node(250,250,100,150, self)
        self.addItem(newNode)
        self.nodes.append(newNode)

    def addConnection(self, n_inputItem, n_outputItem):    
        newConnection = connection(n_inputItem, n_outputItem, self)
        self.addItem(newConnection)
        self.connections.append(newConnection)

    def keyPressEvent(self, e):
        #Delete a node after it have been clicked on
        #Use the node ID as the unique ID of the node to delete
        if e.key() == QtCore.Qt.Key_Delete or e.key() == QtCore.Qt.Key_Backspace:
            #If nothing selected
            if self.selectedNodeID != None:

                isConnection = False
                for j in range(len(self.connections)):
                    if self.connections[j].nid == self.selectedNodeID:
                        isConnection = True
                        self.removeItem(self.connections[j])
                        self.connections.remove(self.connections[j])

                if isConnection != True:
                    #first remove connections
                    rmItem = False
                    connectionsToRemove = []
                    for connect in self.connections: 
                        rmItem = False    
                        for nid in connect.usedNodeIDs:
                            if nid == self.selectedNodeID:
                                if rmItem == False:
                                    connectionsToRemove.append(connect)
                                    rmItem = True

                    for removeThis in connectionsToRemove:
                        self.connections.remove(removeThis)
                        self.removeItem(removeThis)

                    #now remove the nodes
                    for j in range(len(self.nodes)):
                        print(self.nodes[j].nid)
                        #figure out which node in our master node list must be deleted
                        if self.nodes[j].nid == self.selectedNodeID:


                            self.removeItem(self.nodes[j])
                            self.nodes.remove(self.nodes[j])
                    self.selectedNodeID = None




class mainWindowWidget(QtGui.QWidget):
    grid = None
    scene = None
    def __init__(self):
        self.initScene()
        QtGui.QWidget.__init__(self)

    def initScene(self):

        self.grid = QtGui.QGridLayout()

        '''Node Interface'''

        self.scene = Scene(0, 0, 1280, 720, self)
        self.view = QtGui.QGraphicsView()
        self.view.setScene(self.scene)

        self.grid.addWidget(self.view)




        '''AttributeWindow'''

class MainWindowUi(QtGui.QMainWindow):
    def __init__(self):
        mainDataGraber = ind.dataGraber()
        QtGui.QMainWindow.__init__(self)
        self.setWindowTitle('RIS RIB Generator')


        mainwindowwidget = mainWindowWidget()
        self.setCentralWidget(mainwindowwidget)



        exitAction = QtGui.QAction(QtGui.QIcon('exit24.png'), 'Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.close)

        newNodeAction = QtGui.QAction(QtGui.QIcon('exit24.png'), 'New Node', self)
        newNodeAction.setStatusTip('Add a blank node')
        newNodeAction.triggered.connect(mainwindowwidget.scene.addPatternNode)


        nodeCreationActions = []

        for nodeType in mainDataGraber.abstractNodeObjects:

            nodeName = nodeType.nName
            nodeType = nodeType.nType
            #nodeStatusTip = nodeType.nhelp

            newNodeAction = QtGui.QAction(QtGui.QIcon('exit24.png'), nodeName, self)
            newNodeAction.setStatusTip('nodeType.nhelp')
            if nodeType == 'pattern': 
                newNodeAction.triggered.connect(mainwindowwidget.scene.addPatternNode)

            nodeCreationActions.append(newNodeAction)


        newNodeAction = QtGui.QAction(QtGui.QIcon('exit24.png'), 'New Node', self)
        newNodeAction.setStatusTip('Add a blank node')
        newNodeAction.triggered.connect(mainwindowwidget.scene.addPatternNode)


        self.statusBar()
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(newNodeAction)
        nodeMenu = menubar.addMenu('&Nodes')

        for action in nodeCreationActions:
            nodeMenu.addAction(action)

        fileMenu.addAction(exitAction)

'''
Start Point
'''
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    win = MainWindowUi()
    win.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

您的问题是您未指定QGridLayout的父级(在mainWindowWidget类中),因此它未附加到小部件。这导致布局(以及其中包含的所有小部件)不可见。在布局中添加父级会显示第二个问题,即您在调用QWidget之前尝试使用__init__执行操作。

因此修正后的代码为:

class mainWindowWidget(QtGui.QWidget):
    grid = None
    scene = None
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.initScene()

    def initScene(self):

        self.grid = QtGui.QGridLayout(self)

        '''Node Interface'''

        self.scene = Scene(0, 0, 1280, 720, self)
        self.view = QtGui.QGraphicsView()
        self.view.setScene(self.scene)

        self.grid.addWidget(self.view)

注意:对于需要调试帮助的未来问题,请制作最小化 可运行示例。不要只将90%的代码转储到堆栈溢出帖子中。尝试挖掘随机代码试图减少丢失的导入以使它仍然能够重现问题(幸运的是在这种情况下并不太难),这并不好玩。请参阅How to create a Minimal, Complete, and Verifiable example

注2:为什么要将pygtk导入qt应用程序?