An error with QMenuBar in PyQt4 - python

I've tried to put a MenuBar but it doesn't appear, and I don't know what I doing wrong.
from PyQt4 import QtGui
import sys
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("IDE")
self.initUI
def initUI(self):
grid = QtGui.QGridLayout(self)
menuBar = QtGui.QMenuBar(self)
self.fileMenu = menuBar.addMenu("File")
grid.addWidget(menuBar, 0, 0)
self.setLayout(grid)
and the result:

You'll need to set the menubar on the main window
self.setMenuBar(menuBar)
In many cases, you don't need to create the menubar manually, you can just call .menuBar() on the main window and it will return the current one or create one if it doesn't exist. This is the preferred way if there's a chance your .ui file contains a menubar and menubar items.
menubar = self.menuBar()
Also, you can't add QMenuBars to layouts - from the docs:
There is no need to lay out a menu bar. It automatically sets its own geometry to the top of the parent widget and changes it appropriately whenever the parent is resized.

Related

QMainWindow default selecting a QPushButton(Focus)

I'm in a bit of a bind because I have been experimenting on creating a GUI with pyqt4 through python.
In QDialog when you open a window, it automatically focus on a QPushButton and you can press Tab to cycle through the QDialog and press enter on the selected QPushButton or menuBar etc. but how do I do it on QMainWindow? Setting
button1.setAutoDefault(True)
does work but cycling selection in QMainWindow(with Tab) does select other Qbject but pressing enter does not work
unless I re-select the button1 through Tab(Enter only works on the default button1). I've tried reading the documentation but maybe I missed something?
Here's my code:
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setGeometry(750, 450, 400, 200)
self.setFixedSize(self.size())
btn1 = QtGui.QPushButton("OK", self)
btn1.clicked.connect(self.trans_num)
btn1.resize(btn1.minimumSizeHint())
btn1.move(210,171)
btn1.setStatusTip("Magic")
btn1.setDefault(True)
btn1.setAutoDefault(True)
btn2 = QtGui.QPushButton("Exit", self)
btn2.clicked.connect(self.close_application)
btn2.resize(btn2.minimumSizeHint())
btn2.move(305,171)
btn2.setStatusTip("Exit Application")
self.show()

Pyside GUI function overwrite issue

I am learning to make GUI's in PySide.
How do I re-size the buttons inside a QHBoxLayout()? I tried button_1.setFixedWidth() and button_1.setFixedHeight() these make the buttons non-scalable. button_1.move() also doesn't work.
Also I have created a function angles() which have Qlabel and QLineEdit, when I run the program, the button function is over-writing the angles function to display only buttons at right corner of the GUI.
And how to resize the length of the QLineEdit and for it to not extend the whole window?
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class MainWindow(QMainWindow):
#GUI Layout
def __init__(self,parent = None):
super(MainWindow, self).__init__(parent)
widget = QWidget()
self.setCentralWidget(widget)
self.setWindowTitle("Example")
self.setGeometry(400, 100, 1500, 800)
self.angles()
self.makebuttons()
def angles(self):
central_widget = QWidget()
self.setCentralWidget(central_widget)
Rotation = QLabel('Rotation:')
Tilt = QLabel('Tilt:')
RoatationEdit = QLineEdit()
TiltEdit = QLineEdit()
grid = QGridLayout()
grid.setSpacing(2)
grid.addWidget(Rotation,1,0)
grid.addWidget(RoatationEdit, 1, 1)
grid.addWidget(Tilt,2,0)
grid.addWidget(TiltEdit, 2, 1)
central_widget.setLayout(grid)
def makebuttons(self):
central_widget = QWidget()
self.setCentralWidget(central_widget)
hbox = QHBoxLayout()
button_1 = QPushButton("Button 1",self)
button_1.move(0,30)
hbox.addStretch(1)
button_2 = QPushButton("Button 2",self)
hbox.addStretch(1)
hbox.addWidget(button_1)
hbox.addWidget(button_2)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
central_widget.setLayout(vbox)
# central_widget.addLayout(vbox)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
If you want to resize use: button_1.setFixedSize({your scale}*button_1.size())
The makebuttons function creates another centralWidget by deleting all of the above, so you will not see what you did with angles.
To change the width of QLineEdit use {your QlineEdit} .setFixedWidth({your width})
I use Qt Designer for all of my Pyside GUI work, even if it's a fairly trivial program. It's much more than just a drag-and-drop WYSISYG tool. For things like push buttons in your example, you would be presented with a list of configurable properties including sizing parameters of the button as well as the ability to configure the layout.
So, my solution is to create your GUI in QT Designer then modify the layout there before using the pyside-uic tool to convert the code to python. Then just import the resulting python module into your code. From there you can still re-configure whatever you want later in your code if, for example, you need to change the appearance of your GUI during the course of your program.

Button not displayed in the right place

I am using PyQt to create a desktop application. I am trying to create a button using hbox and vbox, but it doesn't display unless I give the specific command:
button1 = QtGui.QPushButton("Exit", self)
But, by doing this, the vbox and hbox functionality doesn't seem to function.
I need the button to be on the bottom-right corner of the window, which stays there even after window-resize.
With this code, it is positioned on the top-left corner.
from PyQt4 import QtGui, QtCore
import sys
class Trial(QtGui.QMainWindow):
def __init__(self):
super(Trial,self).__init__()
self.createUI()
def createUI(self):
button1 = QtGui.QPushButton("Exit",self)
button1.clicked.connect(self.close)
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1) #stretches it to the right end of the page
hbox.addWidget(button1)
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1) #stretches it to the bottom end of the page
vbox.addLayout(hbox)
self.setLayout(vbox)
button1.resize(button1.sizeHint())
self.setGeometry(300,200,750,450)
self.setWindowTitle('Testing')
self.show()
def main():
app= QtGui.QApplication(sys.argv)
w=Trial()
sys.exit(app.exec_())
if __name__=='__main__':
main()
If I use button1.move(420, 400), it moves the button to the position I want, but it doesn't stay there when I re-size the application window.
The example code doesn't work because you are trying to set a layout on the main window, which already has a layout.
Instead, you need to add a central widget, and then set the layout on that:
def createUI(self):
self.setCentralWidget(QtGui.QWidget(self))
...
vbox.addLayout(hbox)
self.centralWidget().setLayout(vbox)
self.setGeometry(300,200,750,450)
...

PyQt4 Child Windows do NOT minimize to Windows taskbar

Whenever I create a PyQt4 application with secondary (child) windows they do not minimize to the Windows 7 taskbar. Only the main (parent) window shows up on the taskbar. When a child window is minimized it collapses to the bottom of the screen with only the titlebar (and titlebar buttons) showing. Here is some sample code to demo this behavoir:
import sys
from PyQt4 import QtGui, QtCore
class Parent(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Parent, self).__init__(parent)
w = QtGui.QWidget()
layout = QtGui.QVBoxLayout(w)
self.button = QtGui.QPushButton('Create Child')
self.text = QtGui.QTextEdit()
layout.addWidget(self.button)
layout.addWidget(self.text)
self.setCentralWidget(w)
self.setWindowTitle('Parent')
self.button.clicked.connect(self.createChild)
def createChild(self):
self.dialog = QtGui.QMainWindow(self)
#self.dialog.setParent(None)
self.dialog.setWindowTitle('Child')
self.dialog.show()
app = QtGui.QApplication(sys.argv)
p = Parent()
p.show()
sys.exit(app.exec_())
The only way I get my pyqt apps to behave the way I want is to set the parent of the children windows to None.
self.dialog.setParent(None)
Doing so makes keeping track of the children windows a lot more complicated than I feel it should be. Closing the main window does not close the secondary windows for example. With extra code this can work but it seems odd to have to break the parent relationship. Am I missing something?

How to make one window to block another without using .setModal(True)

If main window right-clicked a QInputDialog shows up. I want QInputDialog to block main window while it is open. How to achieve this?
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class AppWindow(QtGui.QMainWindow):
def __init__(self):
super(AppWindow, self).__init__()
mainWidget=QtGui.QWidget()
self.setCentralWidget(mainWidget)
mainLayout = QtGui.QVBoxLayout()
mainWidget.setLayout(mainLayout)
frame=QtGui.QFrame()
frame.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
frame.connect(frame, QtCore.SIGNAL("customContextMenuRequested(QPoint)" ), self.up)
mainLayout.addWidget(frame)
self.modal=QtGui.QInputDialog()
def up(self, QPos):
self.modal.move(QtGui.QCursor.pos())
self.modal.show()
self.modal.raise_()
window=AppWindow()
window.show()
sys.exit(app.exec_())
OK, This solution can be solve by use method QWidget.setWindowModality (self, Qt.WindowModality windowModality) . A modal window is one that blocks input to other windows. Note that windows that are children of a modal window are not blocked.
Add this line in your initial method;
self.modal.setWindowModality(QtCore.Qt.ApplicationModal)
Completed code is;
import sys
from PyQt4 import QtCore, QtGui
class AppWindow (QtGui.QMainWindow):
def __init__ (self):
super(AppWindow, self).__init__()
mainWidget = QtGui.QWidget(self)
self.setCentralWidget(mainWidget)
mainLayout = QtGui.QVBoxLayout()
mainWidget.setLayout(mainLayout)
frame = QtGui.QFrame()
frame.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
frame.connect(frame, QtCore.SIGNAL("customContextMenuRequested(QPoint)" ), self.up)
mainLayout.addWidget(frame)
self.modal = QtGui.QInputDialog(self)
self.modal.setWindowModality(QtCore.Qt.ApplicationModal)
def up (self, QPos):
self.modal.move(QtGui.QCursor.pos())
self.modal.show()
self.modal.raise_()
app = QtGui.QApplication([])
window = AppWindow()
window.show()
sys.exit(app.exec_())
Reference method : http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html#setWindowModality
Reference enum : http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#WindowModality-enum
Regards,
In a nut shell, this is the basic approach. I have created a second window (a Frame), containing a table widget, and the name of my class is TableWindow. Import that in your main window file. On a button click, I call the below function.
def call_table_window(self):
self.frame = QtGui.QFrame()
self.window_table = TableWindow()
self.window_table.setupUi(self.frame)
#This stops the user to switch to the main window. He has to close
#the 2nd window first.
self.frame.setWindowModality(QtCore.Qt.ApplicationModal)
self.frame.show()
Especially when working with PyQt5, you can set inside the __init__
self.setWindowModality(QtCore.Qt.ApplicationModal)

Categories