In these days I'm trying to replicate a GUI already written with Tkinter with PyQt5, but I'm new with this framework and I don't still know how to complete some steps. Here is my code:
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
import sys
class MainWindow(qtw.QMainWindow):
def __init__(self):
"""MainWindow constructor"""
super().__init__()
self.title="Main Window"
self.setWindowTitle(self.title)
self.top, self.left, self.width, self.height = 250, 250, 760, 620
self.setGeometry(self.top, self.left, self.width, self.height)
self.setMinimumSize(760, 620)
self.CreateMenu()
self.CreateFrames()
self.show()
def CreateMenu(self):
MainMenu=self.menuBar()
EditMenu=MainMenu.addMenu("Test1")
HelpMenu=MainMenu.addMenu("Test2")
Test1_1=qtw.QAction("Test1-1", self)
Test1_1.triggered.connect(self.Test)
EditMenu.addAction(Test1_1)
Test2_1=qtw.QAction("Test2-1", self)
Test2_1.triggered.connect(self.Test)
HelpMenu.addAction(Test2_1)
def CreateFrames(self):
TheFrame=qtw.QWidget(self)
TheFrame.setStyleSheet("background-color:blue")
self.setCentralWidget(TheFrame)
TheLayout=qtw.QVBoxLayout()
TheFrame.setLayout(TheLayout)
MainFrame, ButtonsFrame = qtw.QFrame(), qtw.QFrame()
MainFrame.setStyleSheet("background-color:red"), ButtonsFrame.setStyleSheet("background-color:green")
TheLayout.addWidget(MainFrame)
TheLayout.addWidget(ButtonsFrame)
# the "resize" method doesn't work..
self.Button1=qtw.QPushButton("Button 2")
self.Button1.resize(50,100)
self.Button2=qtw.QPushButton("Button 2")
self.Button2.resize(50,100)
self.Button3=qtw.QPushButton("Button 2")
self.Button3.resize(50,100)
ButtonsLayout=qtw.QHBoxLayout()
ButtonsFrame.setLayout(ButtonsLayout)
ButtonsLayout.addWidget(self.Button1)
ButtonsLayout.addStretch()
ButtonsLayout.addWidget(self.Button2)
ButtonsLayout.addWidget(self.Button3)
def Test(self):
pass
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
mw = MainWindow()
sys.exit(app.exec())
Inside the main window, I create TheFrame
(the blu frame), and inside of it, I create the ButtonsFrame
and MainFrame
too (the green and the red ones). My questions are:
Did I follow the right approach? I mean, does PyQt make me to create TheFrame
? Because I thought, is it not better to create ButtonsFrame
and MainFrame
in the main window directly? I tried but it didn't work.. I can't create a new layout in a QMainWindow
widget, there is a default one, but I don't know about its nature. What kind of layout is it?
When I put the ButtonsFrame
and MainFrame
inside TheFrame
, I realized that exist some default spaces between the widgets (I sign them in the attached screenshot). How can I manage the size of these default spaces manually? I saw the same spaces when I put the buttons widgets..
When I use the QHBoxLayout
object, how can I set a static height for the frames placed inside it? For example, in my code I want to set a default height for the ButtonsFrame
, in my mind it has not to expand upwards. How can I do it?
How can I change the size for my buttons? As you can see, the resize
method doesn't work..
TL; DR; Everything it asks for is in the Qt docs. The Qt docs is one of the best since they clearly indicate the limitations and what functionalities they cover, so it is recommended that any Qt user read it.
If you check the docs of QMainWindow it clearly indicates that this widget has a predefined structure (check the link for more information as well as this question has been many times in SO).
If you don't want that default structure then use QWidget instead of QMainWindow which is the basic building block for building any type of widget.
Those spaces can be modified using the QHBoxLayout's setContentsMargins()
and setSpacing()
methods.
TheLayout.setContentsMargins(10, 20, 30, 40)
TheLayout.setSpacing(50)
The layouts are managers of the geometry (position and size) of the child widgets of the parent widget where it is set, so they use additional information (such as sizeHint, sizePolicy, stretch factor, etc). So if you want to set a fixed height then set that height in the container:
ButtonsFrame.setFixedHeight(300)
Or in this case it is better to make the top widget stretch as much as possible by setting a factor to 1.
TheLayout.addWidget(MainFrame, stretch=1)
TheLayout.addWidget(ButtonsFrame)
As the geometry of the button is handled by the layout then using resize() will not change anything as the layout will restore it to its default size. To avoid this then it is better to use setFixedSize()
:
self.Button1 = qtw.QPushButton("Button 2")
self.Button1.setFixedSize(50, 100)
self.Button2 = qtw.QPushButton("Button 2")
self.Button2.setFixedSize(50, 100)
self.Button3 = qtw.QPushButton("Button 2")
self.Button3.setFixedSize(50, 100)