Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Create a Graphics View



  • I found an example and tried to incorporate it into my code but it creates a new QGraphicsView and does not put the objects in the QGraphicsView that is in the loaded UI. I know I'm missing some small detail...

    #!/usr/bin/python3
    
    import os, sys
    from PyQt5 import uic
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsScene, QGraphicsView, QGraphicsItem
    from PyQt5.QtGui import QBrush, QPen
    
    UI_FILE = os.path.join(os.path.dirname(__file__), "d2p.ui")
    
    class MainWindow(QMainWindow):
    	def __init__(self):
    		super(MainWindow, self).__init__()
    		uic.loadUi(UI_FILE, self)
    		self.setWindowTitle('HELP ME')
    		self.createGraphicView()
    		self.show()
    
    	def createGraphicView(self):
    		self.scene  = QGraphicsScene()
    		self.greenBrush = QBrush(Qt.green)
    		self.grayBrush = QBrush(Qt.gray)
    		self.pen = QPen(Qt.red)
    		self.graphicView = QGraphicsView(self.scene, self)
    		self.graphicView.setGeometry(0,0,600,400)
    		self.shapes()
    
    	def shapes(self):
    		ellipse = self.scene.addEllipse(20,20, 200,200, self.pen, self.greenBrush)
    		rect = self.scene.addRect(-100,-100, 200,200, self.pen, self.grayBrush)
    		ellipse.setFlag(QGraphicsItem.ItemIsMovable)
    		rect.setFlag(QGraphicsItem.ItemIsMovable)
    		ellipse.setFlag(QGraphicsItem.ItemIsSelectable)
    
    def main():
    	app = QApplication(sys.argv)
    	ex = MainWindow()
    	sys.exit(app.exec_())
    
    if __name__ == "__main__":
    	main()
    
    

    The ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>800</width>
        <height>600</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralwidget">
       <layout class="QVBoxLayout" name="verticalLayout">
        <item>
         <widget class="QWidget" name="widget" native="true">
          <widget class="QLabel" name="coordLbl">
           <property name="geometry">
            <rect>
             <x>30</x>
             <y>10</y>
             <width>141</width>
             <height>19</height>
            </rect>
           </property>
           <property name="text">
            <string>TextLabel</string>
           </property>
          </widget>
         </widget>
        </item>
        <item>
         <widget class="QWidget" name="widget_2" native="true">
          <layout class="QHBoxLayout" name="horizontalLayout">
           <item>
            <widget class="QGraphicsView" name="graphicsView">
             <property name="sizePolicy">
              <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
               <horstretch>0</horstretch>
               <verstretch>30</verstretch>
              </sizepolicy>
             </property>
             <property name="minimumSize">
              <size>
               <width>0</width>
               <height>400</height>
              </size>
             </property>
            </widget>
           </item>
          </layout>
         </widget>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>800</width>
         <height>24</height>
        </rect>
       </property>
       <widget class="QMenu" name="menuFile">
        <property name="title">
         <string>Fi&amp;le</string>
        </property>
        <addaction name="actionOpen"/>
       </widget>
       <addaction name="menuFile"/>
      </widget>
      <widget class="QStatusBar" name="statusbar"/>
      <action name="actionOpen">
       <property name="text">
        <string>&amp;Open</string>
       </property>
      </action>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    alt text

    Thanks
    JT


  • Lifetime Qt Champion

    @JThornton said in Create a Graphics View:

    uic.loadUi(UI_FILE, self)

    Change this line to

    self.ui = uic.loadUi(UI_FILE, self)
    

    And then access your view via

    self.ui.graphicsView
    

    And remove

    self.graphicView = QGraphicsView(self.scene, self)
    

    from createGraphicView as it creates another view.


  • Banned

    Okay those corrections @jsulm pointed out get your version to work perhaps but those are like putting a band-aid on a gaping knife wound -- so let me go over the how to part of using PyQt properly by demonstrating how to turn your simplistic UI garbage into proper PyQt along with how to implement the rest of what it seems you are trying to attempt to do with your program. Note not only did I rewrite it but I added explanatory comments within to hopefully help you understand some of the why of it all

    from PyQt5.QtCore    import Qt
    from PyQt5.QtGui     import QBrush, QPen
    from PyQt5.QtWidgets import QApplication, QStyleFactory, QMainWindow, QWidget, QVBoxLayout, QLabel
    from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsItem
    
    # It is often easier and more effectual to sub-class an object like this in order
    # to render what it is you are wanting to do and it keeps the code cleaner and more
    # encapsulated by functionality -- aka everything having to do with the Graphics
    # View is not contained within the Geometry Class
    class Geometry(QGraphicsView):
        def __init__(self):
      # Note: Do not use Super( ) unless you fully understand its purpose as while it is good for what
      #     it was designed for it has been latched onto and subsequently over-used and miss-used by 
      #     newbies and lazy coders.  Most of the time it simply adds more issues and saves you nothing 
      #     and is imho actually more complex than not using it under most situations
            QGraphicsView.__init__(self)
            self.resize(600,400)
    
          # This is all that the QGraphics part of the code needed
            self.scene = QGraphicsScene()
            self.shapes()
            self.setScene(self.scene)
    
        def shapes(self):
          # These items are only ever used by the Shapes function and as
          # such should be contained within it and thus self. is not needed
          #
          # Also always group like items with like items whenever possible
          #
            pen = QPen(Qt.red)
            greenBrush = QBrush(Qt.green)
            grayBrush = QBrush(Qt.gray)
            # -----
            ellipse = self.scene.addEllipse(20,20, 200,200, pen, greenBrush)
            ellipse.setFlag(QGraphicsItem.ItemIsMovable)
            ellipse.setFlag(QGraphicsItem.ItemIsSelectable)
            # -----
            rect = self.scene.addRect(-100,-100, 200,200, pen, grayBrush)
            rect.setFlag(QGraphicsItem.ItemIsMovable)
    
    # Okay this is basically the contents of your UI File render as it 
    # ought have been rendered using straight PyQt pretty straight foward
    # clear and easy to work with going forward -- not mystery to it at all
    # aka it is now no longer an untouchable black-box
    class CentralPanel(QWidget):
        def __init__(self):
            QWidget.__init__(self)
    
            self.lblCoords = QLabel('Geometry')
            self.gvwShapes = Geometry()
            
            vbxDsply = QVBoxLayout()
            vbxDsply.addWidget(self.lblCoords)
            vbxDsply.addWidget(self.gvwShapes)
            
            self.setLayout(vbxDsply)        
    
    # When using a QMainWindow (which you are not really using all of) 
    # it is best to keep in to its bare minimums and I did not see your
    # UI doing anything with the Menu Bar or Status Bar so just put
    # place holders in place -- I typically sub-class my Menu Bar but
    # functionalize my Status Bar
    class MainWindow(QMainWindow):
        def __init__(self):
            QMainWindow.__init__(self)
            self.setWindowTitle('HELP ME')
            self.setStyle(QStyleFactory.create('Cleanlooks'))
    
            self.CenterPane = CentralPanel()
            self.setCentralWidget(self.CenterPane)
            
          # self.MenuBar = QMenuBar()
          # self.StatusBar = QStatusBar()
    
    # This is my Template that I use for most Python-PyQt programs
    # for the Main it is short concise and pretty easy to understand
    # however if I were adding Command Line arguments I would be
    # adding an argparser function to this that the Main calls as well
    # as anything else that would need to be handled prior to entering
    # into the application
    if __name__ == "__main__":
        MainEventThred = QApplication([])
    
        MainApp = MainWindow()
        MainApp.show()
    
     # Note this is the PyQt5 version of this line yours was PyQt4
        MainEventThred.exec()
    
      # If anyone wants more extensive free help I run an online lab-like classroom-like 
      # message server feel free and drop by you will not be able to post until I clear 
      # you as a student as this prevents spammers so if interested here is the invite
      # https://discord.gg/3D8huKC
    


  • Thanks so much for the example that works, I'll study that and proceed with my learning. My goal is to open a DXF file and display it and allow the user to select the start point for plasma cutting.

    JT



  • @Denni-0

    I've been studying your code and do you not use the Qt Designer but rather just code everything in Python?

    JT


Log in to reply