I'm having trouble with spacing widgets in a QVboxlayout. I have this code:
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
win_w, win_h = 250, 1
self.setGeometry((1920 - win_w) // 2, (1080 - win_h) // 2, win_w, win_h)
self.setWindowTitle('Test')
self.setFont(QtGui.QFont('Times', 12))
self.central_widget()
def central_widget(self):
widget = QtWidgets.QWidget()
grid = QtWidgets.QGridLayout()
group_box1 = QtWidgets.QGroupBox('Group Box')
v1 = QtWidgets.QVBoxLayout()
text_edit1 = QtWidgets.QTextEdit()
v1.addWidget(QtWidgets.QPushButton('Button'))
v1.addWidget(text_edit1)
group_box1.setLayout(v1)
grid.addWidget(group_box1, 0, 0)
widget.setLayout(grid)
self.setCentralWidget(widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Running this brings up this window:
Adding this line v1.setSpacing(100) changes it to this:
Is there any way to make it add the spacing horizontally? Like this:
Use the alignment keyword argument for addWidget():
v1.addWidget(QtWidgets.QPushButton('Button'), alignment=QtCore.Qt.AlignRight)
As already suggested, you should carefully read the documentation about layout managers, including all the listed QLayout subclasses and all their methods. You can do some experiments on your own with them also in Designer, so that you can better understand how they work by directly seeing the results.
Related
I'm making an application in PyQt4 and this is my code so far:
import sys
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.initUi()
def initUi(self):
self.setWindowTitle('Main Menu')
self.setFixedSize(1200, 625)
self.firstWidgets()
self.show()
def firstWidgets(self):
self.vbox1 = QtGui.QVBoxLayout()
self.task1 = QtGui.QLabel('Check 1', self)
self.task1CB = QtGui.QCheckBox(self)
self.hbox1 = QtGui.QHBoxLayout()
self.hbox1.addWidget(self.task1)
self.hbox1.addWidget(self.task1CB)
self.vbox1.addLayout(self.hbox1)
self.setLayout(self.vbox1)
def main():
application = QtGui.QApplication(sys.argv)
gui = MainWindow()
sys.exit(application.exec_())
if __name__=='__main__':
main()
My problem is in MainWindow.firstWidgets(). I try to set a layout but I get an error even though that's my first time using .setLayout for that form, which confuses me.
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "",
which already has a layout
You can't set a QLayout directly on the QMainWindow. You need to create a QWidget and set it as the central widget on the QMainWindow and assign the QLayout to that.
wid = QtGui.QWidget(self)
self.setCentralWidget(wid)
layout = QtGui.QVBoxLayout()
wid.setLayout(layout)
NOTE: This is for Qt4 -- see the other answer on this question for the Qt5 updated code.
Just an update to Brenden Abel's answer:
QWidget and QVBoxLayout (for Python3, PyQt5) are now contained in the PyQt5.QtWidgets module and not the PyQt5.QtGui module.
So updated code:
wid = QtWidgets.QWidget(self)
self.setCentralWidget(wid)
layout = QtWidgets.QVBoxLayout()
wid.setLayout(layout)
This is an example using PyQt5
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QWidget
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('My App')
# Cannot set QxxLayout directly on the QMainWindow
# Need to create a QWidget and set it as the central widget
widget = QWidget()
layout = QVBoxLayout()
b1 = QPushButton('Red' ); b1.setStyleSheet("background-color: red;")
b2 = QPushButton('Blue' ); b2.setStyleSheet("background-color: blue;")
b3 = QPushButton('Yellow'); b3.setStyleSheet("background-color: yellow;")
layout.addWidget(b1)
layout.addWidget(b2)
layout.addWidget(b3)
widget.setLayout(layout)
self.setCentralWidget(widget)
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Why the sizePolicy doesn't affect on widgets that aren't in layout?
here is an example:
from PyQt5 import QtWidgets
app = QtWidgets.QApplication([])
window = QtWidgets.QWidget()
window.setGeometry(50, 50, 500, 300)
test_widget = QtWidgets.QWidget(window)
test_widget.setMinimumSize(100, 100)
test_widget.setStyleSheet("background-color:red")
size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
test_widget.setSizePolicy(size_policy)
window.show()
app.exec()
But that doesn't work, if you changed the main window size the red box still has the same size.
So how can I make that red box resizeable when the parent (main window) is changing.
NOTE: I don't want to use Layouts for some reason.
I'm not sure I completely understand your GUI design but you should note that a single cell (as defined by a row/column pair) in a QGridLayout can be occupied by more than a single widget. A (very) simple example demonstrates this...
#!/usr/local/bin/python3
import os
import sys
from PySide2.QtWidgets import QApplication, QGridLayout, QLabel, QPushButton, QWidget
from PySide2.QtCore import Qt
class widget(QWidget):
def __init__ (self, parent = None):
super(widget, self).__init__(parent)
gl = QGridLayout(self)
pb = QPushButton("Show/Hide Menu")
self.menu = QLabel("Menu goes here...")
self.menu.setAlignment(Qt.AlignCenter)
self.menu.setStyleSheet("background-color: #40800000;")
canvas = QLabel("Canvas")
canvas.setAlignment(Qt.AlignCenter)
canvas.setStyleSheet("background-color: #40000080;")
gl.addWidget(pb, 0, 0)
gl.addWidget(canvas, 0, 0, 2, 2)
pb.raise_()
pb.clicked.connect(self.toggle_menu)
gl.addWidget(self.menu, 1, 0)
self.menu.hide()
def toggle_menu (self, checked):
self.menu.setVisible(not self.menu.isVisible())
if __name__ == '__main__':
app = QApplication([])
w = widget()
w.show()
app.exec_()
[I've used PySide2 as I don't have PyQt5 installed.]
So if I have understood correctly then I don't see why you can't make use of a QGridLayout. Could save you a lot of work.
Just like in the image below, I have a QHBoxLayout. Inside this 2 QVBoxLayout where I add a series of widgets to both. But I want the split of QHBoxLayout to be perfectly in the middle. Some of the widgets inside each side has expanding option but I don't want to QHBoxLayout to allow any side to cross more than half the size of the entire window.
Is this possible? How can I do this?
A possible solution is to set the same stretch factor when adding the QVBoxLayout:
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
hlay = QtWidgets.QHBoxLayout(self)
left_vlay = QtWidgets.QVBoxLayout()
right_vlay = QtWidgets.QVBoxLayout()
hlay.addLayout(left_vlay, stretch=1)
hlay.addLayout(right_vlay, stretch=1)
left_vlay.addWidget(QtWidgets.QTextEdit())
right_vlay.addWidget(QtWidgets.QLineEdit())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I'm making an application in PyQt4 and this is my code so far:
import sys
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.initUi()
def initUi(self):
self.setWindowTitle('Main Menu')
self.setFixedSize(1200, 625)
self.firstWidgets()
self.show()
def firstWidgets(self):
self.vbox1 = QtGui.QVBoxLayout()
self.task1 = QtGui.QLabel('Check 1', self)
self.task1CB = QtGui.QCheckBox(self)
self.hbox1 = QtGui.QHBoxLayout()
self.hbox1.addWidget(self.task1)
self.hbox1.addWidget(self.task1CB)
self.vbox1.addLayout(self.hbox1)
self.setLayout(self.vbox1)
def main():
application = QtGui.QApplication(sys.argv)
gui = MainWindow()
sys.exit(application.exec_())
if __name__=='__main__':
main()
My problem is in MainWindow.firstWidgets(). I try to set a layout but I get an error even though that's my first time using .setLayout for that form, which confuses me.
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "",
which already has a layout
You can't set a QLayout directly on the QMainWindow. You need to create a QWidget and set it as the central widget on the QMainWindow and assign the QLayout to that.
wid = QtGui.QWidget(self)
self.setCentralWidget(wid)
layout = QtGui.QVBoxLayout()
wid.setLayout(layout)
NOTE: This is for Qt4 -- see the other answer on this question for the Qt5 updated code.
Just an update to Brenden Abel's answer:
QWidget and QVBoxLayout (for Python3, PyQt5) are now contained in the PyQt5.QtWidgets module and not the PyQt5.QtGui module.
So updated code:
wid = QtWidgets.QWidget(self)
self.setCentralWidget(wid)
layout = QtWidgets.QVBoxLayout()
wid.setLayout(layout)
This is an example using PyQt5
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QWidget
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('My App')
# Cannot set QxxLayout directly on the QMainWindow
# Need to create a QWidget and set it as the central widget
widget = QWidget()
layout = QVBoxLayout()
b1 = QPushButton('Red' ); b1.setStyleSheet("background-color: red;")
b2 = QPushButton('Blue' ); b2.setStyleSheet("background-color: blue;")
b3 = QPushButton('Yellow'); b3.setStyleSheet("background-color: yellow;")
layout.addWidget(b1)
layout.addWidget(b2)
layout.addWidget(b3)
widget.setLayout(layout)
self.setCentralWidget(widget)
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I am trying to put a QToolBar on a layout of a QWidget instead of QMainWindow. On QMainWindow and QWidget is working fine, but when i try to add it on a layout first, is not. Am I doing something wrong? Is it possible? Here is my code:
from PyQt4 import QtGui, QtCore
import sys
img = '../../Images/logo.png'
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainWin = QtGui.QMainWindow()
widget = QtGui.QWidget()
hLayout = QtGui.QHBoxLayout()
'''ToolBar On main Window '''
basicToolBar = mainWin.addToolBar('Basic')
basicToolBar.addAction(QtGui.QAction('Test', mainWin))
# basicToolBar.addAction(QtGui.QAction(QtGui.QIcon(img), 'Test', mainWin))
# mainWin.show()
'''ToolBar On Widget '''
# Case 1: Set widget as parent
# widgetToolBar = QtGui.QToolBar(widget)
# widgetToolBar.addAction(QtGui.QAction('Test', widget))
# widgetToolBar.addAction(QtGui.QAction(QtGui.QIcon(img), QtGui.QAction('Test', widget))
# Case 2: Set toolBat on a layout
widgetToolBar = QtGui.QToolBar()
widgetToolBar.addAction(QtGui.QAction('Test', None))
# widgetToolBar.addAction(QtGui.QAction(QtGui.QIcon(img), 'Test', None))
hLayout.addWidget(widgetToolBar)
widget.setLayout(hLayout)
widget.show()
# Run
sys.exit(app.exec_())
QToolBar can only be in a QMainWindow since the QMainWindow has a special layout.
So you can use a secondary QMainWindow without problems as I show below:
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tabwidget = QtGui.QTabWidget()
self.setCentralWidget(self.tabwidget)
for name in ("tab1", "tab2", "tab3"):
self.create_widgets(name)
def create_widgets(self, name):
w = QtGui.QMainWindow()
self.tabwidget.addTab(w, name)
basicToolBar = w.addToolBar('Basic')
basicToolBar.addAction('Test')
basicToolBar.addAction(QtGui.QIcon("home.png"), 'Test')
tab = QtGui.QTabWidget()
w.setCentralWidget(tab)
for i in range(10):
tab.addTab(QtGui.QWidget(), "tab-{}".format(i))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Hmmm have you read the description of QToolBar? http://doc.qt.io/qt-5/qtoolbar.html#details
I think it won't work like this if your Object isn't a child of QMainWindow. The documentation says:
When a QToolBar is not a child of a QMainWindow, it loses the ability to populate the extension pop up with widgets added to the toolbar using addWidget(). Please use widget actions created by inheriting QWidgetAction and implementing QWidgetAction::createWidget() instead.