Search code examples
pythonpython-3.xpyqtpyqt5qpainter

PyQt5 Automatic drawing from input value


I have recently created a widget with Qpaint, which I want to pass value to it, at the same time force the Qpaint Widget to draw from input values. The idea is to define a data value from a Qdialog and pass it to main widget, and pass the value to Qpaint Widget class. I would like to have, when user clicks on the button 'Getting values' a dialog widget would appear and insert some int values, then pass it to main Widget. from there pass value to correct class Paint. Which would draw and display the result. I tried with Qlabel, to assign value first to Qlabel or QlineEdit,

class Button(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Button, self).__init__(parent)
          ---------

        self.value = QtWidgets.QLabel()

           --------

Then inside the paint class call the value or text of those. then assign it to Qpaint event. But seems does not work.'

class Paint(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Paint, self).__init__(parent)

        self.button = Button()
        self.Value = self.button.value

          ---------

        painter.drawRect(100,100,250,250)     <----- instead of value 250 having self.Value

The code Main.py

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from datainput import *


class Foo(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Foo, self).__init__(parent)
        self.setGeometry(QtCore.QRect(200, 100, 800, 800))

        self.button = Button()
        self.paint = Paint()

        self.lay = QtWidgets.QVBoxLayout()
        self.lay.addWidget(self.paint)
        self.lay.addWidget(self.button)
        self.setLayout(self.lay)

class Paint(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Paint, self).__init__(parent)

        self.button = Button()
        self.Value = self.button.value

        self.setBackgroundRole(QtGui.QPalette.Base)       
        self.setAutoFillBackground(True)

    def paintEvent(self, event):

        self.pen = QtGui.QPen()
        self.brush = QtGui.QBrush( QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.pen)
        painter.setBrush(self.brush)
        painter.drawRect(100,100,250,250)
        painter.setBrush(QtGui.QBrush())

class Button(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Button, self).__init__(parent)

        getbutton = QtWidgets.QPushButton('Getting values')
        Alay = QtWidgets.QVBoxLayout(self)
        Alay.addWidget(getbutton)

        self.value = QtWidgets.QLabel()

        getbutton.clicked.connect(self.getbuttonfunc)


    def getbuttonfunc(self):
        subwindow=Dinput()
        subwindow.setWindowModality(QtCore.Qt.ApplicationModal)
        if subwindow.exec_() == QtWidgets.QDialog.Accepted:
            self._output = subwindow.valueEdit.text()
            return self.value.setText(self._output)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Foo()
    w.show()
    sys.exit(app.exec_())

Input Qdialog code, datainput.py

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Dinput(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Dinput, self).__init__(parent)

        valuelabel = QtWidgets.QLabel('Input: ')
        self.valueEdit = QtWidgets.QLineEdit()

        buttonBox = QtWidgets.QDialogButtonBox()
        buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(self.accept) 
        buttonBox.rejected.connect(self.close)

        self.Alay = QtWidgets.QHBoxLayout()
        self.Alay.addWidget(valuelabel)
        self.Alay.addWidget(self.valueEdit)

        self.Blay = QtWidgets.QVBoxLayout()
        self.Blay.addLayout(self.Alay)
        self.Blay.addWidget(buttonBox)
        self.setLayout(self.Blay)

    def closeEvent(self, event):
        super(Dinput, self).closeEvent(event)

    def accept(self):          
        super(Dinput, self).accept()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Dinput()
    w.show()
    sys.exit(app.exec_())

Visualization

enter image description here

I appreciate any help. Thankssss


Solution

  • datainput is irrelevant, your task is only to obtain a number so for space question I will not use it and instead I will use QInputDialog::getInt(). Going to the problem, the strategy in these cases where the value can be obtained at any time is to notify the change to the other view through a signal, in the slot that receives the value is to update a variable that stores the value and call update so that it calls when necessary to paintEvent, and in the paintEvent use the variable that stores the value.

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Foo(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Foo, self).__init__(parent)
            self.setGeometry(QtCore.QRect(200, 100, 800, 800))
    
            self.button = Button()
            self.paint = Paint()
            self.button.valueChanged.connect(self.paint.set_size_square)
    
            self.lay = QtWidgets.QVBoxLayout(self)
            self.lay.addWidget(self.paint)
            self.lay.addWidget(self.button)
    
    class Paint(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Paint, self).__init__(parent)
            self.setBackgroundRole(QtGui.QPalette.Base)     
            self.setAutoFillBackground(True)
            self._size_square = 250
    
        @QtCore.pyqtSlot(int)
        def set_size_square(self, v):
            self._size_square = v
            self.update()
    
        def paintEvent(self, event):
            pen = QtGui.QPen()
            brush = QtGui.QBrush( QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)
            painter = QtGui.QPainter(self)
            painter.setRenderHint(QtGui.QPainter.Antialiasing)
            painter.setPen(pen)
            painter.setBrush(brush)
            r = QtCore.QRect(QtCore.QPoint(100, 100), self._size_square*QtCore.QSize(1, 1))
            painter.drawRect(r)
    
    class Button(QtWidgets.QWidget):
        valueChanged = QtCore.pyqtSignal(int)
    
        def __init__(self, parent=None):
            super(Button, self).__init__(parent)
            getbutton = QtWidgets.QPushButton('Getting values')
            Alay = QtWidgets.QVBoxLayout(self)
            Alay.addWidget(getbutton)
            self.value = QtWidgets.QLabel()
            getbutton.clicked.connect(self.getbuttonfunc)
    
        @QtCore.pyqtSlot()
        def getbuttonfunc(self):
            number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
                                             self.tr("Input:"), 1, 1)
            if ok:
                self.valueChanged.emit(number)
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        w = Foo()
        w.show()
        sys.exit(app.exec_())