How to combine columns in a layout (colspan feature) - python

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

Related

QWidgetAction not triggering

Can someone explain to me why the 'triggered' event is not firing when i click my custom Action?
import os, sys
from PySide2 import QtGui, QtWidgets, QtCore
class ActionButton(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ActionButton, self).__init__(parent)
# controls
self.icon = QtWidgets.QToolButton()
self.icon.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay))
self.icon.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
self.label = QtWidgets.QLabel('Sample long name')
self.label.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
# layout
self.buttonLayout = QtWidgets.QGridLayout()
self.buttonLayout.setContentsMargins(4, 4, 4, 4)
self.buttonLayout.setSpacing(2)
self.buttonLayout.addWidget(self.icon, 0, 0, QtCore.Qt.AlignCenter)
self.buttonLayout.addWidget(self.label, 1, 0, QtCore.Qt.AlignCenter)
self.mainLayout = QtWidgets.QGridLayout()
self.mainLayout.setContentsMargins(0, 0, 0, 0)
self.mainLayout.addLayout(self.buttonLayout, 0, 0, QtCore.Qt.AlignCenter)
self.setLayout(self.mainLayout)
# method
def setText(self, value):
self.label.setText(value)
def setIcon(self, value):
self.icon.setIcon(value)
class Example(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
# controls
self.toolBar = QtWidgets.QToolBar()
# layout
self.mainLayout = QtWidgets.QHBoxLayout()
self.mainLayout.addWidget(self.toolBar)
self.setLayout(self.mainLayout)
# custom
wPreset = ActionButton(self)
wAct = QtWidgets.QWidgetAction(self)
wAct.setDefaultWidget(wPreset)
wAct.triggered.connect(self.testThis)
self.toolBar.addAction(wAct)
def testThis(self):
print('here')
def test():
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
pass
test()

pyqt: How to let the QLabel occupy the whole window

I put three label in a window, however, the three labels only occupy small part of the window. Here is my code:
from PyQt5.QtWidgets import *
import sys
class ThreeDMPRWindow(QMainWindow):
def __init__(self, image=None):
super(ThreeDMPRWindow, self).__init__()
self.resize(800, 600)
widget = QWidget()
self.setCentralWidget(widget)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
widget.setLayout(layout)
allLayout = QHBoxLayout()
layout1 = QVBoxLayout()
label1 = QLabel('label 1')
label1.setStyleSheet("background: rgb(255,0,0)")
layout1.addWidget(label1)
layout2 = QVBoxLayout()
label2 = QLabel('label 2')
label2.setStyleSheet("background: rgb(255,0,0)")
layout2.addWidget(label2)
layout3 = QVBoxLayout()
label3 = QLabel('label 3')
label3.setStyleSheet("background: rgb(255,0,0)")
layout3.addWidget(label3)
qlayout = QGridLayout()
qlayout.addLayout(layout1, 0, 0, 2, 1)
qlayout.addLayout(layout2, 0, 1, 1, 1)
qlayout.addLayout(layout3, 1, 1, 1, 1)
allLayout.addLayout(qlayout)
allLayout.addLayout(QVBoxLayout())
layout.addLayout(allLayout)
app = QApplication(sys.argv)
window = ThreeDMPRWindow()
window.show()
app.exec_()
If we annotate the code: allLayout.addLayout(QVBoxLayout()), the three labels would occupy the whole window. I don't know why this code makes such difference. But I can't remove the code allLayout.addLayout(QVBoxLayout()), because I need the new layout for some other widgets.
If you want to have a space where you can add other widgets then you must use QWidget instead of QVBoxLayout, and in that QWidget add the QVBoxLayout:
# ...
allLayout.addLayout(qlayout)
empty_widget = QWidget()
empty_widget.setContentsMargins(0, 0, 0, 0)
lay = QVBoxLayout(empty_widget)
allLayout.addWidget(empty_widget)
layout.addLayout(allLayout)
# ...
Output:

Add multiple columns inside a tableview cell

I'm trying to create a table that have a column inside a cell. Is there an easy way to implement this design to the table view I'm working with?
This is my code right now:
class ColumnsLayout(QWidget):
def __init__(self, parent=None):
super(ColumnsLayout, self).__init__(parent)
table_row = QTableWidget()
table_row.setColumnCount(3)
table_row.horizontalHeader().setVisible(False)
for x in range(0, 3):
table_row.horizontalHeader().setSectionResizeMode(x, QHeaderView.Stretch)
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
layout.addWidget(table_row)
self.setLayout(layout)
self.ui.fields_tableWidget.setCellWidget(self.current_default_total_row, 2, ColumnsLayout())
You can use setSpan() to join cells
from PySide2 import QtWidgets
class ColumnsLayout(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ColumnsLayout, self).__init__(parent)
table_row = QtWidgets.QTableWidget(4, 3)
table_row.horizontalHeader().hide()
table_row.setSpan(0, 0, 1, 3)
for x in range(0, 3):
table_row.horizontalHeader().setSectionResizeMode(x, QtWidgets.QHeaderView.Stretch)
layout = QtWidgets.QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
layout.addWidget(table_row)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = ColumnsLayout()
w.show()
sys.exit(app.exec_())

Add a QMenuBar to a QWidget

I'm trying to integrate a QMenubar in a QWidget in Pyside2 in Python3. It seems to be easier to integrate a QMenubar to a QMainWindow but I started the project with a QWidget and not a QMainWindow and this is why I would like to have a solution for a QWidget.
When I run the code, there is no error message but the menubar doesn't appear when I run the app. I checked that stackoveflow page but it didn't help me or I wasn't able to implement it.
Code
from PySide2.QtWidgets import (QWidget, QApplication, QGraphicsView,
QGridLayout)
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtOpenGL import *
from PySide2.QtCore import *
from PySide2.QtGui import *
image_path_str='image.jpg'
class View(QGraphicsView):
photo_clicked = QtCore.Signal(QtCore.QPoint)
def __init__(self, parent):
super(View, self).__init__()
self.scene = QtWidgets.QGraphicsScene(self)
self.photo = QtWidgets.QGraphicsPixmapItem()
self.scene.addItem(self.photo)
self.pixmap = QtGui.QPixmap(image_path_str)
self.photo.setPixmap(self.pixmap)
self.setScene(self.scene)
self.setDragMode(QGraphicsView.ScrollHandDrag)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.view = View(self)
self.layout_contain_P1_P2 = QtWidgets.QGridLayout()
self.checkbox_P1= QtWidgets.QCheckBox("P1",self)
self.line_edit_P1_x = QtWidgets.QLineEdit(self)
self.line_edit_P1_x.setReadOnly(True)
self.line_edit_P1_y = QtWidgets.QLineEdit(self)
self.line_edit_P1_y.setReadOnly(True)
self.menubar = QtWidgets.QMenuBar()
self.archive = self.menubar.addMenu("archive")
self.menubar.setObjectName("menubar")
self.layout_contain_P1_P2.addWidget(self.checkbox_P1, 0, 0, Qt.AlignLeft)
self.grid_layout_P1_x_y = QtWidgets.QGridLayout()
self.grid_layout_P1_x_y.addWidget(self.line_edit_P1_x, 1, 0, Qt.AlignLeft)
self.grid_layout_P1_x_y.addWidget(self.line_edit_P1_y, 2, 0, Qt.AlignLeft)
self.layout_contain_P1_P2.addLayout(self.grid_layout_P1_x_y, 0, 1, 1, 1)
self.checkbox_P2 = QtWidgets.QCheckBox("P2",self)
self.line_edit_P2_x = QtWidgets.QLineEdit(self)
self.line_edit_P2_x.setReadOnly(True)
self.line_edit_P2_y = QtWidgets.QLineEdit(self)
self.line_edit_P2_y.setReadOnly(True)
self.layout_contain_P1_P2.addWidget(self.checkbox_P2, 1, 0, Qt.AlignLeft)
self.grid_layout_P2_x_y = QtWidgets.QGridLayout()
self.grid_layout_P2_x_y.addWidget(self.line_edit_P2_x, 0, 0, Qt.AlignLeft)
self.grid_layout_P2_x_y.addWidget(self.line_edit_P2_y, 1, 0, Qt.AlignLeft)
self.layout_contain_P1_P2.addLayout(self.grid_layout_P2_x_y, 1, 1, Qt.AlignLeft)
self.combo_box1 = QtWidgets.QComboBox(self)
self.combo_box1.addItem("measurements set 1")
self.combo_box1.addItem("measurements set 1")
self.combo_box2 = QtWidgets.QComboBox(self)
self.combo_box2.addItem("P1-P2")
self.combo_box2.addItem("P3-P4")
self.vertical1= QtWidgets.QVBoxLayout()
self.vertical1.addWidget(self.menubar)
self.vertical1.addWidget(self.combo_box1)
self.vertical1.addWidget(self.combo_box2)
self.vertical1.addLayout(self.layout_contain_P1_P2)
self.vertical2= QtWidgets.QVBoxLayout()
self.vertical2.addWidget(self.view)
self.horizontal= QtWidgets.QHBoxLayout()
self.horizontal.addLayout(self.vertical1)
self.horizontal.addLayout(self.vertical2)
self.setLayout(self.horizontal)
self.setWindowTitle("Image viewer")
self.setGeometry(200, 200, 1000, 800)
app = QApplication.instance()
if app is None:
app = QApplication([])
w = Window()
w.show()
w.raise_()
QApplication.setOverrideCursor(QCursor(Qt.CrossCursor))
app.exec_()
Here is screenshot of what I get:
Edit : not optimal workaround: add a QMainWindow class
Here is not optimal workaround. I had to add an extra class QMainWindow and call the Widget from within the QMainWindow
from PySide2.QtWidgets import (QWidget, QApplication, QGraphicsView,
QGridLayout, QMainWindow, QAction, QMenu)
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtOpenGL import *
from PySide2.QtCore import *
from PySide2.QtGui import *
image_path_str='image.jpg'
class View(QGraphicsView):
photo_clicked = QtCore.Signal(QtCore.QPoint)
def __init__(self, parent):
super(View, self).__init__()
self.scene = QtWidgets.QGraphicsScene(self)
self.photo = QtWidgets.QGraphicsPixmapItem()
self.scene.addItem(self.photo)
self.pixmap = QtGui.QPixmap(image_path_str)
self.photo.setPixmap(self.pixmap)
self.setScene(self.scene)
self.setDragMode(QGraphicsView.ScrollHandDrag)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.view = View(self)
self.layout_contain_P1_P2 = QtWidgets.QGridLayout()
self.checkbox_P1= QtWidgets.QCheckBox("P1",self)
self.line_edit_P1_x = QtWidgets.QLineEdit(self)
self.line_edit_P1_x.setReadOnly(True)
self.line_edit_P1_y = QtWidgets.QLineEdit(self)
self.line_edit_P1_y.setReadOnly(True)
self.layout_contain_P1_P2.addWidget(self.checkbox_P1, 0, 0, Qt.AlignLeft)
self.grid_layout_P1_x_y = QtWidgets.QGridLayout()
self.grid_layout_P1_x_y.addWidget(self.line_edit_P1_x, 1, 0, Qt.AlignLeft)
self.grid_layout_P1_x_y.addWidget(self.line_edit_P1_y, 2, 0, Qt.AlignLeft)
self.layout_contain_P1_P2.addLayout(self.grid_layout_P1_x_y, 0, 1, 1, 1)
self.checkbox_P2 = QtWidgets.QCheckBox("P2",self)
self.line_edit_P2_x = QtWidgets.QLineEdit(self)
self.line_edit_P2_x.setReadOnly(True)
self.line_edit_P2_y = QtWidgets.QLineEdit(self)
self.line_edit_P2_y.setReadOnly(True)
self.layout_contain_P1_P2.addWidget(self.checkbox_P2, 1, 0, Qt.AlignLeft)
self.grid_layout_P2_x_y = QtWidgets.QGridLayout()
self.grid_layout_P2_x_y.addWidget(self.line_edit_P2_x, 0, 0, Qt.AlignLeft)
self.grid_layout_P2_x_y.addWidget(self.line_edit_P2_y, 1, 0, Qt.AlignLeft)
self.layout_contain_P1_P2.addLayout(self.grid_layout_P2_x_y, 1, 1, Qt.AlignLeft)
self.combo_box1 = QtWidgets.QComboBox(self)
self.combo_box1.addItem("measurements set 1")
self.combo_box1.addItem("measurements set 1")
self.combo_box2 = QtWidgets.QComboBox(self)
self.combo_box2.addItem("P1-P2")
self.combo_box2.addItem("P3-P4")
self.vertical1= QtWidgets.QVBoxLayout()
# self.vertical1.addWidget(self.menubar)
self.vertical1.addWidget(self.combo_box1)
self.vertical1.addWidget(self.combo_box2)
self.vertical1.addLayout(self.layout_contain_P1_P2)
self.vertical2= QtWidgets.QVBoxLayout()
self.vertical2.addWidget(self.view)
self.horizontal= QtWidgets.QHBoxLayout()
self.horizontal.addLayout(self.vertical1)
self.horizontal.addLayout(self.vertical2)
self.setLayout(self.horizontal)
self.setWindowTitle("Image viewer")
self.setGeometry(200, 200, 1000, 800)
class Main_window(QMainWindow):
def __init__(self, parent=None):
super(Main_window, self).__init__(parent)
self.window = Window()
self.setCentralWidget(self.window)
self.initUI()
def initUI(self):
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
impMenu = QMenu('Import', self)
impAct = QAction('Import mail', self)
impMenu.addAction(impAct)
newAct = QAction('New', self)
fileMenu.addAction(newAct)
fileMenu.addMenu(impMenu)
app = QApplication.instance()
if app is None:
app = QApplication([])
mw = Main_window()
mw.show()
mw.raise_()
QApplication.setOverrideCursor(QCursor(Qt.CrossCursor))
app.exec_()

PyQt: Put scrollbars in this

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

Categories