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

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)

Related

PyQt4 How keep a QWidget always on top?

I'm using PyQt4 with python 2.7 on Windows7
I have a QWidget that I want to stay above the QMainWindow while clicking on the main. The idea is that the main will contain a series of 'edit' buttons that will open the edit widget, while the edit widget refreshes with info contained on the main. I don't particularly care if either is "always on top" as long as the widget stays in front of the main window.
There are a couple of questions that address this topic, but I'm not seeing an answer that works for my specific use case. One deals in widgets but provides an answer only for the app main window (widget stays above other environmental windows but falls behind the application main window when clicking on the main), and the other addresses Qt generally but not a pythonic example:
PyQt: Always on top
How keep a QWidget always on top?
Here is the code I have so far:
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self, None, QtCore.Qt.WindowStaysOnTopHint)
self.setWindowTitle("MainWindow")
self.resize(400, 300)
class Ui_Widget(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self, None, QtCore.Qt.WindowStaysOnTopHint)
self.setWindowTitle("Widget")
self.resize(400, 300)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = Ui_MainWindow()
MainWindow.show()
Widget = Ui_Widget()
Widget.show()
sys.exit(app.exec_())
If you want Ui_Widget to always be on top of Ui_MainWindow, Ui_Widget must be a child of Ui_MainWindow and the flag Qt::Dialog must be activated as shown below:
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowTitle("MainWindow")
self.resize(400, 300)
class Ui_Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowFlags(self.windowFlags() | QtCore.Qt.Dialog)
self.setWindowTitle("Widget")
self.resize(400, 300)
self.move(200, 150)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = Ui_MainWindow()
MainWindow.show()
Widget = Ui_Widget(MainWindow)
Widget.show()
sys.exit(app.exec_())

Why does my app close when opening a new window in PyQt5?

~EDIT (original question still below)~ when I remove the self.setGeometry() call in the new window it works as it should. Why is that? I'm still building out the UI for it, but once I do I hope I don't continue to have this problem...
~EDIT 2~ Just realized it should be self.resize() not self.setGeometry()...
self.solved()
:(
I'm just learning PyQt5 and just doing a little messing around. For some reason when I try to open a new window from the main application window, the whole thing closes. Putting in some print statements to track progress shows that it's not actually creating the new window either.
Main Window code:
import sys
from PyQt5.QtWidgets import QMainWindow, QAction, QApplication
from newLeague import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
newLeagueAction = QAction('Create New League', self)
newLeagueAction.setShortcut('Ctrl+N')
newLeagueAction.setStatusTip('Create a new league from scratch')
newLeagueAction.triggered.connect(self.createNewLeague)
openLeagueAction = QAction('Open Existing League', self)
openLeagueAction.setShortcut('Ctrl+E')
openLeagueAction.setStatusTip('Continue with a previously started league')
openLeagueAction.triggered.connect(self.openExistingLeague)
exitAction = QAction('Quit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Quit the application...')
exitAction.triggered.connect(self.close)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(newLeagueAction)
fileMenu.addAction(openLeagueAction)
fileMenu.addAction(exitAction)
self.resize(1920, 1080)
self.setWindowTitle("Brackets")
def createNewLeague(self):
'''shows dialog to create a new league'''
self.newLeague = CreateLeague()
self.newLeague.show()
print('New League being created...')
def openExistingLeague(self):
print('Existing League opening...')
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here is the second window:
from PyQt5.QtWidgets import QMainWindow
class CreateLeague(QMainWindow):
def __init__(self):
super(CreateLeague, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(600, 500)
self.setWindowTitle('Create A New League')
I've looked at other examples such as this, and this, and I'm not seeing what it is I'm doing different. I've experimented with using parent as an argument in the constructors and the result is no different.
Your Main Window code is ok, but you should remove CreateLeague, self arguments from the super parameters in your second window, then, your code should work fine.
See below:
from PyQt5.QtWidgets import QMainWindow
class CreateLeague(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(600, 500)
self.setWindowTitle('Create A New League')

Python PyQt4 open from QDialog new QWidget window

By pressing a QPushButton in my QDialog window I want to open a new QWidget window.
My code:
from PyQt4 import QtGui
import sys
class MainWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setWindowTitle("Main Window")
class FirstWindow(QtGui.QDialog):
def __init__(self, parent=None):
super(FirstWindow, self).__init__(parent)
self.createWindow()
def createWindow(self):
btn = QtGui.QPushButton('Open New Window', self)
btn.move(10, 10)
self.openNewWindow = MainWindow(self)
btn.clicked.connect(self.openMainWin)
self.setGeometry(250,250, 150,50)
self.setWindowTitle("First Window")
self.show()
def openMainWin(self):
self.openNewWindow.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
firstwin = FirstWindow()
sys.exit(app.exec_())
When I run the code nothing happens by pressing the button.
But when I change the class from
class MainWindow(QtGui.QWidget) to
class MainWindow(QtGui.QDialog) or class MainWindow(QtGui.QMainWindow)
it works!
What am I doing wrong?! Please assist me.
When you instantiate MainWindow you pass in a parent. Qwidget only makes a new window if you don't specify a parent.
This is of course deliberate. If QWidgets with parents were shown in new windows, then you could never build a GUI. Imagine having every widget in it's own window!
QMainWindow and QDialog are specifically designed to both have a parent, and create a new window. You should use them.

PyQt Window No Show

Upon calling the show method on simple the simple window does not show. Why doesn't my Simple window show. :(
import sys
from PyQt4 import QtGui
class Widget(QtGui.QWidget):
def __init__(self):
super(Widget, self).__init__()
simple = Simple()
button = QtGui.QPushButton("Button", self)
button.clicked.connect(simple.show)
self.show()
class Simple(QtGui.QWidget):
def __init__(self):
super(Simple, self).__init__()
self.setGeometry(300, 250, 250, 150)
self.setWindowTitle("Simple Widget")
if __name__ =="__main__":
app = QtGui.QApplication(sys.argv)
widget = Widget()
sys.exit(app.exec_())
Please Help!
The problem with your code is that, simple in __init__ method of class Widget is a local variable, so as soon as the __init__ method finishes execution, the simple object is destroyed by the python Garbage Collector, thus the window does not appear because the object does not exist in the memory. To solve your problem, just add self at the starting of the simple variable to make it member variable.
...
self.simple = Simple()
button = QtGui.QPushButton("Button", self)
button.clicked.connect(self.simple.show)
...

PyQt: Dialog's Minimize Window Button is Missing in OSX

A dialog created with:
class GUI(QtGui.QMainWindow):
def __init__(self):
super(GUI, self).__init__()
global dialog
dialog = QtGui.QDialog()
myGui = GUI()
is missing a minimize window button (OSX). It is there in Windows. Do I have to set some flag to display this missing controller? Please advise, Thanks in advance!
EDITED LATER:
I didn't try to solve a no-minimize-button issue with QtGui.QDialog(). But it appears I partically aware how to get that missing button using QtGui.QMainWindow.
Here is the simplest code illustrating a basic syntax:
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication(sys.argv)
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
myQWidget = QtGui.QWidget()
myBoxLayout = QtGui.QVBoxLayout()
myLineEdit = QtGui.QLineEdit("myLineEdit")
myBoxLayout.addWidget(myLineEdit)
myQWidget.setLayout(myBoxLayout)
self.setCentralWidget(myQWidget)
window = MainWindow()
window.show()
window.resize(480,320)
sys.exit(app.exec_())
A 'key' 'concept' behind QtGui.QMainWindow is that first we declare QWidget()
myQWidget = QtGui.QWidget()
to which we assign a 'main' layout:
myQWidget.setLayout(myBoxLayout)
Last step not to forget is to assign this QWidget() to dialog itself using:
self.setCentralWidget(myQWidget)
where 'self' is an instanced subclass of QtGui.QMainWindow.
I can't test this myself, but you could try setting these window flags:
dialog.setWindowFlags(dialog.windowFlags() |
QtCore.Qt.WindowMinimizeButtonHint |
QtCore.Qt.WindowSystemMenuHint)
(The WindowSystemMenuHint flag may not be necessary).
QtGui.QDialog does not offer a minimize button on any platform, but QtGui.QMainWindow does offer on each platform (Windows, Linux and OSX). You are creating a QDialog object and at the same time an object of GUI which is subclass of QMainWindow. If you write myGui.show() the window will offer you all three buttons (minimize, maximize/restore and close). But in case of dialog.show(), you will not have two of them (minimize and maximize/restore). It's Qt's limitation.

Categories