PyQt: Put scrollbars in this - python

Here's my class:
class ChildFoundDlg(QDialog):
#__init__ function:
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.resize(500, 270)
self.setMaximumSize(500, 540)
self.GridLayout = QtGui.QGridLayout(self)
def buttons(self, a, b, c): #a = 0, b = 5 c = 7
self.font = QtGui.QFont("Sans Serif", 10, QFont.Normal)
self.label = QtGui.QLabel(self)
self.label.setText(QtGui.QApplication.translate("Form", "Μήπως εννοείτε την/τον:", None, QtGui.QApplication.UnicodeUTF8))
self.label.setFont(self.font)
self.GridLayout.addWidget(self.label, a, 0, 1, 1)
self.label2 = QtGui.QLabel(self)
self.GridLayout.addWidget(self.label2, a, 1, 1, 1)
self.label2.setFont(self.font)
self.pushButton = QtGui.QPushButton(self)
self.GridLayout.addWidget(self.pushButton, b, 0, 2, 1)
self.pushButton.setText(QtGui.QApplication.translate("Form", "Υπότροπος", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
self.pushButton2 = QtGui.QPushButton(self)
self.GridLayout.addWidget(self.pushButton2, b, 1, 2, 1)
self.pushButton2.setText(QtGui.QApplication.translate("Form", "Αναβολή", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton2.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
self.pushButton3 = QtGui.QPushButton(self)
self.GridLayout.addWidget(self.pushButton3, c, 1, 2, 1)
self.pushButton3.setText(QtGui.QApplication.translate("Form", "Ακύρωση", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton3.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
self.pushButton3.clicked.connect(self.reject)
What I want to achieve is that, when I call self.buttons many times with different values,
when the maximum size of the dialog is reached, stop enlarging but instead put scrollbars, if you understand what I'm saying... How can I do that?

Here is an example using a QScrollArea:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtCore, QtGui
class myDialog(QtGui.QDialog):
_buttons = 0
def __init__(self, parent=None):
super(myDialog, self).__init__(parent)
self.pushButton = QtGui.QPushButton(self)
self.pushButton.setText(QtGui.QApplication.translate("self", "Add Button!", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.clicked.connect(self.on_pushButton_clicked)
self.scrollArea = QtGui.QScrollArea(self)
self.scrollArea.setWidgetResizable(True)
self.scrollAreaWidgetContents = QtGui.QWidget(self.scrollArea)
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 380, 247))
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout = QtGui.QVBoxLayout(self)
self.verticalLayout.addWidget(self.pushButton)
self.verticalLayout.addWidget(self.scrollArea)
self.verticalLayoutScroll = QtGui.QVBoxLayout(self.scrollAreaWidgetContents)
#QtCore.pyqtSlot()
def on_pushButton_clicked(self):
self._buttons += 1
pustButtonName = u"Button {0}".format(self._buttons)
pushButton = QtGui.QPushButton(self.scrollAreaWidgetContents)
pushButton.setText(pustButtonName)
self.verticalLayoutScroll.addWidget(pushButton)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('myDialog')
main = myDialog()
main.show()
sys.exit(app.exec_())

Related

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

MouseTracking events does not seem to function

I have this small window code and I want to be able to get the x/y location for the mouse when clicked. I do not see what is the problem in this code, and why it doesn't show me the mouse location
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QGraphicsScene, QMainWindow
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
class Ui_layout_window(QMainWindow):
def setupUi(self, layout_window):
layout_window.setObjectName("layout_window")
layout_window.resize(749, 711)
layout_window.setMouseTracking(True)
self.centralwidget = QtWidgets.QWidget(layout_window)
self.centralwidget.setMouseTracking(True)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setContentsMargins(10, 10, 10, 10)
self.gridLayout.setSpacing(10)
self.gridLayout.setObjectName("gridLayout")
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 727, 609))
self.scrollAreaWidgetContents.setMouseTracking(True)
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.gridLayout_2 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents)
self.gridLayout_2.setContentsMargins(5, 5, 5, 5)
self.gridLayout_2.setSpacing(10)
self.gridLayout_2.setObjectName("gridLayout_2")
self.rot_tgt_btn = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
font = QtGui.QFont()
font.setPointSize(10)
self.rot_tgt_btn.setFont(font)
self.rot_tgt_btn.setObjectName("rot_tgt_btn")
self.gridLayout_2.addWidget(self.rot_tgt_btn, 0, 2, 1, 1)
self.scale_spinBox = QtWidgets.QSpinBox(self.scrollAreaWidgetContents)
self.scale_spinBox.setFont(font)
self.scale_spinBox.setObjectName("scale_spinBox")
self.scale_spinBox.setRange(10, 5000)
self.scale_spinBox.setValue(1000)
self.gridLayout_2.addWidget(self.scale_spinBox, 0, 5, 1, 1)
self.crop_btn = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
self.crop_btn.setFont(font)
self.crop_btn.setObjectName("crop_btn")
self.gridLayout_2.addWidget(self.crop_btn, 0, 3, 1, 1)
self.graphicsView = QtWidgets.QGraphicsView(self.scrollAreaWidgetContents)
self.graphicsView.setObjectName("graphicsView")
self.gridLayout_2.addWidget(self.graphicsView, 1, 0, 1, 6)
self.ror_lft_btn = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
self.ror_lft_btn.setFont(font)
self.ror_lft_btn.setObjectName("ror_lft_btn")
self.gridLayout_2.addWidget(self.ror_lft_btn, 0, 1, 1, 1)
self.scale_label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
font = QtGui.QFont()
font.setPointSize(10)
self.scale_label.setFont(font)
self.scale_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.scale_label.setObjectName("scale_label")
self.gridLayout_2.addWidget(self.scale_label, 0, 4, 1, 1)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.scene = QGraphicsScene()
self.pixmap = QPixmap("talia.png")
self.pixmap_scl = self.pixmap
self.scene.addPixmap(self.pixmap_scl)
self.graphicsView.setScene(self.scene)
self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(self.centralwidget)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
layout_window.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(layout_window)
self.menubar.setGeometry(QtCore.QRect(0, 0, 749, 23))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
self.menuImage = QtWidgets.QMenu(self.menubar)
self.menuImage.setObjectName("menuImage")
layout_window.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(layout_window)
self.statusbar.setObjectName("statusbar")
layout_window.setStatusBar(self.statusbar)
self.actionLoad = QtWidgets.QAction(layout_window)
self.actionLoad.setObjectName("actionLoad")
self.actionCrop = QtWidgets.QAction(layout_window)
self.actionCrop.setObjectName("actionCrop")
self.actionZoom = QtWidgets.QAction(layout_window)
self.actionZoom.setObjectName("actionZoom")
self.actionRotate = QtWidgets.QAction(layout_window)
self.actionRotate.setObjectName("actionRotate")
self.actionRotate_Right = QtWidgets.QAction(layout_window)
self.actionRotate_Right.setObjectName("actionRotate_Right")
self.actionRotate_Left = QtWidgets.QAction(layout_window)
self.actionRotate_Left.setObjectName("actionRotate_Left")
self.actionCrop_2 = QtWidgets.QAction(layout_window)
self.actionCrop_2.setObjectName("actionCrop_2")
self.menuFile.addAction(self.actionLoad)
self.menuFile.addAction(self.actionCrop)
self.menuFile.addAction(self.actionZoom)
self.menuFile.addAction(self.actionRotate)
self.menuImage.addAction(self.actionRotate_Right)
self.menuImage.addAction(self.actionRotate_Left)
self.menuImage.addAction(self.actionCrop_2)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuImage.menuAction())
self.statusbar.showMessage("text")
self.retranslateUi(layout_window)
self.buttonBox.accepted.connect(layout_window.close)
self.buttonBox.rejected.connect(layout_window.close)
self.scale_spinBox.editingFinished.connect(self.resizeimg)
QtCore.QMetaObject.connectSlotsByName(layout_window)
def retranslateUi(self, layout_window):
_translate = QtCore.QCoreApplication.translate
layout_window.setWindowTitle(_translate("layout_window", "MainWindow"))
self.rot_tgt_btn.setText(_translate("layout_window", "Rotate Right"))
self.crop_btn.setText(_translate("layout_window", "Crop"))
self.ror_lft_btn.setText(_translate("layout_window", "Rotate Left"))
self.scale_label.setText(_translate("layout_window", "Scale: "))
self.menuFile.setTitle(_translate("layout_window", "File"))
self.menuImage.setTitle(_translate("layout_window", "Image"))
self.actionLoad.setText(_translate("layout_window", "Load"))
self.actionCrop.setText(_translate("layout_window", "Crop"))
self.actionZoom.setText(_translate("layout_window", "Zoom"))
self.actionRotate.setText(_translate("layout_window", "Rotate"))
self.actionRotate_Right.setText(_translate("layout_window", "Rotate Right"))
self.actionRotate_Left.setText(_translate("layout_window", "Rotate Left"))
self.actionCrop_2.setText(_translate("layout_window", "Crop"))
def resizeimg(self):
zm_fct = self.scale_spinBox.value()
pixmap_scl = self.pixmap.scaled(zm_fct, zm_fct, QtCore.Qt.KeepAspectRatio)
print(zm_fct)
self.scene.clear()
self.scene.addPixmap(pixmap_scl)
self.graphicsView.setScene(self.scene)
def mousePressEvent(self, p):
x = p.x()
y = p.y()
print("On Hover", p.pos().x(), p.pos().y())
def mouseMoveEvent(self, e):
x = e.x()
y = e.y()
print("On Hover", e.pos().x(), e.pos().y())
text = "x: {0}, y: {1}".format(x, y)
self.statusbar.showMessage(text)
def mousePressEvent(self, event):
print(event)
def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape:
self.close()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
layout_window = QtWidgets.QMainWindow()
ui = Ui_layout_window()
ui.setupUi(layout_window)
layout_window.show()
sys.exit(app.exec_())
You are defining the function mousePressEvent() twice, and then you never call or bind it to anything.

how to set the display of the form by pressing the button from the toolbar in Pyqt5 or PyQt4

For example When I open the app to show me one form, when I click the button show second form that will contain the data entry fields
Home
Second form
There are several ways to achieve what you want. Easiest (not cleanest) is to group the widgets in your "forms" into containers (QFrame, QGroupbox, etc) and connect the triggered signal from your actions into suitable slots that hide/show these containers. Below you can see an example (PySide) of this, on which I'm using two QFrames in order to separate your "forms". The layout behaviour can be modified easily.
The form file (compiled from the designer's ui file):
# Form implementation generated from reading ui file 'example.ui'
#
# Created: Tue Apr 10 13:18:07 2018
# by: pyside-uic 0.2.15 running on PySide 1.2.4
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Example(object):
def setupUi(self, Example):
Example.setObjectName("Example")
Example.resize(800, 770)
self.centralwidget = QtGui.QWidget(Example)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.fr_one = QtGui.QFrame(self.centralwidget)
self.fr_one.setFrameShape(QtGui.QFrame.StyledPanel)
self.fr_one.setFrameShadow(QtGui.QFrame.Raised)
self.fr_one.setObjectName("fr_one")
self.verticalLayout_2 = QtGui.QVBoxLayout(self.fr_one)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.bt_quit = QtGui.QPushButton(self.fr_one)
self.bt_quit.setObjectName("bt_quit")
self.verticalLayout_2.addWidget(self.bt_quit)
self.cb_selection = QtGui.QComboBox(self.fr_one)
self.cb_selection.setObjectName("cb_selection")
self.verticalLayout_2.addWidget(self.cb_selection)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem)
self.gridLayout.addWidget(self.fr_one, 0, 0, 1, 1)
self.fr_two = QtGui.QFrame(self.centralwidget)
self.fr_two.setFrameShape(QtGui.QFrame.StyledPanel)
self.fr_two.setFrameShadow(QtGui.QFrame.Raised)
self.fr_two.setObjectName("fr_two")
self.verticalLayout_5 = QtGui.QVBoxLayout(self.fr_two)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtGui.QLabel(self.fr_two)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.le_fname = QtGui.QLineEdit(self.fr_two)
self.le_fname.setObjectName("le_fname")
self.verticalLayout.addWidget(self.le_fname)
self.verticalLayout_5.addLayout(self.verticalLayout)
self.verticalLayout_3 = QtGui.QVBoxLayout()
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.label_2 = QtGui.QLabel(self.fr_two)
self.label_2.setObjectName("label_2")
self.verticalLayout_3.addWidget(self.label_2)
self.le_sname = QtGui.QLineEdit(self.fr_two)
self.le_sname.setObjectName("le_sname")
self.verticalLayout_3.addWidget(self.le_sname)
self.verticalLayout_5.addLayout(self.verticalLayout_3)
self.verticalLayout_4 = QtGui.QVBoxLayout()
self.verticalLayout_4.setSpacing(0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.label_3 = QtGui.QLabel(self.fr_two)
self.label_3.setObjectName("label_3")
self.verticalLayout_4.addWidget(self.label_3)
self.le_address = QtGui.QLineEdit(self.fr_two)
self.le_address.setObjectName("le_address")
self.verticalLayout_4.addWidget(self.le_address)
self.verticalLayout_5.addLayout(self.verticalLayout_4)
spacerItem1 = QtGui.QSpacerItem(20, 267, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout_5.addItem(spacerItem1)
self.gridLayout.addWidget(self.fr_two, 0, 1, 1, 1)
Example.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(Example)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 47))
self.menubar.setObjectName("menubar")
Example.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(Example)
self.statusbar.setObjectName("statusbar")
Example.setStatusBar(self.statusbar)
self.toolBar = QtGui.QToolBar(Example)
self.toolBar.setObjectName("toolBar")
Example.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.actionAction1 = QtGui.QAction(Example)
self.actionAction1.setObjectName("actionAction1")
self.actionAction2 = QtGui.QAction(Example)
self.actionAction2.setObjectName("actionAction2")
self.toolBar.addAction(self.actionAction1)
self.toolBar.addAction(self.actionAction2)
self.retranslateUi(Example)
QtCore.QMetaObject.connectSlotsByName(Example)
def retranslateUi(self, Example):
Example.setWindowTitle(QtGui.QApplication.translate("Example", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.bt_quit.setText(QtGui.QApplication.translate("Example", "Quit", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Example", "First name", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Example", "Second name", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Example", "Address", None, QtGui.QApplication.UnicodeUTF8))
self.toolBar.setWindowTitle(QtGui.QApplication.translate("Example", "toolBar", None, QtGui.QApplication.UnicodeUTF8))
self.actionAction1.setText(QtGui.QApplication.translate("Example", "action1", None, QtGui.QApplication.UnicodeUTF8))
self.actionAction2.setText(QtGui.QApplication.translate("Example", "action2", None, QtGui.QApplication.UnicodeUTF8))
The main file:
from PySide import QtGui, QtCore
from _example import Ui_Example
class Example(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Example, self).__init__(parent)
self.ui = Ui_Example()
self.ui.setupUi(self)
self.ui.fr_two.setVisible(False)
self.ui.cb_selection.addItem("motif")
# here are the connections of the corresponding actions on the QToolBar
self.ui.actionAction1.triggered.connect(self._changeView1)
self.ui.actionAction2.triggered.connect(self._changeView2)
def _changeView1(self):
# fr_one is the first frame (the one that contains the 'quit' button and the QCombobox)
# fr_two is the second frame (the one that contains the QLineEdits)
self.ui.fr_one.setVisible(True)
self.ui.fr_two.setVisible(False)
def _changeView2(self):
self.ui.fr_one.setVisible(False)
self.ui.fr_two.setVisible(True)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()

How to combine columns in a layout (colspan feature)

I have this code:
#!/usr/bin/env python3
from PyQt5.QtWidgets import *
import sys
class Window(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QGridLayout()
self.setLayout(layout)
label_1 = QLabel("label 1")
layout.addWidget(label_1, 0, 0)
label_2 = QLabel("label 2")
layout.addWidget(label_2, 0, 1)
label_3 = QLabel("label 3")
layout.addWidget(label_3, 1, 0)
app = QApplication(sys.argv)
screen = Window()
screen.show()
sys.exit(app.exec_())
I have this result:
but I need this:
How can I do it?
The fourth and fifth arguments of addWidget allow you to specify how many rows and columns to span:
label_3 = QLabel("label 3")
layout.addWidget(label_3, 1, 0, 1, 2)
This is the example code for layout the QLabel. It is PyQt4, but you can try with PyQt5 with small changes.
import sys
from PyQt4 import QtGui
class Window (QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.verticalLayout = QtGui.QVBoxLayout (self)
self.verticalLayout.setObjectName ('verticalLayout')
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName ('gridLayout')
self.label_1 = QtGui.QLabel(self)
self.label_1.setObjectName('label_1')
self.label_1.setText ('Label_1')
self.label_1.setStyleSheet('background-color: rgb(182, 182, 182);')
self.label_2 = QtGui.QLabel(self)
self.label_2.setObjectName('label_2')
self.label_2.setText ('Label_2')
self.label_2.setStyleSheet('background-color: rgb(182, 182, 182);')
self.label_3 = QtGui.QLabel(self)
self.label_3.setObjectName('label_3')
self.label_3.setText ('Label_3')
self.label_3.setStyleSheet('background-color: rgb(182, 182, 182);')
self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1)
self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 2)
self.verticalLayout.addLayout(self.gridLayout)
self.resize(300, 100)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())

qprogressbar bar stops updating if new qprogressbar is opened in case of multithreading

I want to update the progress on progress-bar on some event. there are multiple events/threads and so the progress-bars associated with each of them. But when new thread is started previous thread stops updating the progress bar. This should not happen. Following could can be used:
import sys
from PyQt4 import QtGui, QtCore
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_dialog_progress(object):
def setupUi(self, dialog_progress):
dialog_progress.setObjectName("dialog_progress")
dialog_progress.resize(401, 165)
self.gridLayout = QtGui.QGridLayout(dialog_progress)
self.gridLayout.setObjectName("gridLayout")
self.lblFileName = QtGui.QLabel(dialog_progress)
self.lblFileName.setText("")
self.lblFileName.setObjectName("lblFileName")
self.gridLayout.addWidget(self.lblFileName, 0, 0, 1, 2)
self.pbarFileSize = QtGui.QProgressBar(dialog_progress)
self.pbarFileSize.setProperty("value", 0)
self.pbarFileSize.setObjectName("pbarFileSize")
self.gridLayout.addWidget(self.pbarFileSize, 1, 0, 1, 2)
self.label_2 = QtGui.QLabel(dialog_progress)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.pbarTotal = QtGui.QProgressBar(dialog_progress)
self.pbarTotal.setProperty("value", 0)
self.pbarTotal.setObjectName("pbarTotal")
self.gridLayout.addWidget(self.pbarTotal, 3, 0, 1, 2)
self.lblTotal = QtGui.QLabel(dialog_progress)
self.lblTotal.setText("")
self.lblTotal.setObjectName("lblTotal")
self.gridLayout.addWidget(self.lblTotal, 4, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(213, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 5, 1, 1, 1)
self.btnPbarCancel = QtGui.QPushButton(dialog_progress)
self.btnPbarCancel.setObjectName("btnPbarCancel")
self.gridLayout.addWidget(self.btnPbarCancel, 6, 1, 1, 1)
self.retranslateUi(dialog_progress)
QtCore.QMetaObject.connectSlotsByName(dialog_progress)
def retranslateUi(self, dialog_progress):
dialog_progress.setWindowTitle(QtGui.QApplication.translate("dialog_progress", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("dialog_progress", "Total:", None, QtGui.QApplication.UnicodeUTF8))
self.btnPbarCancel.setText(QtGui.QApplication.translate("dialog_progress", "Cancel", None, QtGui.QApplication.UnicodeUTF8))
class Ui_dialog_file(object):
def setupUi(self, dialog_file):
dialog_file.setObjectName(_fromUtf8("dialog_file"))
dialog_file.resize(101, 59)
self.btnCreate = QtGui.QPushButton(dialog_file)
self.btnCreate.setGeometry(QtCore.QRect(10, 20, 77, 25))
self.btnCreate.setObjectName(_fromUtf8("btnCreate"))
self.retranslateUi(dialog_file)
QtCore.QMetaObject.connectSlotsByName(dialog_file)
def retranslateUi(self, dialog_file):
dialog_file.setWindowTitle(QtGui.QApplication.translate("dialog_file", "file", None, QtGui.QApplication.UnicodeUTF8))
self.btnCreate.setText(QtGui.QApplication.translate("dialog_file", "Create", None, QtGui.QApplication.UnicodeUTF8))
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent = None)
self.ui = Ui_dialog_progress()
self.ui.setupUi(self)
# self.setWindowModality(QtCore.Qt.ApplicationModal)
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal()
updateFPD = QtCore.pyqtSignal()
updateTPD = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
self.pd = ProgressDialog()
signal = QtCore.SIGNAL("clicked()")
self.pd.ui.btnPbarCancel.connect(self.pd.ui.btnPbarCancel, signal, self.abort)
self.aborted= False
def run(self):
self.trigger.emit()
def abort(self):
self.aborted = True
print "aborted"
self.pd.close()
def setup(self, no):
self.threadNo = no
self.name = "Thread %d"%self.threadNo
class Main(QtGui.QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.ui = Ui_dialog_file()
self.ui.setupUi(self)
self.ui.btnCreate.clicked.connect(self.start_threads)
self.count = 0
self.threadPool = []
def start_threads(self):
self.mythread = MyThread(self)
self.mythread.setup(self.count)
self.count += 1
self.mythread.trigger.connect(self.pdialog)
self.mythread.start()
self.threadPool.append(self.count)
def abort(self):
self.mythread.stop()
def pdialog(self):
self.mythread.pd.show()
i = 1
self.mythread.pd.ui.pbarTotal.setValue(0)
self.mythread.pd.ui.pbarFileSize.setValue(0)
self.mythread.pd.setWindowTitle(self.mythread.name)
j = 1
while i < 100:
while j <= 100:
self.mythread.pd.ui.lblFileName.setText(self.mythread.name)
self.mythread.pd.ui.pbarFileSize.setValue(j)
print "name: %s, fileprogress: %d"%(self.mythread.name,j)
QtGui.qApp.processEvents()
j += 1
i += 1
j = 1
self.mythread.pd.ui.pbarTotal.setValue(i)
print "name: %s, total progress %d"%(self.mythread.name, i)
QtGui.qApp.processEvents()
if self.mythread.aborted:
return
self.mythread.pd.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())
please find my new code:
import sys
from PyQt4 import QtGui, QtCore
import time
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_dialog_progress(object):
def setupUi(self, dialog_progress):
dialog_progress.setObjectName("dialog_progress")
dialog_progress.resize(401, 165)
self.gridLayout = QtGui.QGridLayout(dialog_progress)
self.gridLayout.setObjectName("gridLayout")
self.lblFileName = QtGui.QLabel(dialog_progress)
self.lblFileName.setText("")
self.lblFileName.setObjectName("lblFileName")
self.gridLayout.addWidget(self.lblFileName, 0, 0, 1, 2)
self.pbarFileSize = QtGui.QProgressBar(dialog_progress)
self.pbarFileSize.setProperty("value", 0)
self.pbarFileSize.setObjectName("pbarFileSize")
self.gridLayout.addWidget(self.pbarFileSize, 1, 0, 1, 2)
self.label_2 = QtGui.QLabel(dialog_progress)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.pbarTotal = QtGui.QProgressBar(dialog_progress)
self.pbarTotal.setProperty("value", 0)
self.pbarTotal.setObjectName("pbarTotal")
self.gridLayout.addWidget(self.pbarTotal, 3, 0, 1, 2)
self.lblTotal = QtGui.QLabel(dialog_progress)
self.lblTotal.setText("")
self.lblTotal.setObjectName("lblTotal")
self.gridLayout.addWidget(self.lblTotal, 4, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(213, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 5, 1, 1, 1)
self.btnPbarCancel = QtGui.QPushButton(dialog_progress)
self.btnPbarCancel.setObjectName("btnPbarCancel")
self.gridLayout.addWidget(self.btnPbarCancel, 6, 1, 1, 1)
self.retranslateUi(dialog_progress)
QtCore.QMetaObject.connectSlotsByName(dialog_progress)
def retranslateUi(self, dialog_progress):
dialog_progress.setWindowTitle(QtGui.QApplication.translate("dialog_progress", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("dialog_progress", "Total:", None, QtGui.QApplication.UnicodeUTF8))
self.btnPbarCancel.setText(QtGui.QApplication.translate("dialog_progress", "Cancel", None, QtGui.QApplication.UnicodeUTF8))
class Ui_dialog_file(object):
def setupUi(self, dialog_file):
dialog_file.setObjectName(_fromUtf8("dialog_file"))
dialog_file.resize(101, 59)
self.btnCreate = QtGui.QPushButton(dialog_file)
self.btnCreate.setGeometry(QtCore.QRect(10, 20, 77, 25))
self.btnCreate.setObjectName(_fromUtf8("btnCreate"))
self.retranslateUi(dialog_file)
QtCore.QMetaObject.connectSlotsByName(dialog_file)
def retranslateUi(self, dialog_file):
dialog_file.setWindowTitle(QtGui.QApplication.translate("dialog_file", "file", None, QtGui.QApplication.UnicodeUTF8))
self.btnCreate.setText(QtGui.QApplication.translate("dialog_file", "Create", None, QtGui.QApplication.UnicodeUTF8))
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent=None)
self.ui = Ui_dialog_progress()
self.ui.setupUi(self)
# self.setWindowModality(QtCore.Qt.ApplicationModal)
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal()
updateFPD = QtCore.pyqtSignal(int, QtCore.QString)
updateTPD = QtCore.pyqtSignal(int, QtCore.QString)
showpdSignal = QtCore.pyqtSignal(bool)
def __init__(self, parent=None, no=0):
super(MyThread, self).__init__(parent)
self.aborted = False
self.threadNo = no
# self.name = "Thread %d"%self.threadNo
def run(self):
self.trigger.emit()
def emitSignals(self, iprogress=-99, tprogress=-99, \
updateFPDSignal=True, updateTPDSignal=None, \
showpdSignal=False, peSignal=None, msg=None
):
if updateFPDSignal:
self.updateFPD.emit(iprogress, msg)
if updateTPDSignal:
self.updateTPD.emit(tprogress, msg)
if showpdSignal:
self.showpdSignal.emit(True)
else:
self.showpdSignal.emit(False)
if peSignal:
QtGui.QApplication.processEvents()
def abort(self):
self.aborted = True
print "aborted"
def stop(self):
self.terminate()
class Main(QtGui.QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.ui = Ui_dialog_file()
self.ui.setupUi(self)
self.ui.btnCreate.clicked.connect(self.start_threads)
self.count = 0
self.threadPool = []
def start_threads(self):
self.mythread = MyThread()
self.pd = ProgressDialog()
self.pd.ui.btnPbarCancel.clicked.connect(self.abort)
self.mythread.trigger.connect(self.pdialog)
self.mythread.updateFPD.connect(self.updateFileProgress)
self.mythread.updateTPD.connect(self.updateTotalProgress)
self.mythread.start()
self.threadPool.append(self.mythread)
def abort(self):
self.pd.close()
self.mythread.aborted = True
def updateFileProgress(self, j, name):
self.pd.ui.lblFileName.setText(name)
self.pd.ui.pbarFileSize.setValue(j)
# print "name: %s, fileprogress: %d" % (name, j)
def updateTotalProgress(self, i, name):
self.pd.ui.pbarTotal.setValue(i)
# print "name: %s, total progress %d" % (name, i)
def showProgressDialog(self, show):
if show:
self.pd.show()
else:
self.pd.close()
def pdialog(self):
self.pd.show()
i = 1
self.threadPool[len(self.threadPool) - 1].emitSignals(iprogress=0 , tprogress=0, updateFPDSignal=True,
updateTPDSignal=True, showpdSignal=True, msg="")
j = 1
while i < 100:
while j <= 100:
self.threadPool[len(self.threadPool) - 1].emitSignals(iprogress=j, updateFPDSignal=True, \
peSignal=True, msg="")
j += 1
i += 1
j = 1
self.threadPool[len(self.threadPool) - 1].emitSignals(tprogress=i, updateTPDSignal=True, \
peSignal=True, msg="")
if self.threadPool[len(self.threadPool) - 1].aborted:
return
self.threadPool[len(self.threadPool) - 1].sleep(2)
self.pd.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())
Widgets should only be controlled by the main ui thread(i.e the thread that is in control of the main event-loop). If a widget exists outside the main thread then it will most likely not receive any updates, nor will it post any events such as it being clicked. Don't have your threads owning and/or manipulating ui widgets. In this particular case you don't need MyThread at all.
Let me use an example.
import time
import sys
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
progress_changed = QtCore.pyqtSignal(object)
def run(self):
for x in range(101):
#we do not interect with the progress bar directly
self.progress_changed.emit(x)
time.sleep(0.1)
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.progress_thread1 = MyThread()
self.progress_thread2 = MyThread()
self.progress_bar1 = QtGui.QProgressBar()
self.progress_bar1.setMinimum(0)
self.progress_bar1.setMaximum(100)
self.progress_bar2 = QtGui.QProgressBar()
self.progress_bar2.setMinimum(0)
self.progress_bar2.setMaximum(100)
"""
the progress is emmited through the thread's progress_changed signal
we connect that signal to our updateProgress method which will
be used to set the progress_bar's value
you can also just connect it directly to the progress bar's setValue method
self.progress_thread.progress_changed.connect(self.progress_bar.setValue)
"""
self.progress_thread1.progress_changed.connect(self.updateProgress1)
self.progress_thread2.progress_changed.connect(self.updateProgress2)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.progress_bar1)
mainLayout.addWidget(self.progress_bar2)
self.setLayout(mainLayout)
self.progress_thread1.start()
self.progress_thread2.start()
def updateProgress1(self, progress):
self.progress_bar1.setValue(progress)
def updateProgress2(self, progress):
self.progress_bar2.setValue(progress)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
widget = MyWidget()
widget.show()
r = app.exec_()
sys.exit(r)
Copy this to an empty python script and run it.

Categories