【问题标题】:Get a custom Qt QGraphicsView to display in a form made with Qt Designer获取自定义 Qt QGraphicsView 以使用 Qt Designer 制作的表单显示
【发布时间】:2019-07-09 13:00:38
【问题描述】:

我将一个自定义 QGraphicsView 放在一起,我可以在 Python 的主窗口中显示它,但我很难将它集成到我使用 Qt Designer 制作的表单中。我如何将其添加到表单中?

另外,我还添加了一个 mousepress 事件。如何使用 Qt Designer 制作的表单将其集成到应用程序中?我已经使用 Qt Designer 构建了一个完整的应用程序,其他一切正常,我只需要能够将此部分与其余部分一起添加。

import sys
from PySide2 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QPushButton, QLineEdit, QAction, QSlider
from PySide2.QtWidgets import QListWidget, QTabWidget, QGraphicsView, QGraphicsScene
from PySide2.QtWidgets import QSpinBox, QWidget, QDialog, QVBoxLayout
from PySide2.QtGui import QPixmap, QImage, QMatrix, QPainter, QColor, QMouseEvent, QCursor
from PySide2.QtCore import QFile, QObject, SIGNAL

import cv2
import numpy as np
import math

class Display_Pixels(QGraphicsView):

    def __init__(self, parent=None):
        QGraphicsView.__init__(self, parent=parent)
        #super().__init__()
        self.initUI()
        self.img = cv2.imread('roi.jpg')

    def initUI(self):      
        self.setGeometry(100, 100, 650, 650)
        #self.setWindowTitle('By Pixel')
        #self.setMouseTracking(True)
        #self.show()
        res = 40 
        self.grid = np.array([ [-1] * res  for n in range(res)]) # list comprehension
        #print(self.grid.shape)


    def paintEvent(self, e):
        qp = QPainter()
        qp.begin(self.viewport())
        self.drawRectangles(qp)
        qp.end()


    def drawRectangles(self, qp, w = 16):
        print("Drawing")
        mode = 0
        x,y = 0,0 # starting position
        lr = 20
        hr = 35
        col = QColor(0, 0, 0)
        col.setNamedColor('#d4d4d4')
        qp.setPen(col)
        #print(self.img.shape)

        for g_row, img_row in zip(self.grid, self.img):
            #print(img_row.shape)
            for g_col, img_col in zip(g_row, img_row):
                r, g, b = (img_col[0], img_col[1], img_col[2])
                #print(r,g,b)

                if g_col == 1:
                    if mode == 0:
                        r = int(math.log(r+1)*lr)
                        g = int(math.log(g+1)*hr)
                        b = int(math.log(b+1)*lr)
                    elif mode == 1:
                        if r+50 <= 220: r = r+50
                        if g+80 <= 255: g = g+80
                        if b+50 <= 220: b = b+50
                    else:
                        if r+70 <= 220: r = r+70
                        if g+140 <= 255: g = g+140
                        if b+70 <= 220: b = b+70

                    qp.setBrush(QColor(r, g, b))
                    qp.drawRect(x, y, w, w)
                else:
                    qp.setBrush(QColor(r, g, b))
                    qp.drawRect(x, y, w, w)

                #qp.setBrush(QColor(200, 0, 0))
                #qp.drawRect(x, y, w, w)
                x = x + w  # move right
            y = y + w # move down
            x = 0 # rest to left edge


    def mousePressEvent(self, QMouseEvent):
        w = 16.0

        #print("MOUSE:")
        #print('(', int(QMouseEvent.x()/w), ', ', int(QMouseEvent.y()/w), ')')
        #print (QMouseEvent.pos())
        x = float(QMouseEvent.x())
        y = float(QMouseEvent.y())
        self.grid[int(y/w)][int(x/w)] = -1 * self.grid[int(y/w)][int(x/w)]

        #print(img[int(y/w), int(x/w), :])

        self.repaint()
        #self.update()


if __name__ == '__main__':
    app = QApplication.instance()
    if app is None: 
        app = QApplication(sys.argv)
    px = Display_Pixels()
    px.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python qt pyqt qt-designer qgraphicsview


    【解决方案1】:

    我认为您的意思是您已成功将此代码添加到主窗口,但您希望能够将其添加到您在设计器中制作的小部件中,而不是严格意义上的主窗口。

    如果是这种情况,您要做的就是在 Qt Designer 中按照您的需要格式化您的小部件,在您想要插入 Display_Pixels QGraphicsView 对象的位置添加一个占位符,例如框架、布局、可能是组等。

    之后不会直接将其添加到框架中,而是该框架使用的任何布局。所以如果你的框架中有一个网格布局,它会是这样的:

        self.Disp_pixel = Display_Pixels()
        widget_name.gridlayout.addWidget(self.Disp_pixel)
    

    很难告诉您该代码将在您的代码中的何处实现,但假设您运行 pyuic5 并获得了 python 输出。您可以将其添加到该输出 python 文件中。我建议使用类似于查看器类的东西来继承生成的输出类并在其中添加小部件。 frame 也是您为图形视图创建的框架的名称,而不是字面意义上的框架。

    此外,我不确定您是否可以在任何类型的小部件上进行显示,我很确定小部件必须是可显示的,例如主窗口小部件或对话框小部件。话虽如此,小部件可以放在其他小部件中。

    这是我给你的一个例子,它有点粗糙,但我认为它会有所帮助:

    import sys
    import cv2
    import numpy as np
    import math
    
    from PyQt5.QtGui import QPainter, QColor
    from PyQt5.QtWidgets import QGraphicsView, QApplication
    
    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file '.\testUI.ui' and .\testMainWin.ui
    #
    # Created by: PyQt5 UI code generator 5.9.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(800, 600)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
            self.gridLayout.setObjectName("gridLayout")
            MainWindow.setCentralWidget(self.centralwidget)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
    
    class Ui_Form(object):
        def setupUi(self, Form):
            Form.setObjectName("Form")
            Form.resize(400, 300)
            self.gridLayout = QtWidgets.QGridLayout(Form)
            self.gridLayout.setObjectName("gridLayout")
            self.frame = QtWidgets.QFrame(Form)
            self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
            self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
            self.frame.setObjectName("frame")
            self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
            self.gridLayout_2.setObjectName("gridLayout_2")
            self.gridLayout.addWidget(self.frame, 0, 0, 1, 1)
    
            self.retranslateUi(Form)
            QtCore.QMetaObject.connectSlotsByName(Form)
    
        def retranslateUi(self, Form):
            _translate = QtCore.QCoreApplication.translate
            Form.setWindowTitle(_translate("Form", "Form"))
    
    
    class FormView(QtWidgets.QWidget, Ui_Form):
        def __init__(self, parent=None):
            super(FormView, self).__init__(parent)
            self.setupUi(self)
            self.disp_pixels = Display_Pixels()
            self.gridLayout_2.addWidget(self.disp_pixels)
    
    
    class MainView(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None):
            super(MainView, self).__init__(parent)
            self.setupUi(self)
    
    
    class Display_Pixels(QGraphicsView):
    
        def __init__(self, parent=None):
            QGraphicsView.__init__(self, parent=parent)
            #super().__init__()
            self.initUI()
            self.img = cv2.imread('resources/images/pic3.jpg')
    
        def initUI(self):
            self.setGeometry(100, 100, 650, 650)
            #self.setWindowTitle('By Pixel')
            #self.setMouseTracking(True)
            #self.show()
            res = 40
            self.grid = np.array([ [-1] * res  for n in range(res)]) # list comprehension
            #print(self.grid.shape)
    
        def paintEvent(self, e):
            qp = QPainter()
            qp.begin(self.viewport())
            self.drawRectangles(qp)
            qp.end()
    
    
        def drawRectangles(self, qp, w = 16):
            print("Drawing")
            mode = 0
            x,y = 0,0 # starting position
            lr = 20
            hr = 35
            col = QColor(0, 0, 0)
            col.setNamedColor('#d4d4d4')
            qp.setPen(col)
            #print(self.img.shape)
    
            for g_row, img_row in zip(self.grid, self.img):
                #print(img_row.shape)
                for g_col, img_col in zip(g_row, img_row):
                    r, g, b = (img_col[0], img_col[1], img_col[2])
                    #print(r,g,b)
    
                    if g_col == 1:
                        if mode == 0:
                            r = int(math.log(r+1)*lr)
                            g = int(math.log(g+1)*hr)
                            b = int(math.log(b+1)*lr)
                        elif mode == 1:
                            if r+50 <= 220: r = r+50
                            if g+80 <= 255: g = g+80
                            if b+50 <= 220: b = b+50
                        else:
                            if r+70 <= 220: r = r+70
                            if g+140 <= 255: g = g+140
                            if b+70 <= 220: b = b+70
    
                        qp.setBrush(QColor(r, g, b))
                        qp.drawRect(x, y, w, w)
                    else:
                        qp.setBrush(QColor(r, g, b))
                        qp.drawRect(x, y, w, w)
    
                    #qp.setBrush(QColor(200, 0, 0))
                    #qp.drawRect(x, y, w, w)
                    x = x + w  # move right
                y = y + w # move down
                x = 0 # rest to left edge
    
    
        def mousePressEvent(self, QMouseEvent):
            w = 16.0
    
            #print("MOUSE:")
            #print('(', int(QMouseEvent.x()/w), ', ', int(QMouseEvent.y()/w), ')')
            #print (QMouseEvent.pos())
            x = float(QMouseEvent.x())
            y = float(QMouseEvent.y())
            self.grid[int(y/w)][int(x/w)] = -1 * self.grid[int(y/w)][int(x/w)]
    
            #print(img[int(y/w), int(x/w), :])
    
            self.repaint()
            #self.update()
    
    
    if __name__ == '__main__':
        app = QApplication.instance()
        if app is None:
            app = QApplication(sys.argv)
        main_window = MainView()
        form = FormView()
        main_window.gridLayout.addWidget(form)
        main_window.show()
    
        sys.exit(app.exec_())
    

    【讨论】:

    • 我添加了以下几行似乎可以解决问题的代码: self.edit_layout = self.window.findChild(QHBoxLayout, 'Editor_Layout') self.view = Display_Pixels() self.view.installEventFilter (self) self.edit_layout.addWidget(self.view) self.view.show()
    • 这无关,但我的编码能力显然不是最好的。我仍然不知道为什么最好为主窗口和表单设置单独的类。另外,子类的意义何在?
    • 这真的取决于你。我喜欢这样把事情分开。我正在使用接近模型、视图、控制器的设计模式,所以它适用于我。不过,您不必这样做。代码几乎是相同的,除了 FormView 中的 2 行代码,我在其中初始化 Display_Pixels 然后将其添加到 gridlayout,这将被移动到 Ui_Form 类。 Ui_Form 也是从我创建的 ui 文件生成的,然后使用 pyuic5 转换为 python,因此您很可能希望自己制作。不过这取决于你。
    • 啊 MVC,我忘了这个!自从我在 uni 上编码课程以来已经有很长时间了。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    相关资源
    最近更新 更多