问题
just like the title says i'm trying to draw inside an existing QGraphicsView. The window I generated using QT Designer, and I would like to draw a matrix of 16x16 squares inside the QGraphicsView.
This is the code I have as of right now:
Window:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.8.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(911, 567)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(20, 10, 301, 31))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.label.setFont(font)
self.label.setObjectName("label")
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox.setGeometry(QtCore.QRect(620, 40, 271, 91))
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.groupBox.setFont(font)
self.groupBox.setObjectName("groupBox")
self.rdtest = QtWidgets.QRadioButton(self.groupBox)
self.rdtest.setGeometry(QtCore.QRect(60, 60, 101, 22))
self.rdtest.setObjectName("rdtest")
self.rdtrain = QtWidgets.QRadioButton(self.groupBox)
self.rdtrain.setGeometry(QtCore.QRect(60, 30, 101, 22))
self.rdtrain.setObjectName("rdtrain")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(10, 40, 601, 411))
self.graphicsView.setObjectName("graphicsView")
self.clear = QtWidgets.QPushButton(self.centralwidget)
self.clear.setGeometry(QtCore.QRect(10, 470, 88, 29))
self.clear.setObjectName("clear")
self.trainNewInput = QtWidgets.QPushButton(self.centralwidget)
self.trainNewInput.setGeometry(QtCore.QRect(500, 470, 111, 29))
self.trainNewInput.setObjectName("trainNewInput")
self.trainbox = QtWidgets.QGroupBox(self.centralwidget)
self.trainbox.setGeometry(QtCore.QRect(620, 150, 271, 171))
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.trainbox.setFont(font)
self.trainbox.setObjectName("trainbox")
self.vtrain = QtWidgets.QLineEdit(self.trainbox)
self.vtrain.setGeometry(QtCore.QRect(100, 70, 101, 29))
self.vtrain.setObjectName("vtrain")
self.label_2 = QtWidgets.QLabel(self.trainbox)
self.label_2.setGeometry(QtCore.QRect(40, 70, 56, 31))
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.trainDefault = QtWidgets.QPushButton(self.trainbox)
self.trainDefault.setGeometry(QtCore.QRect(40, 30, 161, 29))
self.trainDefault.setObjectName("trainDefault")
self.output = QtWidgets.QLabel(self.trainbox)
self.output.setGeometry(QtCore.QRect(10, 130, 271, 17))
self.output.setText("")
self.output.setObjectName("output")
self.output_2 = QtWidgets.QLabel(self.trainbox)
self.output_2.setGeometry(QtCore.QRect(10, 150, 271, 17))
self.output_2.setText("")
self.output_2.setObjectName("output_2")
self.testbox = QtWidgets.QGroupBox(self.centralwidget)
self.testbox.setGeometry(QtCore.QRect(620, 330, 271, 171))
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.testbox.setFont(font)
self.testbox.setObjectName("testbox")
self.pushButton = QtWidgets.QPushButton(self.testbox)
self.pushButton.setGeometry(QtCore.QRect(50, 40, 161, 29))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 911, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "RNA: Numeros "))
self.groupBox.setTitle(_translate("MainWindow", "Opciones:"))
self.rdtest.setText(_translate("MainWindow", "Test"))
self.rdtrain.setText(_translate("MainWindow", "Train"))
self.clear.setText(_translate("MainWindow", "Clear"))
self.trainNewInput.setText(_translate("MainWindow", "Train new Input"))
self.trainbox.setTitle(_translate("MainWindow", "Train:"))
self.label_2.setText(_translate("MainWindow", "% Test:"))
self.trainDefault.setText(_translate("MainWindow", "Train Default Data"))
self.testbox.setTitle(_translate("MainWindow", "Test:"))
self.pushButton.setText(_translate("MainWindow", "Start Test"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Logic class where I want to create a method that draws on the QGraphicsView from the window:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QGraphicsScene
from PyQt5.QtCore import (QLineF, QPointF, QRectF, Qt)
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtWidgets import (QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem,
QGridLayout, QVBoxLayout, QHBoxLayout,
QLabel, QLineEdit, QPushButton)
from window import Ui_MainWindow
from RNA import NumberIA
train = []
train_r = []
test = []
test_r = []
class MyFirstGuiProgram(Ui_MainWindow):
def __init__(self, dialog):
Ui_MainWindow.__init__(self)
self.setupUi(dialog)
self.rdtrain.setChecked(True)
# Connect "add" button with a custom function (addInputTextToListbox)
self.clear.clicked.connect(self.addInputTextToListbox)
self.trainDefault.clicked.connect(self.t_DefaultData)
self.rdtest.clicked.connect(self.enableTest)
self.rdtrain.clicked.connect(self.enableTrain)
def enableTest(self):
self.trainbox.setEnabled(False)
self.trainNewInput.setEnabled(False)
self.testbox.setEnabled(True)
def drawSomething(self):
tes = "f"
def enableTrain(self):
self.trainbox.setEnabled(True)
self.trainNewInput.setEnabled(True)
self.testbox.setEnabled(False)
def addInputTextToListbox(self):
print("Hello world!!!")
def t_DefaultData(self):
ann = NumberIA()
t = self.vtrain.text()
print("Training data: ", t)
global train
global train_r
global test
global test_r
train, train_r, test, test_r = ann.read_file(float(t))
self.output.setText("Train complete...")
ann.crear_red(train, train_r)
accuracy, matrix = ann.probar_red(test, test_r)
self.output_2.setText("Accuracy: " + str(accuracy * 100) + "%")
print("Matris de Confusion:")
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in matrix]))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = MyFirstGuiProgram(MainWindow)
MainWindow.show()
MainWindow.setWindowTitle("RNA: Inteligencia Artificial 2")
ui.enableTrain()
sys.exit(app.exec_())
I cant seem to find examples on how to to this online, the examples I have found are vague to me and cant seem to figure it out.
回答1:
I recommend you inherit from QMainWindow
and implement the Ui_MainWindow
interface, to draw in a QGraphicsView
you must use a QGraphicsScene
, and use its methods, in this case use addRect()
.
from PyQt5 import QtCore, QtGui, QtWidgets
class MyFirstGuiProgram(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
scene = QtWidgets.QGraphicsScene()
self.graphicsView.setScene(scene)
pen = QtGui.QPen(QtCore.Qt.green)
side = 20
for i in range(16):
for j in range(16):
r = QtCore.QRectF(QtCore.QPointF(i*side, j*side), QtCore.QSizeF(side, side))
scene.addRect(r, pen)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyFirstGuiProgram()
w.show()
sys.exit(app.exec_())
回答2:
You can also draw it by QLineF(), it gives more control from design point of view.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
def sceneWithPen(grid):
scene = QGraphicsScene()
view = QGraphicsView()
view.setScene(scene)
# Creating line's colors
red = QColor(qRgb(172, 50, 99))
blue = QColor(qRgb(50, 150, 203))
# Set length of square's side and number of horizontal and vertical lines
vLines = 16
hLines = 16
side = 30
# Set starting values for loops
hor = 0
ver = 0
subdiv = 16
leftX,leftY = 0, 0
rightX, rightY = subdiv*side, 0
bottomX, bottomY= 0, 0
topX, topY = 0, subdiv*side
while ver < vLines:
# Drawing vertical lines
ver = ver + 1
vLine = QLineF(bottomX, bottomY, topX, topY)
bottomX, topX = bottomX + side, topX + side
scene.addLine(vLine, red)
while hor < hLines:
#Drawing horizontal lines
hor = hor + 1
hLine = QLineF(leftX, leftY, rightX, rightY)
leftY, rightY = leftY + side, rightY + side
scene.addLine(hLine, blue)
grid.addWidget(view)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
grid = QGridLayout()
sceneWithPen(grid)
w.setLayout(grid)
w.show()
sys.exit(app.exec_())
It will be like this:

回答3:
Great example @eyllanesc just gave you right above, here is another small example I just happened to have laying around, if you need to draw like a simple free hand.
- Have your MainWindow, for example a QMainWindow or Qwidget or...
- Have a QGraphicsView.
- Set the QGraphicsView's scene with your QGraphicsScene
- Have your own QGraphicsPathItem so you can set properties you need.
- Have the implementation of what you want to draw inside your scene, so it knows how to draw on itself.
Having things in this way you will have control of several scenes knowing how to draw on itself independently, of course if you will need more than one scene.
This example the logic were implemented inside the QGraphicsView, you could move it to your GraphicsScene.
class MainWindow(QMainWindow):
central_widget = None
layout_container = None
def __init__(self):
super(MainWindow, self).__init__()
self.central_widget = QWidget()
self.layout_container = QVBoxLayout()
self.central_widget.setLayout(self.layout_container)
self.setCentralWidget(self.central_widget)
self.layout_container.addWidget(GraphicsView())
class GraphicsView(QGraphicsView):
start = None
end = None
item = None
path = None
def __init__(self):
super(GraphicsView, self).__init__()
self.setScene(QGraphicsScene())
self.path = QPainterPath()
self.item = GraphicsPathItem()
self.scene().addItem(self.item)
def mousePressEvent(self, event):
self.start = self.mapToScene(event.pos())
self.path.moveTo(self.start)
def mouseMoveEvent(self, event):
self.end = self.mapToScene(event.pos())
self.path.lineTo(self.end)
self.start = self.end
self.item.setPath(self.path)
class GraphicsPathItem(QGraphicsPathItem):
def __init__(self):
super(GraphicsPathItem, self).__init__()
pen = QPen()
pen.setColor(Qt.black)
pen.setWidth(10)
self.setPen(pen)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/44193227/how-can-i-draw-inside-existing-qgraphicsview