Cannot open multiple frame in PyQt4 - python

I am trying to open a new window once a button is clicked using Python PyQt library. Currently, I can create two buttons in my frame but I cannot click the first button where it should open a new window and hide my first window. There I have created a back button for it to go back to my first window. Can anyone help to teach me how to create a new window and using button click to open a new window.
This is my Python code:
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(300, 300, 600, 400)
self.setWindowTitle("Testing Window")
# self.setWindowIcon(QtGui.QIcon(''))
self.home()
def home(self):
btn = QtGui.QPushButton("QR Code", self)
btn.clicked.connect(self.qr)
btn.resize(100, 100)
btn.move(100, 100)
btn1 = QtGui.QPushButton("Face Recognition", self)
btn1.clicked.connect(QtCore.QCoreApplication.instance().quit)
btn1.resize(200, 100)
btn1.move(300, 100)
self.show()
def qr(self):
backbtn = QtGui.QPushButton("Back" , self)
backbtn.clicked.connect(self.home)
backbtn.resize(100, 100)
backbtn.move(100, 100)
self.show()
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
# GUI1 = QRCode()
sys.exit(app.exec_())
run()

There's only one window in your code, the one you instantiate with GUI=Window().
Your function qr does not create a new window, it:
creates a third button on the same window
try to show the window, which has no effect since the window is already shown. The third button doesn't appear because it's created after the first call to self.show()
To open a new window on a button click, see this answer. You can use hide() for the first window.
On a side note, for a basic GUI you don't need QMainWindow, a simple QWidget will work fine. Also, you might want to look at layouts instead of absolute positioning.

Related

Switching Buttons in QMessageBox

I have this code:
def initUI(self):
mainLayout = QVBoxLayout()
# Temporary: Dialog Testing Button #
self.buttonTest = button('Dialog Testing')
self.buttonTest.clicked.connect(self.TestFile)
mainLayout.addWidget(self.buttonTest)
self.setLayout(mainLayout)
# Connects to dialogTesting Button
def dialogMessage(self, message):
dialog = QMessageBox(self)
dialog.setWindowTitle('Sample Text')
dialog.setText(message)
dialog.show()
# Connects with dialogMessage class.
def TestFile(self):
self.dialogMessage("When will non-OK buttons appear?")
return
I get results like this:
How can I change what buttons appear in the popup?
You can change the buttons by using an argument for the buttons parameter when you instantiate a QMessageBox. You use the Standard Button constants. Here is a silly example:
dialog = QMessageBox(self, buttons=QMessageBox.Ok+QMessageBox.Save+QMessageBox.Yes )
If you don't like the choices for standard buttons, you can make your own using addButton. This answer shows how to use addButton.

How to create an independent non-modal dialog

I'm trying to extend this solution Non modal dialog
from PyQt5 import QtWidgets
dialog = None
class Dialog(QtWidgets.QDialog):
def __init__(self, *args, **kwargs):
super(Dialog, self).__init__(*args, **kwargs)
self.setWindowTitle('A floating dialog')
self.resize(250,250)
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
button = QtWidgets.QPushButton('Open Dialog', self)
button.clicked.connect(self.handleOpenDialog)
self.resize(300, 200)
self._dialog = None
global dialog
dialog = Dialog(self)
dialog.show()
def handleOpenDialog(self):
if self._dialog is None:
self._dialog = QtWidgets.QDialog(self)
self._dialog.resize(200, 100)
self._dialog.exec_()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
Apology if title wasn't relevant. I want to have a dialog/window that is independent of all existing window/dialogs, and can be always interacted with, i.e. GUI loop of application window/any dialogs doesn't block this non-model dialog. For simplicity, I have used global variable dialog in above code snippet which will hold the non-modal dialog instance.
When above program is run, the main window appears along-with the non-modal dialog, and both dialogs are user interactive, but when the button is clicked, the GUI loop of self._dialog starts, and user can no longer interact with the floating dialog, and application window. What I want is to be able to interact with dialog but not with Window
I want behavior similar to the example below:
I opened help dialog from main window, then I opened a non-modal dialog which appears on top of the main window, and can not interact with the main window, but still doesn't block help dialog/window and allows user to interact with this non-modal window i.e. the help dialog in the example.
When a dialog is opened with exec(), it will default to being application-modal. This means it will block all other windows in the application, regardless of whether they're parented to other windows or not. To make a dialog modal for only one window, it must be parented to that window and also have its modality explicitly set to window-modal.
For a dialog to be fully non-modal with respect to all other windows (and any of their modal dialogs), it must have no parent and then be opened with show(). However, a side-effect of this is that it won't be automatically closed when the main-window is closed. To work around this, it can be explicitly closed in the closeEvent() of the main-window.
Here is a simple demo that implements all of the above:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Main Window')
self.setGeometry(400, 100, 300, 200)
self._help_dialog = None
self._other_dialog = None
self.buttonHelp = QtWidgets.QPushButton('Open Help')
self.buttonHelp.clicked.connect(self.handleOpenHelp)
self.buttonDialog = QtWidgets.QPushButton('Open Dialog')
self.buttonDialog.clicked.connect(self.handleOpenDialog)
layout = QtWidgets.QHBoxLayout(self)
layout.addWidget(self.buttonDialog)
layout.addWidget(self.buttonHelp)
self.handleOpenHelp()
def handleOpenDialog(self):
if self._other_dialog is None:
self._other_dialog = QtWidgets.QDialog(self)
self._other_dialog.setWindowModality(QtCore.Qt.WindowModal)
self._other_dialog.setWindowTitle('Other Dialog')
self._other_dialog.resize(200, 100)
self._other_dialog.exec_()
def handleOpenHelp(self):
if self._help_dialog is None:
self._help_dialog = QtWidgets.QDialog()
self._help_dialog.setWindowTitle('Help Dialog')
self._help_dialog.setGeometry(750, 100, 250, 250)
self._help_dialog.show()
def closeEvent(self, event):
if self._help_dialog is not None:
self._help_dialog.close()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())

How to make pop-up window with force attention in Tkinter

I want to create a window which doesn't allow the user to access other windows until you give an input.
I tried win.attribute("ontop", True) but it allows the user to access other windows.
or is there any function like a force_focus_lock() in Tkinter python 3.8 which doesn't allow other window to
get focus until you give a input or the close present window.
I believe the below is what you are trying to do. Explanation is given in comments.
method #1: (PopOut1)
you can still move the main window
the new window assumes focus if there is a mouse release on main window
method #2: (PopOut2)
the main window is locked in place
the new window will assume focus, blink and "ding" if there is a mouse release on main window
import tkinter as tk
#first method
class PopOut1(tk.Toplevel):
def __init__(self, master, **kwargs):
tk.Toplevel.__init__(self, master, **kwargs)
self.geometry('400x300')
#set focus to this window
self.focus_set()
#releasing on any other tkinter window, within this process, forces focus back to this window
self.grab_set()
#second method
class PopOut2(tk.Toplevel):
def __init__(self, master, **kwargs):
tk.Toplevel.__init__(self, master, **kwargs)
self.geometry('400x300')
#set focus to this window
self.focus_set()
#disable the main window
master.attributes('-disabled', True)
#so this window can't end up behind the disabled window
#only necessary if this window is not transient
#self.attributes('-topmost', True)
#capture close event
self.protocol("WM_DELETE_WINDOW", self.close)
#event=None ~ in case you also want to bind this to something
def close(self, event=None):
#re-enable the main window
self.master.attributes('-disabled', False)
#destroy this window
self.destroy()
class App(tk.Tk):
TITLE = 'Application'
WIDTH, HEIGHT, X, Y = 800, 600, 50, 50
def __init__(self):
tk.Tk.__init__(self)
tk.Button(self, text="open popout 1", command=self.open1).grid()
tk.Button(self, text="open popout 2", command=self.open2).grid()
def open1(self):
PopOut1(self)
def open2(self):
#.transient(self) ~
# flash PopOut if focus is attempted on main
# automatically drawn above parent
# will not appear in taskbar
PopOut2(self).transient(self)
if __name__ == '__main__':
app = App()
app.title(App.TITLE)
app.geometry(f'{App.WIDTH}x{App.HEIGHT}+{App.X}+{App.Y}')
#app.resizable(width=False, height=False)
app.mainloop()

PyQt5 how to make changes to second window when first window closes

I am relatively new to GUI design, what I want is very simple:
Suppose I have two windows , when first window closes, it will change the label text on second window.
any help will be appreciated! thanks
I just made it work myself, the basic idea is to pass one window object to the other window for modification.
For example, when window2 closes, I will make change to window1:
from PyQt5 import QtWidgets
import sys
class window_1(QtWidgets.QWidget):
#Initilization stuff
def __init__(self):
super(window_1,self).__init__()
self.setGeometry(50,50,500,500)
self.Label = QtWidgets.QLabel(self)
self.Label.setGeometry(100,100,200,10)
self.Label.setText('Second Window Not closed yet')
self.show()
class window_2(QtWidgets.QWidget):
#Pass win1 object during initialization
def __init__(self,win1_obj):
super(window_2,self).__init__()
self.setGeometry(600,50,500,500)
self.win1_obj = win1_obj
self.show()
#Define what happens when window2 closes
def closeEvent(self,event):
self.win1_obj.Label.setText('Second Window closed!')
app = QtWidgets.QApplication(sys.argv)
win1 = window_1() #window1 object
win2 = window_2(win1) #pass window1 object to window2 class
sys.exit(app.exec_())

Block QMainWindow while child widget is alive , pyqt

I want when the user press the button a form will appear after MainWindow is blocked pending form filling
You don't need to do anything that the other answers suggest. Using any exec() methods is a surefire way to have bugs, since suddenly your gui code can be reentered. Don't do it.
All you need to do is to set proper window modality before you show it (that's the important part). So:
widget.setWindowModality(Qt.ApplicationModal)
widget.show()
If you wish the window to block only some other window, not the entire application:
widget.setWindowFlags(widget.windowFlags() | Qt.Window)
widget.setParent(otherWindow)
widget.setWindowModality(Qt.WindowModal)
widget.show()
Note that this code is for PyQt4 only, it won't work with Qt 5 as there, the window functionality belongs in a class separate from QWidget.
You need to use a QDialog and show it using exec, which will block the rest of the application until it is closed. The return value of exec also tells you whether the form was closed without committing changes (i.e. cancelled).
Here is a simple demo script that shows how to use a QDialog:
from PyQt4 import QtCore, QtGui
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.checkbox1 = QtGui.QCheckBox('Option one', self)
self.checkbox2 = QtGui.QCheckBox('Option two', self)
self.buttonOk = QtGui.QPushButton('Ok', self)
self.buttonOk.clicked.connect(self.accept)
self.buttonCancel = QtGui.QPushButton('Cancel', self)
self.buttonCancel.clicked.connect(self.reject)
layout = QtGui.QGridLayout(self)
layout.addWidget(self.checkbox1, 0, 0, 1, 2)
layout.addWidget(self.checkbox2, 1, 0, 1, 2)
layout.addWidget(self.buttonOk, 2, 0)
layout.addWidget(self.buttonCancel, 2, 1)
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
widget = QtGui.QWidget(self)
layout = QtGui.QVBoxLayout(widget)
self.button = QtGui.QPushButton('Show Dialog', self)
self.button.clicked.connect(self.handleButton)
layout.addWidget(self.button)
self.setCentralWidget(widget)
def handleButton(self):
dialog = Dialog(self)
if dialog.exec_() == QtGui.QDialog.Accepted:
print('Option one: %s' % dialog.checkbox1.isChecked())
print('Option two: %s' % dialog.checkbox2.isChecked())
else:
print('Cancelled')
dialog.deleteLater()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 200, 100)
window.show()
sys.exit(app.exec_())
This is what you need
self.setWindowModality(QtCore.Qt.ApplicationModal)
Ok , so you want to block the parent window until the child window has been closed.
dialog = QInputDialog()
dialog.exec_()
Use the exec_() function , it will block until the child window is not closed
for further info :
launch a PyQT window from a main PyQt window, and get the user input?
Python - make a window appear on top of another, block access to other windows until button clicked
Subclass your QDialog or your QWidget with your form, and then connect it like this in the constructory of your main window. You will want to convert this code from c++ to python:
QObject::connect(myPushButton, SIGNAL(clicked), this, SLOT(on_myPushButton()));
//...
void MainWindow::on_myPushButton()
{
Dialog d;
int retVal = d.exec();// this is a blocking call
// Here the user has finished filling out the form.
// save any data that should be in the form, or respond to the retVal
}
EDIT: Added link to docs on using QDialog::exec()
http://qt-project.org/doc/qt-5/qdialog.html#exec
Hope that helps.
must create Widget inherits from Qdialog
AjoutArBase, AjoutArForm = uic.loadUiType('ajoutArticle.ui')
class AjoutArticle(AjoutArBase,QtGui.QDialog):

Categories

Resources