Pyqt5. Running string and clock - python

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_())

Related

Why can't My GUI program built by PyQt5 show?

I refer to the article1 to build my GUI by PyQt5,The difference between the program of the article and mine is the module <img_controller.py>. When I initilize my img_controller instance,I only need the parameter ui(the class I got from Qtdesigner)and my program ,img_controller. will revise the attributes of ui. Initialize the parameters of img_controller.py according to 1 are directed inputted attributes of ui.
When I run the program got from 1, it can work normally; but I run my program, I can't get the mainwindow and the wrong message hints that "AttributeError: 'Img_controller' object has no attribute 'ui'".I don't know where is my problem, because in the function __ init __ of Img_controller(class), I state that "self.ui = ui",anyone can tell me the problem, thank you very much.
The following is my program:
UI.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1085, 857)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(110, 20, 861, 491))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.scrollArea = QtWidgets.QScrollArea(self.verticalLayoutWidget)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
# self.scrollAreaWidgetContents = QtWidgets.QWidget()
# self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 857, 487))
# self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.image_label = QtWidgets.QLabel(self.scrollArea) #此處有更動
self.image_label.setGeometry(QtCore.QRect(10, 10, 841, 471))
self.image_label.setObjectName("image_label")
self.scrollArea.setWidget(self.image_label) #此處有更動
self.verticalLayout.addWidget(self.scrollArea)
self.btn_zoomin = QtWidgets.QPushButton(self.centralwidget)
self.btn_zoomin.setGeometry(QtCore.QRect(330, 530, 75, 23))
self.btn_zoomin.setObjectName("btn_zoomin")
self.btn_zoomout = QtWidgets.QPushButton(self.centralwidget)
self.btn_zoomout.setGeometry(QtCore.QRect(640, 530, 75, 23))
self.btn_zoomout.setObjectName("btn_zoomout")
self.slider = QtWidgets.QSlider(self.centralwidget)
self.slider.setGeometry(QtCore.QRect(440, 530, 160, 22))
self.slider.setOrientation(QtCore.Qt.Horizontal)
self.slider.setObjectName("slider")
self.btn_open = QtWidgets.QPushButton(self.centralwidget)
self.btn_open.setGeometry(QtCore.QRect(140, 530, 75, 23))
self.btn_open.setObjectName("btn_open")
self.label_resolution = QtWidgets.QLabel(self.centralwidget)
self.label_resolution.setGeometry(QtCore.QRect(770, 530, 75, 15))
self.label_resolution.setObjectName("label_resolution")
self.label_filename = QtWidgets.QLabel(self.centralwidget)
self.label_filename.setGeometry(QtCore.QRect(130, 660, 111, 41))
self.label_filename.setObjectName("label_filename")
self.label_img_shape = QtWidgets.QLabel(self.centralwidget)
self.label_img_shape.setGeometry(QtCore.QRect(540, 620, 411, 51))
self.label_img_shape.setObjectName("label_img_shape")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1085, 21))
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.image_label.setText(_translate("MainWindow", "image"))
self.btn_zoomin.setText(_translate("MainWindow", "zoom_in"))
self.btn_zoomout.setText(_translate("MainWindow", "zoom_out"))
self.btn_open.setText(_translate("MainWindow", "open file"))
self.label_resolution.setText(_translate("MainWindow", "TextLabel"))
self.label_filename.setText(_translate("MainWindow", "file_name"))
self.label_img_shape.setText(_translate("MainWindow", "TextLabel"))
img_controller.py
from PyQt5 import QtCore, QtGui
import cv2
from UI import Ui_MainWindow
class Img_controller(object):
def __init__(self, ui:Ui_MainWindow, img_ratio:int = 50):
super(Img_controller, self).__init__()
self.img_path = 'sad.jpg'
self.img_ratio = img_ratio
self.read_img(self.img_path)
self.ui = ui
def read_img(self,img_path):
try:
self.img = cv2.imread(img_path)
self.orig_h, self.orig_w, self.orig_c = self.img.shape
self.img_path = img_path
except:
self.img = cv2.imread(self.img_path)
self.orig_h, self.orig_w, self.orig_c = self.img.shape
bytesPerline = self.orig_h*self.orig_c
self.qimg = QtGui.QImage(self.img, self.orig_w, self.orig_h, bytesPerline, QtGui.QImage.Format_RGB888).rgbSwapped()
self.origin_qpixmap = QtGui.QPixmap.fromImage(self.qimg)
self.img_ratio = 50
self.set_img_ratio()
def set_img_ratio(self):
self.img_ratio = pow(10, (self.img_ratio - 50)/50)
qpixmap_height = self.orig_h * self.img_ratio
self.qpixmap = self.origin_qpixmap.scaledToHeight(qpixmap_height)
#更新UI介面上的顯示
self.__update_img()
self.__update_text_ratio()
self.__update_text_img_shape()
self.__update_text_file_path()
def __update_img(self):
self.ui.image_label.setPixmap(self.qpixmap)
self.ui.image_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
def __update_text_file_path(self):
self.ui.label_filename.setText(f"File path = {self.img_path}")
def __update_text_ratio(self):
self.ui.label_resolution.setText(f"{int(100*self.img_ratio)} %")
def __update_text_img_shape(self):
current_text = f"Current img shape = ({self.qpixmap.width()}, {self.qpixmap.height()})"
origin_text = f"Origin img shape = ({self.origin_width}, {self.origin_height})"
self.ui.label_img_shape.setText(current_text+"\t"+origin_text)
def set_zoom_in(self):
self.img_ratio = max(0, self.img_ratio - 1)
self.set_img_ratio()
def set_zoom_out(self):
self.img_ratio = min(100, self.img_ratio + 1)
self.set_img_ratio()
def set_slider_value(self, value):
self.img_ratio = value
self.set_img_ratio()
controller.py
from PyQt5 import QtCore,QtWidgets,QtGui
from PyQt5.QtWidgets import QMainWindow,QFileDialog
from img_controller import Img_controller
from UI import Ui_MainWindow
class Ui_controller(QMainWindow):
def __init__(self):
super(Ui_controller,self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setup_control()
def setup_control(self):
self.img_controller = Img_controller(ui = self.ui)
self.ui.btn_open.clicked.connect(self.open_file)
self.ui.btn_zoomin.clicked.connect(self.img_controller.set_zoom_in)
self.ui.btn_zoomout.clicked.connect(self.img_controller.set_zoom_out)
self.ui.slider.valueChanged.connect(self.getslidervalue)
def open_file(self):
filename, filetype = QFileDialog.getOpenFileName(self, "Open file", "./") # start path
self.init_new_picture(filename)
def init_new_picture(self, filename):
self.ui.slider.setProperty("value", 50)
self.img_controller.read_img(filename)
def getslidervalue(self):
self.img_controller.set_slider_value(self.ui.slider.value()+1)
What you DIDN'T say was the key piece of information -- the rest of the traceback. Notice that Img_controller.__init__ calls self.read_img, which calls self.set_img_ratio, which calls self.__update_img, which uses self.ui, and that all happens BEFORE you set self.ui. You need to swap the order of that initialization.

PyQt5 Menubars, Backgrounds and Dragging Main Window [duplicate]

This question already has answers here:
Qt 4: Move window without title bar
(2 answers)
Closed 2 years ago.
I am trying to make an image viewer in PyQt5 with Python.
So far I have the functionality I want at the moment, this is a matter of styling the GUI how I would like it.
It looks almost how I want it.
I struggled to get that transparentish background, but managed to by setting windowflags to FramelesswindowHint. Unfortunately, now I don't have a menubar to close the application if I want to and drag the window around. I figure I will have to craft my own bar if I want to style it in a way that suits my background, which is fine, adding an X button to close the window shouldn't be too much of an issue.
My question is, how do I make it so I can drag the window around? I could make a rectangle widget and position it at the top with my buttons, but how do I get the whole window to move if the user clicks and drags it? I know similar questions are around, but I'm not sure how to make click and drag functions yet on objects in PyQt5 and it seems they use different layout strategies so I'm finding them confusing.
Here is my code:
from PyQt5 import QtCore, QtGui, QtWidgets
import os
class Ui_MainWindow(object):
def __init__(self):
cwd = r"C:\Users\chees\PycharmProjects\PYQT5GUI\images"
self.imagelist = []
self.imagepaths = []
self.imagecount = 0
for a, b, c in os.walk(cwd):
self.imagelist = c
for i in c:
self.imagepaths.append(a + "\\" + i)
print(self.imagepaths)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.NonModal)
MainWindow.resize(661, 580)
MainWindow.setAttribute(QtCore.Qt.WA_TranslucentBackground)
MainWindow.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.b = QtWidgets.QWidget(self.centralwidget)
self.b.setGeometry(QtCore.QRect(0, 0, MainWindow.width(), MainWindow.height()))
self.b.setStyleSheet("background-color: rgba(0, 0, 0, 70%); border:1px; border-radius:25px;")
self.imageviewer = QtWidgets.QLabel(self.centralwidget)
self.imageviewer.setGeometry(QtCore.QRect(170, 60, 351, 321))
self.imageviewer.setText("")
self.imageviewer.setPixmap(QtGui.QPixmap("images/IMG1.jpg"))
self.imageviewer.setScaledContents(True)
self.imageviewer.setObjectName("imageviewer")
self.backward_button = QtWidgets.QPushButton(self.centralwidget)
self.backward_button.setGeometry(QtCore.QRect(50, 471, 120, 50))
self.backward_button.setObjectName("backward_button")
self.backward_button.clicked.connect(self.backward)
self.forward_button = QtWidgets.QPushButton(self.centralwidget)
self.forward_button.setGeometry(QtCore.QRect(510, 470, 120, 50))
self.forward_button.setObjectName("forward_button")
self.forward_button.clicked.connect(self.forward)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
self.statusbar.setStyleSheet("background-color: rgba(255,255,255, 40%)")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.changesize()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.backward_button.setText(_translate("MainWindow", "<<"))
self.forward_button.setText(_translate("MainWindow", ">>"))
def changesize(self):
self.imageviewer.adjustSize()
if self.imageviewer.width() < 500:
MainWindow.resize(500, self.imageviewer.height() + 200)
self.b.resize(500, self.imageviewer.height() + 200)
self.imageviewer.move((500-self.imageviewer.width())//2, 55)
else:
MainWindow.resize((self.imageviewer.width() + self.imageviewer.width() // 8), (self.imageviewer.height() + 200))
self.b.resize((self.imageviewer.width() + self.imageviewer.width() // 8),
(self.imageviewer.height() + 200))
self.imageviewer.move(self.imageviewer.width() // 16, 55)
self.forward_button.move(MainWindow.width()-150,MainWindow.height()-80)
self.backward_button.move(30, MainWindow.height() - 80)
self.statusbar.showMessage(self.imagepaths[self.imagecount])
def flipmode(self):
self.imageviewer.setPixmap(QtGui.QPixmap("images\\" + self.imagelist[self.imagecount]))
self.changesize()
print(self.imageviewer.height(), self.imageviewer.width())
def forward(self):
self.imagecount += 1
if self.imagecount == len(self.imagelist):
self.imagecount = 0
self.flipmode()
def backward(self):
self.imagecount -= 1
if self.imagecount < 0:
self.imagecount = len(self.imagelist)-1
self.flipmode()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
print(ui.imagelist)
sys.exit(app.exec_())
Do not modify the code generated by Qt Designer but create another class that inherits
from the appropriate widget and use the initial class to fill it.
One of the ways to drag a window might look like this:
self._old_pos = None
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self._old_pos = event.pos()
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self._old_pos = None
def mouseMoveEvent(self, event):
if not self._old_pos:
return
delta = event.pos() - self._old_pos
self.move(self.pos() + delta)
from PyQt5 import QtCore, QtGui, QtWidgets
import os
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.NonModal)
MainWindow.resize(661, 580)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.b = QtWidgets.QWidget(self.centralwidget)
self.b.setGeometry(QtCore.QRect(0, 0, MainWindow.width(), MainWindow.height()))
self.b.setStyleSheet("background-color: rgba(0, 0, 0, 70%); border:1px; border-radius:25px;")
self.imageviewer = QtWidgets.QLabel(self.centralwidget)
self.imageviewer.setGeometry(QtCore.QRect(170, 60, 351, 321))
self.imageviewer.setText("")
self.imageviewer.setPixmap(QtGui.QPixmap("images/IMG1.jpg"))
self.imageviewer.setScaledContents(True)
self.imageviewer.setObjectName("imageviewer")
self.backward_button = QtWidgets.QPushButton(self.centralwidget)
self.backward_button.setGeometry(QtCore.QRect(50, 471, 120, 50))
self.backward_button.setObjectName("backward_button")
self.backward_button.clicked.connect(self.backward)
self.forward_button = QtWidgets.QPushButton(self.centralwidget)
self.forward_button.setGeometry(QtCore.QRect(510, 470, 120, 50))
self.forward_button.setObjectName("forward_button")
self.forward_button.clicked.connect(self.forward)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
self.statusbar.setStyleSheet("background-color: rgba(255,255,255, 40%)")
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.backward_button.setText(_translate("MainWindow", "<<"))
self.forward_button.setText(_translate("MainWindow", ">>"))
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
# cwd = r"C:\Users\chees\PycharmProjects\PYQT5GUI\images"
cwd = "D:/_Qt/__Qt/images"
self.imagelist = []
self.imagepaths = []
self.imagecount = 0
for a, b, c in os.walk(cwd):
self.imagelist = c
for i in c:
self.imagepaths.append(a + "\\" + i)
#print(self.imagepaths)
self.changesize()
#++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
self._old_pos = None
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self._old_pos = event.pos()
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self._old_pos = None
def mouseMoveEvent(self, event):
if not self._old_pos:
return
delta = event.pos() - self._old_pos
self.move(self.pos() + delta)
# ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
def changesize(self):
self.imageviewer.adjustSize()
if self.imageviewer.width() < 500:
self.resize(500, self.imageviewer.height() + 200)
self.b.resize(500, self.imageviewer.height() + 200)
self.imageviewer.move((500-self.imageviewer.width())//2, 55)
else:
self.resize((self.imageviewer.width() + self.imageviewer.width() // 8), (self.imageviewer.height() + 200))
self.b.resize((self.imageviewer.width() + self.imageviewer.width() // 8),
(self.imageviewer.height() + 200))
self.imageviewer.move(self.imageviewer.width() // 16, 55)
self.forward_button.move(self.width()-150, self.height()-80)
self.backward_button.move(30, self.height() - 80)
self.statusbar.showMessage(self.imagepaths[self.imagecount])
def flipmode(self):
self.imageviewer.setPixmap(QtGui.QPixmap("images\\" + self.imagelist[self.imagecount]))
self.changesize()
# print(self.imageviewer.height(), self.imageviewer.width())
def forward(self):
self.imagecount += 1
if self.imagecount == len(self.imagelist):
self.imagecount = 0
self.flipmode()
def backward(self):
self.imagecount -= 1
if self.imagecount < 0:
self.imagecount = len(self.imagelist)-1
self.flipmode()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
# MainWindow = QtWidgets.QMainWindow()
# ui = Ui_MainWindow()
# ui.setupUi(MainWindow)
# MainWindow.show()
w = MainWindow()
w.show()
# print(ui.imagelist)
sys.exit(app.exec_())

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_())

PySide2 composite widget Hover Effect

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_())

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