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_())
Related
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()
I want to make GUI like below with PyQt5, but I can't find an example to help me.
I searched for "change layout on qwidget" and "tab pane with no title bar" and "card layout" without luck. How can I make this with PyQt5?
You have to use a QStackedLayout (or a QStackedWidget) that changes pages when the buttons are pressed. And the first page should have the buttons. I have also implemented the back() method that returns to the initial page, that slot must be invoked when the Change button is pressed:
from functools import partial
from PyQt5 import QtCore, QtWidgets
class CardWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(CardWidget, self).__init__(parent)
self._layout = QtWidgets.QStackedLayout(self)
button_widget = QtWidgets.QWidget()
self.btn_lay = QtWidgets.QFormLayout(button_widget)
self._layout.addWidget(button_widget)
def add_widget(self, text, widget):
self._layout.addWidget(widget)
btn = QtWidgets.QPushButton(text)
self.btn_lay.addRow(btn)
btn.clicked.connect(partial(self._layout.setCurrentWidget, widget))
#QtCore.pyqtSlot()
def back(self):
self._layout.setCurrentIndex(0)
class Widget(QtWidgets.QWidget):
backSignal = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.le1 = QtWidgets.QLineEdit()
self.le2 = QtWidgets.QLineEdit()
button = QtWidgets.QPushButton("Change")
button.clicked.connect(self.backSignal)
flay = QtWidgets.QFormLayout()
flay.addRow("Value 1:", self.le1)
flay.addRow("Value 2:", self.le2)
lay = QtWidgets.QVBoxLayout(self)
lay.addLayout(flay)
lay.addWidget(button)
def create_label():
label = QtWidgets.QLabel(
"Some Other Components",
alignment=QtCore.Qt.AlignCenter
)
label.setStyleSheet("background-color:blue;")
return label
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
c = CardWidget()
for i in range(3):
w = Widget()
w.backSignal.connect(c.back)
c.add_widget("Want to Change value {}".format(i+1), w)
p = QtWidgets.QWidget()
lay = QtWidgets.QGridLayout(p)
lay.addWidget(create_label(), 0, 0, 1, 2)
lay.addWidget(c, 1, 0)
lay.addWidget(create_label(), 1, 1)
lay.setColumnStretch(0, 1)
lay.setColumnStretch(1, 1)
lay.setRowStretch(0, 1)
lay.setRowStretch(1, 1)
p.resize(640, 480)
p.show()
sys.exit(app.exec_())
I've coded a little Snake example.
I've created a QMainWindow with a centralWidget that has a gridlayout.
I can't seem to get the spacing right. I thought I can do it with setContentMargins(), so I placed it everywhere I can but the space still remains. I'm probably overseeing something. I think it has to do with my grid. But I don't see the problem. Thoughts?
Here is a picture:
https://imgur.com/tHbf6tV
Here's my code:
import sys
from PyQt5 import QtWidgets as qw
from PyQt5 import QtGui as qg
from PyQt5 import QtCore as qc
class Snake(qw.QMainWindow):
def __init__(self, parent=None):
super(Snake, self).__init__(parent)
self.setContentsMargins(0,0,0,0)
self.test()
self.show()
def test(self):
self.centralwidget = qw.QWidget()
self.setCentralWidget(self.centralwidget)
self.centralwidget.setStyleSheet("background-color: green")
self.gridLayout = qw.QGridLayout()
self.gridLayout.setSpacing(0)
# self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.vLayout = qw.QVBoxLayout(self.centralwidget)
self.hLayout = qw.QHBoxLayout()
self.hLayout.setContentsMargins(0, 0, 0, 0)
self.vLayout.setContentsMargins(0, 0, 0, 0)
# center the grid with stretch on both sides
self.hLayout.addLayout(self.gridLayout)
self.hLayout.addStretch(0)
self.vLayout.addLayout(self.hLayout)
# push grid to the top of the window
self.vLayout.addStretch(0)
self.buttons = []
for i in range(24):
l = []
for j in range(24):
b = qw.QPushButton()
b.setFixedSize(20, 20)
b.setStyleSheet("background-color: black")
l.append(b)
self.gridLayout.addWidget(b, i, j)
self.gridLayout.setColumnMinimumWidth(j, 20)
self.buttons.append(l)
self.gridLayout.setRowMinimumHeight(i, 16)
self.buttons[5][5].setStyleSheet("background-color: green")
self.buttons[4][5].setStyleSheet("background-color: green")
self.buttons[3][5].setStyleSheet("background-color: green")
if __name__ == '__main__':
app = qw.QApplication(sys.argv)
Menu = Snake()
sys.exit(app.exec_())
i think i've solved it.The clue was to recreate my grid without QHBoxLayout and QVBoxLayout.
Here's my code:
import sys
from PyQt5 import QtWidgets as qw
from PyQt5 import QtGui as qg
from PyQt5 import QtCore as qc
class Snake(qw.QMainWindow):
def __init__(self, parent=None):
super(Snake, self).__init__(parent)
self.setContentsMargins(0, 0, 0, 0)
self.setFixedSize(20*24,20*24)
self.test()
self.show()
def test(self):
self.centralwidget = qw.QWidget()
self.setCentralWidget(self.centralwidget)
self.centralwidget.setStyleSheet("background-color: green")
self.centralwidget.setContentsMargins(0, 0, 0, 0)
self.gridLayout = qw.QGridLayout()
self.gridLayout.setSpacing(0)
self.gridLayout.setContentsMargins(0,0,0,0)
self.buttons = []
for i in range(24):
for j in range(24):
b = qw.QLabel("Knopf" + str(i) + "/" + str(j))
b.setFixedSize(20, 20)
b.setStyleSheet("background-color: black")
self.gridLayout.addWidget(b, i, j)
self.gridLayout.setColumnMinimumWidth(j, 20)
self.gridLayout.setRowMinimumHeight(i, 16)
self.centralwidget.setLayout(self.gridLayout)
if __name__ == '__main__':
app = qw.QApplication(sys.argv)
Menu = Snake()
sys.exit(app.exec_())
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_())
My GLWidget (inherited from QtOpenGL.QGLWidget) does not appear on screen, while it should be visible at the right of the other widgets. However, when I switch from an horizontal layout:
layout_final = Qtgui.QHBoxLayout()
to a vertical one:
layout_final = Qtgui.QVBoxLayout()
my GL widget does appear under the other widgets, but I want it to be on the right of the other widgets.
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
# create layout
layout_before_final = QtGui.QVBoxLayout()
layout_final = QtGui.QHBoxLayout()
layout = QtGui.QGridLayout()
layout1 = QtGui.QGridLayout()
self.groupBox = QtGui.QGroupBox('Set HDF5 file')
self.groupBox1 = QtGui.QGroupBox('Current HDF5 file')
# instance widgets
# first box
self.setH5Button = QtGui.QPushButton('set H5')
self.currentH5LineEdit = QtGui.QLineEdit('')
layout.addWidget(self.setH5Button, 0,0)
layout.addWidget(self.currentH5LineEdit, 0, 1)
self.groupBox.setLayout(layout)
# second box
self.channelsLabel = QtGui.QLabel('Channel')
self.channelsComboBox = QtGui.QComboBox()
self.levelsLabel = QtGui.QLabel('Level')
self.levelsComboBox = QtGui.QComboBox()
layout1.addWidget(self.channelsLabel, 0, 0, 1, 1)
layout1.addWidget(self.channelsComboBox, 0, 1, 1, 1)
layout1.addWidget(self.levelsLabel, 1, 0, 1, 1)
layout1.addWidget(self.levelsComboBox, 1, 1, 1, 1)
self.groupBox1.setLayout(layout1)
# create QWidget to gather the two previous boxes
self.widget = QtGui.QWidget()
layout_before_final.addWidget(self.groupBox)
layout_before_final.addWidget(self.groupBox1)
self.widget.setLayout(layout_before_final)
# GL widget
self.widgetGL = MyWidget()
# create a final widget to add the GL widget
self.finalWidget = QtGui.QWidget()
layout_final.addWidget(self.widgetGL)
layout_final.addWidget(self.widget)
self.finalWidget.setLayout(layout_final)
self.setCentralWidget(self.finalWidget)
self.setWindowTitle('PyPractis')
self.resize(640, 480)
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I'm not sure why it's happening, but it appears to be caused by the GL widget preferentially collapsing horizontally (giving up it's space to the other elements). You can easily override this behaviour however, by specifying the stretch priority when adding the element:
layout_final.addWidget(self.widgetGL, stretch=1)
This results in the following layout: