I'm trying to set a layout manager. But getting the message:
QLayout: Attempting to add QLayout "" to Window "", which already has a layout
How can I change or detect which type the layout is? I'd like to use the boxlayout as it seems to be prefered.
import sys
from PyQt4 import QtGui as qt
class Window(qt.QMainWindow):
def __init__(self):
super(Window, self).__init__()
#Lav widgets
self.CreateWidgets()
def CreateWidgets(self):
btn = qt.QPushButton("Fetch", self)
btn.clicked.connect(self.GetData)
self.layout = qt.QVBoxLayout(self)
self.setGeometry(560, 240, 800, 600)
self.setWindowTitle("We do not sow")
self.show()
def GetData(self):
print("Hello World!")
app = qt.QApplication(sys.argv)
w = Window()
sys.exit(app.exec_())
The QMainWindow class has built-in support for toolbars and dock-widgets, and a menubar and statusbar - so it has to have a fixed layout. Therefore, rather than adding child widgets to the main window itself, you must set its central widget, and then add the child widgets to that:
def CreateWidgets(self):
btn = qt.QPushButton("Fetch", self)
btn.clicked.connect(self.GetData)
widget = qt.QWidget(self)
layout = qt.QVBoxLayout(widget)
layout.addWidget(btn)
self.setCentralWidget(widget)
self.setGeometry(560, 240, 800, 600)
self.setWindowTitle("We do not sow")
Related
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)
I am looking to develop a Qt application whose main/parent widget is capable of 'holding' one or more "special" widgets. Each special widget displays a separate QGraphicsView and QGraphicsScene.
As far as I can see there can only be one central widget to which a graphics view can be set i.e. QMainWindow::setCentralWidget( QGraphicsView ), whereas I would like to have multiple graphics views.
Here is my failed quick and dirty attempt (in PySide)
#!/usr/bin/python
from PySide import QtGui
import sys
class MyApp(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
layout = QtGui.QHBoxLayout()
self.scene1 = QtGui.QGraphicsScene(self)
self.scene1.addRect(5,5,200,200)
self.view1 = QtGui.QGraphicsView(self.scene1, self)
self.scene2 = QtGui.QGraphicsScene(self)
self.scene2.addLine(500,500,300,300)
self.view2 = QtGui.QGraphicsView(self.scene1, self)
layout.addWidget(self.view1)
layout.addWidget(self.view2)
self.setLayout(layout)
self.show()
if __name__=="__main__":
app=QtGui.QApplication(sys.argv)
myapp = MyApp()
sys.exit(app.exec_())
QMainWindow has a default layout, you do not have to set it. In Qt a QWidget can be used as a container, so we create a widget that will be the container of the QGraphicsViews and also the centralwidget:
class MyApp(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyApp, self).__init__(parent)
self.scene1 = QtGui.QGraphicsScene(self)
self.scene1.addRect(5,5,200,200)
self.view1 = QtGui.QGraphicsView(self.scene1)
self.scene2 = QtGui.QGraphicsScene(self)
self.scene2.addLine(500,500,300,300)
self.view2 = QtGui.QGraphicsView(self.scene2)
central_widget = QtGui.QWidget()
layout = QtGui.QHBoxLayout(central_widget)
layout.addWidget(self.view1)
layout.addWidget(self.view2)
self.setCentralWidget(central_widget)
self.show()
I have a simple PyQt4 example.
When run, it displays a QMainWindow with a button.
If you click the button, then a second QMainWindow is created.
If you click it again, you get 2 second windows.
What is an elegant and simple way to prevent more than 1 second window in this example?
import sys
from PyQt4.QtGui import *
class win2(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self,parent)
layout = QVBoxLayout()
label = QLabel(self)
label.setText('This is win2')
layout.addWidget(label)
self.adjustSize()
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
layout = QVBoxLayout()
button1 = QPushButton("win2", self)
layout.addWidget(button1)
button1.clicked.connect(self.showwin2)
def showwin2(self):
w2 = win2(self)
w2.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
Your Function creates a new instance of the class win2 each time the button is pressed. To Supress this behavior only call the show and raise_ functions instead of creating a new instance.
I would create the class as follows, and only use the button to 'show' the window. Tested and works as intended. Also consider using self when assigning your variables so they can be accessed throughout the class instance.
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
layout = QVBoxLayout()
button1 = QPushButton("win2", self)
layout.addWidget(button1)
button1.clicked.connect(self.showwin2)
self.w2 = win2(self)
def showwin2(self):
self.w2.show()
self.w2.raise_()
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()
I have a Qwidget thats usually is displayed in a Qmainwindow.
Sometimes its unnecessary to use the whole mainwindow, because you only want to use functions from a certain Qwidget. If that's the case, I want a menubar in my widget.
I tried:
if parent == "self":
self.layout().addMenubar(self)
But using the code above the its just stops compiling without raising any error.
What Im doing wrong? Thanks!
OK, I can do !
You just add QtGui.QMenuBar(self) in your QWidget and implement just like QMainWindows.
Reference : Here
Example;
import sys
from PyQt4 import QtGui
class QTestWidget (QtGui.QWidget):
def __init__ (self):
super(QTestWidget, self).__init__()
self.myQMenuBar = QtGui.QMenuBar(self)
exitMenu = self.myQMenuBar.addMenu('File')
exitAction = QtGui.QAction('Exit', self)
exitAction.triggered.connect(QtGui.qApp.quit)
exitMenu.addAction(exitAction)
myQApplication = QtGui.QApplication(sys.argv)
myQTestWidget = QTestWidget()
myQTestWidget.show()
myQApplication.exec_()
Regards,
There is also a pretty clean way to combine QMainWindow with QWidget, using two classes:
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.win_widget = WinWidget(self)
widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout(widget)
layout.addWidget(self.win_widget)
self.setCentralWidget(widget)
self.statusBar().showMessage('Ready')
self.toolbar = self.addToolBar('Exit')
exitAction = QtGui.QAction ('Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(QtGui.qApp.quit)
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
self.setGeometry(300, 300, 450, 250)
self.setWindowTitle('Test')
self.setWindowIcon (QtGui.QIcon('logo.png'))
self.show()
class WinWidget (QtGui.QWidget) :
def __init__(self, parent):
super (WinWidget , self).__init__(parent)
self.controls()
#self.__layout()
def controls(self):
self.qbtn = QtGui.QPushButton('Quit', self)
self.qbtn.setFixedSize (100,25)
self.qbtn.setToolTip ("quit")
self.qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
self.qbtn.move(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This works :
def menu_bar (self) :
self.menuBar = QtGui.QMenuBar (self)
fileMenu = self.menuBar.addMenu ("File")
self.menuBar.show()
or already with actions :
def menu_bar (self) :
self.menuBar = QtGui.QMenuBar (self)
fileMenu = self.menuBar.addMenu ("File")
exitAction = QtGui.QAction(QtGui.QIcon('exit24.png'), 'Exit', self)
fileMenu.addAction(exitAction)
exitAction.triggered.connect(self.close)
exitAction.setShortcut('Ctrl+Q')
self.menuBar.show()
It will be a good idea to keep using QMainWindow since QMenuBar is designed to be used within it.
That said, I found this post helpful when I was also looking into doing same:
Qt QWidget add menubar
See if it's the solution that can help you. It helped me though