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&le</string> </property> <addaction name="actionOpen"/> </widget> <addaction name="menuFile"/> </widget> <widget class="QStatusBar" name="statusbar"/> <action name="actionOpen"> <property name="text"> <string>&Open</string> </property> </action> </widget> <resources/> <connections/> </ui>
Thanks
JT
-
@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.
-
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
-
I've been studying your code and do you not use the Qt Designer but rather just code everything in Python?
JT