Cannot define QLabels with QPixmap in cycle [duplicate] - python

Probably a noob question, but I'm still learning PySide. So I'm trying to use QMainWindow which has a QFrame and the QFrame has two labels. I'm using QBoxLayouts on QMainWindow and QFrame. The problem is that when I set the QFrame to something like 200x200 then QMainWindow does not resize, it remains too small to display both labels. Correct me if I'm wrong but shouldn't QMainWindow automatically have the right size when using layouts? Additionaly when I output frame.sizeHint() then it outputs PySide.QtCore.QSize(97, 50) but I would expect it to be 200, 200.
The code below will reproduce the problem:
import sys
from PySide import QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.initUI()
def initUI(self):
#-------
#CREATE WIDGETS
#-------
frame = QtGui.QFrame()
frame.setStyleSheet("QFrame {background-color: yellow}")
frame.setGeometry(0, 0, 200, 200)
someLabel = QtGui.QLabel("SomeLabel")
someOtherLabel = QtGui.QLabel("SomeOtherLabel")
self.setCentralWidget(frame)
#--------
#CREATE LAYOUT
#--------
frameLayout = QtGui.QVBoxLayout()
frameLayout.addWidget(someLabel)
frameLayout.addWidget(someOtherLabel)
frame.setLayout(frameLayout)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(frame)
self.setLayout(mainLayout)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
mainWindow = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This is what happens after code is run:

A QMainWindow already has a top-level layout, so you should never set one yourself. All you need to do is set the central-widget, and then add a layout and widgets to that.
Your example can therefore be fixed like this:
frame.setLayout(frameLayout)
# get rid of these three lines
# mainLayout = QtGui.QVBoxLayout()
# mainLayout.addWidget(frame)
# self.setLayout(mainLayout)
self.show()
It's worth noting that there is possibly a bug/misfeature in PySide regarding this, because in PyQt your original script would print a useful error message:
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "", which already has a layout

Related

How to add PyQt5 layout to parent window and show? [duplicate]

I am making a GUI with PyQt, and I am having issues with my MainWindow class. The window doesn't show widgets that I define in other classes, or it will show a small portion of the widgets in the top left corner, then cut off the rest of the widget.
Can someone please help me with this issue?
Here is some example code showing my issue.
import sys
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.resize(300, 400)
self.centralWidget = QtGui.QWidget(self)
self.hbox = QtGui.QHBoxLayout(self.centralWidget)
self.setLayout(self.hbox)
names = ['button1', 'button2', 'button3']
testButtons = buttonFactory(names, parent=self)
self.hbox.addWidget(testButtons)
class buttonFactory(QtGui.QWidget):
def __init__(self, names, parent=None):
super(buttonFactory, self).__init__(parent=parent)
self.vbox = QtGui.QVBoxLayout()
self.setLayout(self.vbox)
for name in names:
btn = QtGui.QPushButton(name)
self.vbox.addWidget(btn)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
gui = MainWindow()
gui.show()
app.exec_()
A QMainWindow has a central widget that is a container in which you should add your widgets. It has its own layout. The layout of the QMainWindow is for toolbars and such. The centralWidget must be set with the setCentralWidget method. It isn't enough to just call it self.centralWidget
Use the following three lines instead.
self.setCentralWidget(QtGui.QWidget(self))
self.hbox = QtGui.QHBoxLayout()
self.centralWidget().setLayout(self.hbox)

How can I get rid of the previous layout and set new Grid Layout in QMainWindow?

I am a newbie with PyQt. I am trying to organize my buttons on a grid layout, but I guess the window has a default layout already. How can I get rid of it and replace it with the new Grid Layout? I have contained the code block relevant with hashes ###, Here is my program:
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QWidget
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setMinimumSize (800,600) # set minimum size for window
self.setWindowTitle("CoolPlay Kabul") # set window title
self.setWindowIcon(QtGui.QIcon("images/CoolPlay.png"))# set icon for Window
myMenu = self.menuBar()
File_Menu = myMenu.addMenu("&File")
Items_Menu = myMenu.addMenu("&Items")
Playlist_Menu = myMenu.addMenu("&Playlist")
Option_Menu = myMenu.addMenu("&Option")
Exit_Menu = myMenu.addMenu("&Exit")
File_Menu.addAction("New Time")
File_Menu.addAction("Delete Time")
File_Menu.addSeparator()
File_Menu.addAction("Exit")
Items_Menu.addAction("New Item")
Items_Menu.addAction("Delete Item")
Items_Menu.addSeparator()
Items_Menu.addAction("Toggle Segue")
Playlist_Menu.addAction("Clear Playlist")
Playlist_Menu.addAction("Save playlist")
Playlist_Menu.addAction("Load Playlist")
Playlist_Menu.addSeparator()
Playlist_Menu.addAction("Clear 'Played' Indication")
Option_Menu.addAction("Application Setup")
Exit_Menu.addAction("Help")
Exit_Menu.addAction("About")
######################################################
Overall_Layout = QtGui.QGridLayout(self)
self.setLayout(Overall_Layout)
Play_Button = QtGui.QPushButton(QtGui.QIcon("images/PLAY.bmp"), "PLAY",self)
Overall_Layout.addWidget(Play_Button,1,2)
Overall_Layout.addWidget(Play_Button,2,2)
########################################################
self.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
CoolPlay = MainWindow()
CoolPlay.show()
sys.exit(app.exec_())
QMainWindow is a special widget since it already has a preset layout as shown below:
So in this case you should not set a layout to the QMainWindow but to the central widget, but first establish a centralwidget, using the indicated thing we get the following:
######################################################
central_widget = QtGui.QWidget()
self.setCentralWidget(central_widget)
Overall_Layout = QtGui.QGridLayout(central_widget)
Play_Button = QtGui.QPushButton(QtGui.QIcon("images/PLAY.bmp"), "PLAY")
Overall_Layout.addWidget(Play_Button,1,2)
Overall_Layout.addWidget(Play_Button,2,2)
########################################################
On the other hand if you inherit from QMainWindow you must call the QMainWindow constructor, but in code you call QWidget, so you must modify it to:
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Or
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

PyQt add widget to second window

I've got the following python code which opens a second window. I can't figure out how to add a label or pushbutton to this second window. I thought it would be easy but nothing I try seems to work. Thanks!
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
menu = self.menuBar().addMenu(self.tr('View'))
action = menu.addAction(self.tr('New Window'))
action.triggered.connect(self.handleNewWindow)
def handleNewWindow(self):
window = QtGui.QMainWindow(self)
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle(self.tr('New Window'))
window.show()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.resize(300, 300)
window.show()
sys.exit(app.exec_())
If the two windows are different, it makes more sense to create two class.
I guess the second one doesn't need to be a QMainWindow (= it doesn't need a menu and a toolbar and a status bar etc), so let's just make it a QWidget.
class SecondWindow(QtGui.QWidget):
def __init__(self,parent):
QtGui.QWidget.__init__(self,parent)
self.button=QtGui.QPushButton("my button !")
layout=QtGui.QHBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
self.show()
In your main window, you cretae and instance of the class SecondWindow:
class FirstWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
...
self.show()
def handleNewWindow(self):
self.childWindow = SecondWindow(self)
If you just want a TopLevel window, using QtGui.QDialog seems to be more appropriate. To add button and label, you can do something like this:
def handleNewWindow(self):
window = QtGui.QMainWindow(self)
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle(self.tr('New Window'))
button = QtGui.QPushButton("MY BUTTON!") #create button
label = QtGui.QLabel("MY LABEL!") # create label
CentralWidget = QtGui.QWidget() # create an empty widget
CentralWidgetLayout = QtGui.QHBoxLayout() # create a layout
CentralWidgetLayout.addWidget(label) # add your label to the layout
CentralWidgetLayout.addWidget(button) # add your button to the layout
CentralWidget.setLayout(CentralWidgetLayout) # assign your layout to the empty widget
window.setCentralWidget(CentralWidget) #make the assigned widget CentralWidget
window.show()

PySide: If I add a custom widget with its own layout to a parent widget's layout, it has an offset. What causes this?

I'm running into a bit of a program with an interface I'm designing. It's a bit hard to concisely explain the problem, so I'll introduce the elements at play first. I have a QMainWindow MainWindow that has QWidget MainWidget as central widget. MainWidget contains two widgets: A QLabel and QWidget SubWidget. SubWidget contains a mere QLabel.
Better illustrated (I hope I represented inheritance correctly. Either way, MainWindow inherits from QMainWindow, etc.):
form (MainWindow::QMainWindow)
|main_widget (MainWidget::QWidget)
||label_1 (QLabel)
||sub_widget (SubWidget::QWidget)
|||label_2 (QLabel)
The problem lies herein; the label inside SubWidget has an offset to the right. An image can be found here.
The code is fairly straightforward. I tried to condense it as much as I could.
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.main_widget = MainWidget(self)
self.setCentralWidget(self.main_widget)
class MainWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.label_1 = QLabel("Label 1")
self.sub_widget = SubWidget()
self.layout = QVBoxLayout() # Vertical layout.
self.layout.addWidget(self.label_1)
self.layout.addWidget(self.sub_widget)
self.setLayout(self.layout)
class SubWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.label_2 = QLabel("Label 2")
self.layout = QHBoxLayout() # Horizontal layout.
self.layout.addWidget(self.label_2)
self.setLayout(self.layout)
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
if __name__ == "__main__":
main()
The obvious solution would be to put label_2 in MainWidget, but that conflicts with what I want to do. What causes the weird offset? Is there anything I can do to combat it?
Thank you very much!
self.layout.setContentsMargins(0, 0, 0, 0)
in SubWidget.
http://doc.qt.io/qt-5/qlayout.html#contentsMargins

PyQt : How to add a grid layout inside a QGroupBox in PyQt4

I am trying to create an application window with PyQt4. I want to create a window with a frame and inside that frame some widgets such as labels and text editors.
I created the frame as a QGroupBox to be able to put a title on it.
I know that HBox and VBox seem to be the prefered layout when you deal with frames, however, I would like to manage the positionning of the widgets inside my frame with a grid Layout, which I find easier to manage.
So I tried this piece of code :
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
grid = QtGui.QGridLayout()
#Definition des Tracing Parameters widgets
WindowSize = QtGui.QLabel("Window size (m)")
SampPts = QtGui.QLabel("Sampling points")
WindowSizeEdit = QtGui.QLineEdit()
SampPtsEdit = QtGui.QLineEdit()
TracParamFrame = QtGui.QGroupBox(self)
TracParamFrame.setTitle("Tracing Parameters")
hbox.addLayout(grid)
grid.addWidget(WindowSize,0,0)
grid.addWidget(WindowSizeEdit,0,1)
grid.addWidget(SampPts,1,0)
grid.addWidget(SampPtsEdit,1,1)
self.setLayout(hbox)
self.setGeometry(300,300,350,300)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The main idea here was to create an hbox where I put the QGroupBox and then place a grid layout inside.
The problem is that in the application generated, the widgets are placed outside the frame, and in addition I get the error :
QLayout: Attempting to add QLayout "" to Example "", which already has a layout
QWidget::setLayout: Attempting to set QLayout "" on Example "", which already has a layout
I modified your code, by adding this statement: TracParamFrame.setLayout(hbox)
The code with this added is as:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
grid = QtGui.QGridLayout()
#Definition des Tracing Parameters widgets
WindowSize = QtGui.QLabel("Window size (m)")
SampPts = QtGui.QLabel("Sampling points")
WindowSizeEdit = QtGui.QLineEdit()
SampPtsEdit = QtGui.QLineEdit()
TracParamFrame = QtGui.QGroupBox(self)
TracParamFrame.setTitle("Tracing Parameters")
hbox.addLayout(grid)
grid.addWidget(WindowSize,0,0)
grid.addWidget(WindowSizeEdit,0,1)
grid.addWidget(SampPts,1,0)
grid.addWidget(SampPtsEdit,1,1)
TracParamFrame.setLayout(hbox)
#self.setLayout(hbox)
self.setGeometry(300,300,350,300)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Ok forget it, I found the solution. I had to use the setLayout method of the GroupBox as follows :
TracParamFrame.setLayout(grid)

Categories