PySide2 composite widget Hover Effect - python

How to animate position,scale or any other attributes of composed elements inside custom widget, on mouse pointer enters or leaves the QListWidgetItem ?
(see reference image below)
And is there any better way to manage space around ListWidgetItem ?
item_widget.sizeHint() gives unwanted extra space, which is why i added hard coded value to setSizeHint.
ProductMainWindow.py
from PySide2 import QtCore, QtGui, QtWidgets
import productThumbnailWidget
import sys
sys.path.append('E:/code')
class prodMainWindowUI(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setupUi(self)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.productListWidget = QtWidgets.QListWidget(self.centralwidget)
self.productListWidget.setObjectName("productListWidget")
self.productListWidget.setViewMode(QtWidgets.QListWidget.IconMode)
self.productListWidget.setIconSize(QtCore.QSize(256,256))
self.productListWidget.setResizeMode(QtWidgets.QListWidget.Adjust)
self.productListWidget.setMovement(QtWidgets.QListWidget.Static) # disable drag and drop
self.productListWidget.setGridSize(QtCore.QSize(256 + 5, 256 + 5))
self.verticalLayout.addWidget(self.productListWidget)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
for i in range(6):
item = QtWidgets.QListWidgetItem(self.productListWidget)
item_widget = productThumbnailWidget.productThumbWidget()
#item.setSizeHint(item_widget.sizeHint())
item.setSizeHint(QtCore.QSize(256,256))
self.productListWidget.addItem(item)
self.productListWidget.setItemWidget(item, item_widget)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtWidgets.QApplication.translate("MainWindow", "MainWindow", None, -1))
app = QtWidgets.QApplication(sys.argv)
prodUI = prodMainWindowUI()
prodUI.show()
sys.exit(app.exec_())
productThumbnailWidget
from PySide2 import QtCore, QtGui, QtWidgets
class productThumbWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(productThumbWidget, self).__init__(parent)
self.setObjectName("Form")
self.resize(256, 256)
self.setMinimumSize(QtCore.QSize(256, 256))
self.setMaximumSize(QtCore.QSize(256, 256))
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.frame = QtWidgets.QFrame()
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.thumbnailLabel = QtWidgets.QLabel("", self.frame)
self.thumbnailLabel.setObjectName("thumbnailLabel")
self.thumbnailLabel.setScaledContents(False)
self.thumbnailLabel.setGeometry(QtCore.QRect(0, 0, 256, 256))
self.thumbnailLabel.setMinimumSize(QtCore.QSize(256, 256))
self.thumbnailLabel.setMaximumSize(QtCore.QSize(256, 256))
self.thumbnailLabel.setPixmap(QtGui.QPixmap("E:/code/android.png"))
self.backgroundLabel = QtWidgets.QLabel("", self.frame)
self.backgroundLabel.setObjectName("backgroundLabel")
self.backgroundLabel.setGeometry(QtCore.QRect(0, 206, 256, 50))
self.backgroundLabel.setMinimumSize(QtCore.QSize(256, 50))
self.backgroundLabel.setMaximumSize(QtCore.QSize(256, 50))
self.backgroundLabel.setStyleSheet("QLabel#backgroundLabel{\n"
" background: #32353B;\n"
"}")
self.titleLabel = QtWidgets.QLabel("Title", self.frame)
self.titleLabel.setObjectName("titleLabel")
self.titleLabel.setGeometry(QtCore.QRect(10, 218, 246, 25))
self.titleLabel.setMinimumSize(QtCore.QSize(246, 25))
self.titleLabel.setMaximumSize(QtCore.QSize(246, 25))
font = QtGui.QFont()
font.setFamily("SF Pro Display")
font.setPointSize(16)
font.setWeight(75)
font.setBold(True)
self.titleLabel.setFont(font)
self.titleLabel.setStyleSheet("QLabel#titleLabel {\n"
" color: #FFFFFF;\n"
"}")
self.verticalLayout.addWidget(self.frame)
self.setLayout(self.verticalLayout)
Output

The solution is to animate the position of the rectangle using QPropertyAnimation, and to activate the animations using the events QEvent::Enter and QEvent::Leave:
import shiboken2
from PySide2 import QtCore, QtGui, QtWidgets
class RectangleHoverEffect(QtCore.QObject):
def __init__(self, rectangle, parent):
super().__init__(parent)
if not isinstance(rectangle, QtWidgets.QWidget):
raise TypeError(f"{rectangle} must be a QWidget")
if rectangle.parent() is None:
raise ValueError(f"{rectangle} must have a parent")
self.m_rectangle = rectangle
self.m_rectangle.parent().installEventFilter(self)
self.m_animation = QtCore.QPropertyAnimation(
self,
targetObject=self.m_rectangle,
propertyName=b"pos",
duration=300,
easingCurve=QtCore.QEasingCurve.OutQuad,
)
def eventFilter(self, obj, event):
if shiboken2.isValid(self.m_rectangle):
if self.m_rectangle.parent() is obj:
y0 = self.m_rectangle.parent().height()
y1 = self.m_rectangle.parent().height() - self.m_rectangle.height()
if event.type() == QtCore.QEvent.Enter:
self._start_animation(y0, y1)
elif event.type() == QtCore.QEvent.Leave:
self._start_animation(y1, y0)
return super().eventFilter(obj, event)
def _start_animation(self, y0, y1):
self.m_animation.setStartValue(QtCore.QPoint(0, y0))
self.m_animation.setEndValue(QtCore.QPoint(0, y1))
self.m_animation.start()
class ThumbWidget(QtWidgets.QFrame):
def __init__(self, title, pixmap, parent=None):
super().__init__(parent)
self.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.setFrameShadow(QtWidgets.QFrame.Raised)
pixmap_label = QtWidgets.QLabel(pixmap=pixmap, scaledContents=True)
title_label = QtWidgets.QLabel(title)
title_label.setStyleSheet("""color: #FFFFFF""")
font = QtGui.QFont()
font.setFamily("SF Pro Display")
font.setPointSize(16)
font.setWeight(75)
font.setBold(True)
title_label.setFont(font)
background_label = QtWidgets.QLabel(pixmap_label)
background_label.setStyleSheet("background: #32353B;")
background_label.setFixedSize(self.width(), 50)
background_label.move(0, self.height())
background_lay = QtWidgets.QVBoxLayout(background_label)
background_lay.addWidget(title_label)
self.setFixedSize(256, 256)
lay = QtWidgets.QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
lay.setSpacing(0)
lay.addWidget(pixmap_label)
effect = RectangleHoverEffect(background_label, self)
class ProductMainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.product_listwidget = QtWidgets.QListWidget(
viewMode=QtWidgets.QListWidget.IconMode,
iconSize=QtCore.QSize(256, 256),
resizeMode=QtWidgets.QListWidget.Adjust,
movement=QtWidgets.QListWidget.Static,
)
self.product_listwidget.setGridSize(QtCore.QSize(256 + 5, 256 + 5))
for i in range(6):
item = QtWidgets.QListWidgetItem()
item_widget = ThumbWidget(f"Title {i}", QtGui.QPixmap("E:/code/android.png"))
item.setSizeHint(QtCore.QSize(256, 256))
self.product_listwidget.addItem(item)
self.product_listwidget.setItemWidget(item, item_widget)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(self.product_listwidget)
self.resize(960, 480)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = ProductMainWindow()
w.show()
sys.exit(app.exec_())

Related

remove a tuggled checkbox from a scroll area when a button is clicked

I am creating a program that has the function that a checkbox is deleted when it toggled. But when I click the delete button it is not deleted from my scroll area.
I have tried some solutions, but I still have problems on it. An the below code is the best condition I managed until now.
# -*- coding: utf-8 -*-
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(300, 495)
MainWindow.setMaximumSize(QtCore.QSize(300, 16777215))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.frame_3 = QtWidgets.QFrame(self.centralwidget)
self.frame_3.setMaximumSize(QtCore.QSize(500, 50))
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(self.frame_3)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.verticalLayout.addWidget(self.frame_3)
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.scrollArea = QtWidgets.QScrollArea(self.frame)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 260, 357))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.frame_4 = QtWidgets.QFrame(self.scrollAreaWidgetContents)
self.frame_4.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_4.setObjectName("frame_4")
self.verticalLayout_3.addWidget(self.frame_4)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout_2.addWidget(self.scrollArea)
self.verticalLayout.addWidget(self.frame)
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
self.frame_2.setMaximumSize(QtCore.QSize(500, 50))
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(self.frame_2)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.frame_2)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout.addWidget(self.pushButton_2)
self.verticalLayout.addWidget(self.frame_2)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtWidgets.QApplication.translate("MainWindow", "MainWindow", None, -1))
self.label.setText(QtWidgets.QApplication.translate("MainWindow", "Chose Number", None, -1))
self.pushButton.setText(QtWidgets.QApplication.translate("MainWindow", "add", None, -1))
self.pushButton_2.setText(QtWidgets.QApplication.translate("MainWindow", "remove", None, -1))
class Remove_checkBox(QtWidgets.QMainWindow,
Ui_MainWindow):
def __init__(self,n):
super(Remove_checkBox, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.checkBox = []
self.fill_comboBox(n)
#Signals
self.ui.pushButton.clicked.connect(lambda: self.add_param())
self.ui.pushButton_2.clicked.connect(lambda: self.remove_param())
def fill_comboBox(self,n):
self.comboBox = QtWidgets.QComboBox(self.ui.frame_3)
self.comboBox.addItem("")
self.comboBox.setItemText(0, QtWidgets.QApplication.translate("MainWindow", "", None, -1))
self.ui.horizontalLayout_2.addWidget(self.comboBox)
for i in range(n):
self.comboBox.addItem("")
self.comboBox.setItemText(i+1, QtWidgets.QApplication.translate("MainWindow", str(i), None, -1))
def add_param(self):
num = self.comboBox.currentText()
self.checkBox.append(QtWidgets.QCheckBox(self.ui.scrollAreaWidgetContents))
self.ui.verticalLayout_3.addWidget(self.checkBox[-1])
self.checkBox[-1].setText(QtWidgets.QApplication.translate("MainWindow", num, None, -1))
self.ui.verticalLayout_3.removeWidget(self.ui.frame_4)
self.ui.verticalLayout_3.addWidget(self.ui.frame_4)
def remove_param(self):
for i in range(len(self.checkBox)):
if self.checkBox[i].isChecked():
self.ui.verticalLayout_3.removeWidget(self.checkBox[i])
self.ui.verticalLayout_3.removeWidget(self.ui.frame_4)
self.ui.verticalLayout_3.addWidget(self.ui.frame_4)
if __name__ == "__main__":
n=10
app = QtWidgets.QApplication.instance()
if app == None:
app = QtWidgets.QApplication([])
myApp = Remove_checkBox(n)
myApp.show()
sys.exit(app.exec_())
It took me a while to find a solution that worked with my issue, but I finally arrived to the solution below presented, based on: What is best way to remove items from layout in pyqt
def remove_element(self, support_layout, element_to_remove, control_list_name):
"""
This function aims to remove selected elements that are contained in a
widget.
Parameters
----------
support_layout : QtWigget Layout
Layout that supports the object that will be removed
element_to_remove : list with QtWidget
A list with Qtwidget items that ones whant to remove.
control_list_name : list with strings
A list with Qtwidget added items string name
Returns
-------
None.
"""
for i in reversed(range(support_layout.count()-1)):
if element_to_remove[i].isChecked():
# Remove checkbox from frame
item = support_layout.takeAt(i)
widget = item.widget()
widget.deleteLater()
# Remove list selected items
control_list_name.remove(element_to_remove[i].text())
element_to_remove.remove(element_to_remove[i])
With this function my problem was solved I am able to follow my project.

Mapping position of QLabel on an image

I'm trying to segment an image using Qlabels, these Qlabels are placed on an image then the segmentation will be done by pressing the segment button, I have done working on cropping function, its work but the result of the cropped images are not matched with the exact location of labels on the image.
Here is my code:
def crop(self):
i=1
image = self.UserImageLbl.pixmap()
for label in self.labels:
currentQRect = label.geometry()
#pixmap_rect = self.UserImageLbl.geometry()
tr = QtGui.QTransform()
r = tr.mapRect(currentQRect)
cropQPixmap = image.copy(r)
cropQPixmap.save('OUT '+str(i)+'.png')
i=i+1
Complete Code example:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtGui import QDrag, QPixmap, QPainter, QCursor
from PyQt5.QtCore import QMimeData, Qt
class DraggableLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setStyleSheet("border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset; background: transparent;")
self.origin = None
def setLimits(self, rect):
self.limits = rect
def mousePressEvent(self, event):
if not self.origin:
# update the origin point, we'll need that later
self.origin = self.pos()
if event.button() == Qt.LeftButton:
self.mousePos = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton:
# move the box
self.move(self.pos() + event.pos() - self.mousePos)
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
# if the box is not within the image boundaries, move it
# back to the original position
if not self.limits.contains(self.geometry()):
self.move(self.origin)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1050, 800)
Dialog.setMinimumSize(QtCore.QSize(1050, 800))
Dialog.setMaximumSize(QtCore.QSize(1050, 800))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("../.designer/backup/project pic/images icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Dialog.setWindowIcon(icon)
Dialog.setStyleSheet("background-color: rgb(217, 217, 217);\n"
"background-color: rgb(243, 243, 243);")
self.BrowesImageButton = QtWidgets.QPushButton(Dialog)
self.BrowesImageButton.setGeometry(QtCore.QRect(820, 60, 200, 60))
self.BrowesImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.BrowesImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.BrowesImageButton.setFont(font)
self.BrowesImageButton.setStyleSheet("")
self.BrowesImageButton.setCheckable(True)
self.BrowesImageButton.setObjectName("BrowesImageButton")
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setGeometry(QtCore.QRect(820, 170, 211, 131))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.groupBox.setFont(font)
self.groupBox.setLayoutDirection(QtCore.Qt.LeftToRight)
self.groupBox.setObjectName("groupBox")
self.checkBox_Short = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Short.setGeometry(QtCore.QRect(20, 40, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Short.setFont(font)
self.checkBox_Short.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Short.setObjectName("checkBox_Short")
self.checkBox_Short.setEnabled(False)
self.checkBox_Long = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Long.setGeometry(QtCore.QRect(20, 80, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Long.setFont(font)
self.checkBox_Long.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Long.setObjectName("checkBox_Long")
self.checkBox_Long.setEnabled(False)
self.SegmentImageButton = QtWidgets.QPushButton(Dialog)
self.SegmentImageButton.setGeometry(QtCore.QRect(830, 330, 200, 60))
self.SegmentImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.SegmentImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.SegmentImageButton.setFont(font)
self.SegmentImageButton.setStyleSheet("")
self.SegmentImageButton.setCheckable(True)
self.SegmentImageButton.setObjectName("SegmentImageButton")
self.SegmentImageButton.setEnabled(False)
self.UserImageLbl = QtWidgets.QLabel(Dialog)
self.UserImageLbl.setGeometry(QtCore.QRect(40, 40, 750, 500))
self.UserImageLbl.setMinimumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setMaximumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.UserImageLbl.setFrameShadow(QtWidgets.QFrame.Plain)
self.UserImageLbl.setLineWidth(1)
self.UserImageLbl.setMidLineWidth(0)
self.UserImageLbl.setText("")
self.UserImageLbl.setScaledContents(False)
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter)
self.UserImageLbl.setObjectName("UserImageLbl")
self.buttonGroup = QtWidgets.QButtonGroup()
self.buttonGroup.addButton(self.checkBox_Short)
self.buttonGroup.addButton(self.checkBox_Long)
self.label_1 = DraggableLabel(Dialog)
self.label_2 = DraggableLabel(Dialog)
self.label_3 = DraggableLabel(Dialog)
self.label_1.move(820, 470)
self.label_2.move(900, 470)
self.label_3.move(980, 470)
self.labels = [self.label_1, self.label_2, self.label_3]
for label in self.labels:
label.hide()
label.raise_()
self.BrowesImageButton.clicked.connect(self.setImage)
self.checkBox_Long.toggled.connect(self.setBoxSizes)
self.checkBox_Short.toggled.connect(self.setBoxSizes)
self.SegmentImageButton.clicked.connect(self.crop)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Cropping"))
self.BrowesImageButton.setText(_translate("Dialog", "Select Image"))
self.groupBox.setTitle(_translate("Dialog", "Choose Type"))
self.checkBox_Short.setText(_translate("Dialog", "Short "))
self.checkBox_Long.setText(_translate("Dialog", "Long "))
self.SegmentImageButton.setText(_translate("Dialog", "Segment Image"))
def setImage(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png *.jpg *jpeg *.bmp)") # Ask for file
if fileName: # If the user gives a file
pixmap = QtGui.QPixmap(fileName) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.UserImageLbl.width(), self.UserImageLbl.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
self.UserImageLbl.setPixmap(pixmap) # Set the pixmap onto the label
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
#UserImageLbl = DropLabel()
self.checkBox_Short.setEnabled(True)
self.checkBox_Long.setEnabled(True)
def setBoxSizes(self):
if self.checkBox_Short.isChecked():
self.SegmentImageButton.setEnabled(True)
boxSize = 80
else:
boxSize = 60
self.SegmentImageButton.setEnabled(True)
for label in self.labels:
label.setFixedSize(boxSize, boxSize)
label.setLimits(self.UserImageLbl.geometry())
label.show()
def crop(self):
i=1
image = self.UserImageLbl.pixmap()
for label in self.labels:
currentQRect = label.geometry()
#pixmap_rect = self.UserImageLbl.geometry()
tr = QtGui.QTransform()
r = tr.mapRect(currentQRect)
cropQPixmap = image.copy(r)
cropQPixmap.save('OUT '+str(i)+'.png')
i=i+1
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
can someone tell me what's wrong with my code!
Thanks
First of all do not modify the code generated by Qt Designer but you must create a class that inherits from a widget and use the generated class to fill it.
On the other hand considering the above a simpler solution than to make a crop in the QPixmap is to record a section of the window.
from PyQt5 import QtCore, QtGui, QtWidgets
class DraggableLabel(QtWidgets.QLabel):
def __init__(self, parent=None):
super().__init__(parent)
self.setStyleSheet(
"border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset; background: transparent;"
)
self.origin = QtCore.QPoint()
def setLimits(self, rect):
self.limits = rect
def mousePressEvent(self, event):
if self.origin.isNull():
self.origin = self.pos()
if event.button() == QtCore.Qt.LeftButton:
self.mousePos = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
self.move(self.pos() + event.pos() - self.mousePos)
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
if not self.limits.contains(self.geometry()):
self.move(self.origin)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1050, 800)
Dialog.setMinimumSize(QtCore.QSize(1050, 800))
Dialog.setMaximumSize(QtCore.QSize(1050, 800))
icon = QtGui.QIcon()
icon.addPixmap(
QtGui.QPixmap("../.designer/backup/project pic/images icon.png"),
QtGui.QIcon.Normal,
QtGui.QIcon.Off,
)
Dialog.setWindowIcon(icon)
Dialog.setStyleSheet(
"background-color: rgb(217, 217, 217);\n"
"background-color: rgb(243, 243, 243);"
)
self.BrowesImageButton = QtWidgets.QPushButton(Dialog)
self.BrowesImageButton.setGeometry(QtCore.QRect(820, 60, 200, 60))
self.BrowesImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.BrowesImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.BrowesImageButton.setFont(font)
self.BrowesImageButton.setStyleSheet("")
self.BrowesImageButton.setCheckable(True)
self.BrowesImageButton.setObjectName("BrowesImageButton")
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setGeometry(QtCore.QRect(820, 170, 211, 131))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.groupBox.setFont(font)
self.groupBox.setLayoutDirection(QtCore.Qt.LeftToRight)
self.groupBox.setObjectName("groupBox")
self.checkBox_Short = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Short.setGeometry(QtCore.QRect(20, 40, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Short.setFont(font)
self.checkBox_Short.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Short.setObjectName("checkBox_Short")
self.checkBox_Short.setEnabled(False)
self.checkBox_Long = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Long.setGeometry(QtCore.QRect(20, 80, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Long.setFont(font)
self.checkBox_Long.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Long.setObjectName("checkBox_Long")
self.checkBox_Long.setEnabled(False)
self.SegmentImageButton = QtWidgets.QPushButton(Dialog)
self.SegmentImageButton.setGeometry(QtCore.QRect(830, 330, 200, 60))
self.SegmentImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.SegmentImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.SegmentImageButton.setFont(font)
self.SegmentImageButton.setStyleSheet("")
self.SegmentImageButton.setCheckable(True)
self.SegmentImageButton.setObjectName("SegmentImageButton")
self.SegmentImageButton.setEnabled(False)
self.UserImageLbl = QtWidgets.QLabel(Dialog)
self.UserImageLbl.setGeometry(QtCore.QRect(40, 40, 750, 500))
self.UserImageLbl.setMinimumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setMaximumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.UserImageLbl.setFrameShadow(QtWidgets.QFrame.Plain)
self.UserImageLbl.setLineWidth(1)
self.UserImageLbl.setMidLineWidth(0)
self.UserImageLbl.setText("")
self.UserImageLbl.setScaledContents(False)
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter)
self.UserImageLbl.setObjectName("UserImageLbl")
self.buttonGroup = QtWidgets.QButtonGroup()
self.buttonGroup.addButton(self.checkBox_Short)
self.buttonGroup.addButton(self.checkBox_Long)
self.retranslateUi(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Cropping"))
self.BrowesImageButton.setText(_translate("Dialog", "Select Image"))
self.groupBox.setTitle(_translate("Dialog", "Choose Type"))
self.checkBox_Short.setText(_translate("Dialog", "Short "))
self.checkBox_Long.setText(_translate("Dialog", "Long "))
self.SegmentImageButton.setText(_translate("Dialog", "Segment Image"))
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.label_1 = DraggableLabel(self)
self.label_2 = DraggableLabel(self)
self.label_3 = DraggableLabel(self)
self.label_1.move(820, 470)
self.label_2.move(900, 470)
self.label_3.move(980, 470)
self.labels = [self.label_1, self.label_2, self.label_3]
for label in self.labels:
label.hide()
label.raise_()
self.BrowesImageButton.clicked.connect(self.setImage)
self.checkBox_Long.toggled.connect(self.setBoxSizes)
self.checkBox_Short.toggled.connect(self.setBoxSizes)
self.SegmentImageButton.clicked.connect(self.crop)
def setImage(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
None, "Select Image", "", "Image Files (*.png *.jpg *jpeg *.bmp)"
) # Ask for file
if fileName: # If the user gives a file
pixmap = QtGui.QPixmap(fileName) # Setup pixmap with the provided image
pixmap = pixmap.scaled(
self.UserImageLbl.width(),
self.UserImageLbl.height(),
QtCore.Qt.KeepAspectRatio,
) # Scale pixmap
self.UserImageLbl.setPixmap(pixmap) # Set the pixmap onto the label
self.UserImageLbl.setAlignment(
QtCore.Qt.AlignCenter
) # Align the label to center
# UserImageLbl = DropLabel()
self.checkBox_Short.setEnabled(True)
self.checkBox_Long.setEnabled(True)
def setBoxSizes(self):
if self.checkBox_Short.isChecked():
self.SegmentImageButton.setEnabled(True)
boxSize = 80
else:
boxSize = 60
self.SegmentImageButton.setEnabled(True)
for label in self.labels:
label.setFixedSize(boxSize, boxSize)
label.setLimits(self.UserImageLbl.geometry())
label.show()
def crop(self):
base_rect = self.UserImageLbl.geometry()
for i, label in enumerate(self.labels, 1):
label_r = label.geometry()
res_rect = base_rect.intersected(label_r)
if not res_rect.isNull():
label.hide()
pixmap = self.grab(res_rect)
label.show()
pixmap.save("OUT{}.png".format(i))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())

Cropping an image based on its angles with PyQt

I want to make a python script where the program shows an image that contains a rectangle or a square and then the End-user should specify four angles of this shape by drag some pointers on its angles. These pointers will be presented by the program.
Based on these angles the program should crop the shape from the rest of the image.
Example of images that the program will show:
Pointers Images:
What the user should do :
The Output of the program:
How I can do this?
I'm Working with Python3, PyQt5.
This is what I have done so far, which is the process of allowing the user to browse to select an image from his computer and upload it to the program
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QCursor
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1050, 800)
Dialog.setMinimumSize(QtCore.QSize(1050, 800))
Dialog.setMaximumSize(QtCore.QSize(1050, 800))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("project pic/images LPR icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Dialog.setWindowIcon(icon)
Dialog.setStyleSheet("background-color: rgb(217, 217, 217);\n"
"background-color: rgb(243, 243, 243);")
self.UserImageLbl = QtWidgets.QLabel(Dialog)
self.UserImageLbl.setGeometry(QtCore.QRect(130, 60, 800, 600))
self.UserImageLbl.setMinimumSize(QtCore.QSize(800, 600))
self.UserImageLbl.setMaximumSize(QtCore.QSize(800, 600))
self.UserImageLbl.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.UserImageLbl.setFrameShadow(QtWidgets.QFrame.Plain)
self.UserImageLbl.setLineWidth(1)
self.UserImageLbl.setMidLineWidth(0)
self.UserImageLbl.setText("")
self.UserImageLbl.setPixmap(QtGui.QPixmap("project pic/upn.png"))
self.UserImageLbl.setScaledContents(False)
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter)
self.UserImageLbl.setObjectName("UserImageLbl")
self.BrowesImageButton = QtWidgets.QPushButton(Dialog)
self.BrowesImageButton.setGeometry(QtCore.QRect(430, 690, 230, 60))
self.BrowesImageButton.setMinimumSize(QtCore.QSize(230, 60))
self.BrowesImageButton.setMaximumSize(QtCore.QSize(230, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.BrowesImageButton.setFont(font)
self.BrowesImageButton.setStyleSheet("background-color: rgb(0, 214, 157);\n"
"background-color: rgb(0, 170, 127);")
self.BrowesImageButton.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
# self.BrowesImageButton.setStyleSheet("BrowesImageButton:hover { background-color: rgb(0, 214, 157) }" )
self.BrowesImageButton.setCheckable(True)
self.BrowesImageButton.setObjectName("BrowesImageButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.BrowesImageButton.clicked.connect(self.setImage)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", " Cropping Shapes"))
self.BrowesImageButton.setText(_translate("Dialog", "Browse Image"))
def setImage(self):
#fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png *.jpg *jpeg *.bmp);;All Files (*)") # Ask for file
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png)") # Ask for file
if fileName: # If the user gives a file
pixmap = QtGui.QPixmap(fileName) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.UserImageLbl.width(), self.UserImageLbl.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
self.UserImageLbl.setPixmap(pixmap) # Set the pixmap onto the label
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
Thanks in advance.
In this case it is better to use QGraphicsView as it allows us to add other images without the need to scale the image. In the QGraphicsView you get the points where you click on the item that has the image, and then with that information using my previous answer you get the following:
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
current_dir = os.path.dirname(os.path.realpath(__file__))
point_filename = os.path.join(current_dir, "41uu2.png")
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super().__init__(QtWidgets.QGraphicsScene(), parent)
self.pixmap_item = self.scene().addPixmap(QtGui.QPixmap())
self.pixmap_item.setShapeMode(QtWidgets.QGraphicsPixmapItem.BoundingRectShape)
self.setAlignment(QtCore.Qt.AlignCenter)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
def set_image(self, pixmap):
self.pixmap_item.setPixmap(pixmap)
self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
class CropView(GraphicsView):
resultChanged = QtCore.pyqtSignal(QtGui.QPixmap)
def __init__(self, parent=None):
super().__init__(parent)
self.point_items = []
def mousePressEvent(self, event):
if not self.pixmap_item.pixmap().isNull():
sp = self.mapToScene(event.pos())
lp = self.pixmap_item.mapFromScene(sp)
if self.pixmap_item.contains(lp):
size = QtCore.QSize(30, 30)
height = (
self.mapToScene(QtCore.QRect(QtCore.QPoint(), size))
.boundingRect()
.size()
.height()
)
pixmap = QtGui.QPixmap(point_filename)
point_item = QtWidgets.QGraphicsPixmapItem(pixmap, self.pixmap_item)
point_item.setOffset(
-QtCore.QRect(QtCore.QPoint(), pixmap.size()).center()
)
point_item.setPos(lp)
scale = height / point_item.boundingRect().size().height()
point_item.setScale(scale)
self.point_items.append(point_item)
if len(self.point_items) == 4:
points = []
for it in self.point_items:
points.append(it.pos().toPoint())
self.crop(points)
elif len(self.point_items) == 5:
for it in self.point_items[:-1]:
self.scene().removeItem(it)
self.point_items = [self.point_items[-1]]
else:
print("outside")
super().mousePressEvent(event)
def crop(self, points):
# https://stackoverflow.com/a/55714969/6622587
polygon = QtGui.QPolygonF(points)
path = QtGui.QPainterPath()
path.addPolygon(polygon)
source = self.pixmap_item.pixmap()
r = path.boundingRect().toRect().intersected(source.rect())
pixmap = QtGui.QPixmap(source.size())
pixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(pixmap)
painter.setClipPath(path)
painter.drawPixmap(QtCore.QPoint(), source, source.rect())
painter.end()
result = pixmap.copy(r)
self.resultChanged.emit(result)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedSize(1050, 600)
self.left_view = CropView()
self.rigth_view = GraphicsView()
self.left_view.resultChanged.connect(self.rigth_view.set_image)
button = QtWidgets.QPushButton(self.tr("Browse Image"))
button.setStyleSheet("background-color: rgb(0, 214, 157);")
button.setFixedSize(230, 60)
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
button.setFont(font)
button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
button.clicked.connect(self.load_image)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(self.left_view, 0, 0)
lay.addWidget(self.rigth_view, 0, 1)
lay.addWidget(button, 1, 0, 1, 2, alignment=QtCore.Qt.AlignHCenter)
#QtCore.pyqtSlot()
def load_image(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
None, "Select Image", "", "Image Files (*.png)"
)
if fileName:
pixmap = QtGui.QPixmap(fileName)
self.left_view.set_image(pixmap)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Pyqt5. Running string and clock

I have a form with to labels (clock on the top and running string on the bottom). I added linker_by_grid to form (so that all components can proportional resize when form resize).
When I run project, every seconds text in running string is twitching. If I delete linker_by_grid from form, everything is OK, but all components not autoresizing to form.
Code from QtDesigner:
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(498, 299)
self.verticalLayoutWidget = QtWidgets.QWidget(Form)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 479, 281))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget)
font = QtGui.QFont()
font.setPointSize(15)
self.label_2.setFont(font)
self.label_2.setText("")
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.verticalLayout.addWidget(self.label_2)
self.tableWidget = QtWidgets.QTableWidget(self.verticalLayoutWidget)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
self.verticalLayout.addWidget(self.tableWidget)
self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
font = QtGui.QFont()
font.setPointSize(15)
self.label.setFont(font)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "Running string ... "))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_()) ```
main file:
``` from PyQt5 import QtWidgets
from PyQt5.QtCore import QTimer, QTime
import sys
import untitled
class Widget(QtWidgets.QWidget):
def __init__(self):
super(Widget, self).__init__()
self.ui = untitled.Ui_Form()
self.ui.setupUi(self)
self.x = 477
self.y = self.height() - 30
self.ui.label.move(self.x, self.y)
self.timer = QTimer(self)
self.timer.timeout.connect(self.move_label_left)
self.timer.start(100)
self.timer2 = QTimer(self)
self.timer2.timeout.connect(self.show_clock)
self.timer2.start(1000)
def move_label_left(self):
if self.x == -477:
self.x = 477
self.x -= 2
self.ui.label.move(self.x, self.height() - 30)
else:
self.x -= 2
self.ui.label.move(self.x, self.height() - 30)
def show_clock(self):
time = QTime.currentTime()
text = time.toString('hh:mm:ss')
self.ui.label_2.setText(text)
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_()) ```
You need to remove the label from the layout
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtWidgets
from PyQt5.QtCore import QTimer, QTime
#import untitled
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(500, 350) #(498, 299)
# self.verticalLayoutWidget = QtWidgets.QWidget(Form)
# self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 479, 281))
# self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(Form) #(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 50) # + 50
self.verticalLayout.setObjectName("verticalLayout")
self.label_2 = QtWidgets.QLabel(Form) #(self.verticalLayoutWidget)
font = QtGui.QFont()
font.setPointSize(15)
self.label_2.setFont(font)
self.label_2.setText("")
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.verticalLayout.addWidget(self.label_2)
self.tableWidget = QtWidgets.QTableWidget(Form) #(self.verticalLayoutWidget)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(4)
self.tableWidget.setRowCount(3)
self.verticalLayout.addWidget(self.tableWidget)
# self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
# font = QtGui.QFont()
# font.setPointSize(15)
# self.label.setFont(font)
# self.label.setObjectName("label")
# self.verticalLayout.addWidget(self.label)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
# self.label.setText(_translate("Form", "Running string ... "))
class Widget(QtWidgets.QWidget):
def __init__(self):
super(Widget, self).__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.tableWidget.setAlternatingRowColors(True) # +
self.ui.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) # +
self.labelMove = QtWidgets.QLabel("Running string ... ", self) # +
font = QtGui.QFont() # +
font.setPointSize(15) # +
self.labelMove.setFont(font) # +
self.x = self.width() #477
self.y = self.height() - 30
self.labelMove.move(self.x, self.y)
self.timer = QTimer(self)
self.timer.timeout.connect(self.move_label_left)
self.timer.start(15) # 100
self.timer2 = QTimer(self)
self.timer2.timeout.connect(self.show_clock)
self.timer2.start(1000)
def move_label_left(self):
if self.x <= -150: # 477
self.x = self.width() # 477
self.x -= 1
self.labelMove.move(self.x, self.height() - 30)
else:
self.x -= 1
self.labelMove.move(self.x, self.height() - 30)
self.labelMove.adjustSize() # +++
def show_clock(self):
time = QTime.currentTime()
text = time.toString('hh:mm:ss')
self.ui.label_2.setText(text)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())

Display a down arrow in a widget

I want to display a downward facing arrow (or any shape really) in QT designer between two lineEdits. This seems simple, but I can't seem to find an answer. I have code below that shows what I am trying to do. Any help is greatly appreciated!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPainter, QBrush, QPen
from PyQt5.QtCore import Qt
class Ui_Frame(object):
def setupUi(self, Frame):
Frame.setObjectName("Frame")
Frame.resize(472, 408)
Frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
Frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.verticalLayout = QtWidgets.QVBoxLayout(Frame)
self.verticalLayout.setObjectName("verticalLayout")
self.lineEdit = QtWidgets.QLineEdit(Frame)
self.lineEdit.setAlignment(QtCore.Qt.AlignCenter)
self.lineEdit.setObjectName("lineEdit")
self.verticalLayout.addWidget(self.lineEdit)
self.frame = QtWidgets.QFrame(Frame)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.frame_3 = QtWidgets.QFrame(self.frame)
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_2 = QtWidgets.QLabel(self.frame_3)
self.label_2.setObjectName("label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.lineEdit_4 = QtWidgets.QLineEdit(self.frame_3)
self.lineEdit_4.setObjectName("lineEdit_4")
self.horizontalLayout_2.addWidget(self.lineEdit_4)
self.verticalLayout_2.addWidget(self.frame_3)
# I would like to paint a shape on this frame (frame_paint) using method paintEvent
self.frame_paint = QtWidgets.QFrame(self.frame)
self.frame_paint.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_paint.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_paint.setObjectName("frame_paint")
self.verticalLayout_2.addWidget(self.frame_paint)
self.frame_2 = QtWidgets.QFrame(self.frame)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(self.frame_2)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit_3 = QtWidgets.QLineEdit(self.frame_2)
self.lineEdit_3.setObjectName("lineEdit_3")
self.horizontalLayout.addWidget(self.lineEdit_3)
self.verticalLayout_2.addWidget(self.frame_2)
self.verticalLayout.addWidget(self.frame)
self.retranslateUi(Frame)
QtCore.QMetaObject.connectSlotsByName(Frame)
def retranslateUi(self, Frame):
_translate = QtCore.QCoreApplication.translate
Frame.setWindowTitle(_translate("Frame", "Frame"))
self.lineEdit.setText(_translate("Frame", "(Name of research project)"))
self.label_2.setText(_translate("Frame", "Level 1:"))
self.label.setText(_translate("Frame", "Level 2:"))
### I want this paintEvent to go to the self.frame_paint
def paintEvent(self, e):
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 10, Qt.SolidLine))
painter.drawRect(100, 15, 400, 200)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Frame = QtWidgets.QFrame()
ui = Ui_Frame()
ui.setupUi(Frame)
Frame.show()
sys.exit(app.exec_())
After some time, I figured it out. I was missing the whole thing about having two py files and implementing painting on a scene. Here is my code that works.
class MainWindow_RUA(QtWidgets.QMainWindow, Ui_MainWindow_RUA):
def __init__(self, parent=None):
super(MainWindow_RUA, self).__init__(parent)
self.setupUi(self)
scene = Painter()
self.graphicsView.setScene(scene)
class Painter(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.black))
pen.setWidth(2)
brush = QtGui.QBrush(pen.color().darker(150))
self.addLine(100, 200, 100, 100, pen)
self.addLine(85, 175, 100, 200, pen)
self.addLine(100, 200, 115, 175, pen)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
application = MainWindow_RUA()
application.show()
sys.exit(app.exec_())

Categories