How to control QAction buttons spacing in QToolBar? - python

With four QAction buttons added to QToolBar what widgets properties need to be set and to what value to make no spacing between the buttons. So each button is placed side by side?
As it can be seen from the example posted below I've tried to achieve zero spacing with:
toolbar.setContentsMargins(0, 0, 0, 0)
toolbar.layout().setSpacing(0)
toolbar.layout().setContentsMargins(0, 0, 0, 0)
but it makes no difference and the buttons are still spaced from each other....
import sys
from PyQt4.QtGui import *
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.initUI()
def initUI(self):
textEdit = QTextEdit()
self.setCentralWidget(textEdit)
btn1 = QAction(QIcon('icons/btn1.png'), 'Button 01', self)
btn2 = QAction(QIcon('icons/btn2.png'), 'Button 02', self)
btn3 = QAction(QIcon('icons/btn3.png'), 'Button 03', self)
btn3.setEnabled(False)
btn1.setShortcut('Ctrl+Q')
btn1.triggered.connect(self.close)
toolbar = self.addToolBar('Exit')
toolbar.addAction(btn1)
toolbar.addAction(btn2)
toolbar.addAction(btn3)
toolbar.addSeparator()
toolbar.setContentsMargins(0, 0, 0, 0)
toolbar.layout().setSpacing(0)
toolbar.layout().setContentsMargins(0, 0, 0, 0)
self.setGeometry(300, 300, 350, 250)
self.setWindowTitle('Main window')
self.show()
def main():
app = QApplication(sys.argv)
ex = Window()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

From the stylesheet examples for QToolBar:
spacing: 3px; /* spacing between items in the tool bar */
So this should do the trick:
toolbar.setStyleSheet("QToolBar{spacing:0px;}");

Related

How to create checkable ability to Qpushbuttons like QRadioButtons in pyqt5

How to add checkable ability to buttons when clicking on one of them had the checked mode and the other buttons are unchecked.
That is, one button can be checked at a time.
from PyQt5.QtWidgets import *
import sys
class Window(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QGridLayout()
self.setLayout(layout)
btn1 = QPushButton()
btn1.setChecked(True)
btn1.setStyleSheet("background-color: rgba(255, 0, 0, 0.61);")
layout.addWidget(btn1, 0, 0)
btn2 = QPushButton()
btn2.setStyleSheet("background-color: rgb(0, 255, 34);")
layout.addWidget(btn2, 0, 1)
btn3 = QPushButton()
btn3.setStyleSheet("background-color: rgb(49, 49, 49);")
layout.addWidget(btn3, 0, 2)
app = QApplication(sys.argv)
screen = Window()
screen.show()
sys.exit(app.exec_())

PyQt5 - The "setContentsMargins" method doesn't work properly in a Tab widget (there is a default 9px margin)

I'm writing a GUI with PyQt5 and I realized that the setContentsMargins method doesn't work properly in a Tab widget. Inside of it there is always a 9px margin for each side (see the attached screenshot):
Here is an example (inside the Tab1 I put a TreeView widget with a using the QVBoxLayout):
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QTabWidget, QVBoxLayout, QTreeView
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 tabs'
self.left = 0
self.top = 0
self.width = 300
self.height = 200
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.table_widget = MyTableWidget(self)
self.setCentralWidget(self.table_widget)
self.show()
class MyTableWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tabs.resize(300,200)
self.tabs.addTab(self.tab1,"Tab 1")
self.tabs.addTab(self.tab2,"Tab 2")
self.tab1.layout = QVBoxLayout(self)
self.TreeView=QTreeView()
self.tab1.layout.addWidget(self.TreeView)
self.tab1.setLayout(self.tab1.layout)
self.tab1.setStyleSheet("background-color: red")
self.tab1.setContentsMargins(-4, -4, -4, -4) # this instruction doesn't work! there is always a default margin (9px for each side)!
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
As you can see, if I use the instruction self.tab1.setContentsMargins(10, 10, 10, 10) all the margins, will be 19px (9+10), but what about if a want 5px? The instruction self.tab1.setContentsMargins(-4, -4, -4, -4) doesn't work.
The additional margin is from the widget's layout. Set it to zero or any other value:
self.tab1.layout.setContentsMargins(0, 0, 0, 0)

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:

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

Why does one of my QtWidgets not appear?

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:

Categories