I am writing a program where I have do the following.
Get User Credentials using a Dialog Box
If successful Launch another application, if Unsuccessful prompt again for credentials.
I am implementing this using two classes called x_LoginForm and x_Application
The code is as follows
class x_LoginForm(QDialog)
Elements in Class
QLineEdit to get Username
QLineEdit to get Password
QPushbutton to Cancel
QPushbutton to Login
If Login is successful, I will set a flag main_window_flag to 1
class x_Application()
This class will Launch a new application and provide control to the user.
The object of this class will be instantiated if the flag main_window_flag is set to 1
main_window_flag=0
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
form = x_LoginForm()
form.show()
if main_window_flag == 1:
window = x_Application()
window.show()
sys.exit(app.exec_())
in the class x_LoginForm
when I have validated I want to pass the control back to main, and instantiate an object of the x_Application class.
to exit from the class x_LoginForm, If I issue self.close - the entire program gets closed.
What is happening is that form.show() returns immediately and your program does the if check then which is likely evaluating to False since you have main_window_flag=0 if you change form.show() to form.exec_() it will wait until the form closes and then proceed with the code. Read here for more about modal dialogs.
Related
I'm working on a basic project with using PyQt5. I made a break method so I can close app with pressing a button. I made a loop in this but when I close the window loop doesn't go back. I want to able to close the window without quitting the program fully.
There is 'main' side:
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = TextBar()
mainWin.show()
sys.exit(app.exec_())
And there is button and its command:
pybutton = QPushButton('OK', self)
pybutton.clicked.connect(self.clickMethod)
pybutton.resize(200, 32)
pybutton.move(80, 100)
def clickMethod(self):
print('Name: ' + self.tool.text(), '\nProperties:' + self.prop.text(), '\n')
TextBar.close(self)
I want to close ONLY window when I press OK, NOT full of program.
when the Mainwindow is closed nothing should be running, unless you consider hidding it, like
YourQMainWindow.hide()
self.YourQMainWindow.hide()
2-Methode initialize 2 difference instances, like that once one is closed, another remains or, at about to close, your run a second instance
if __name__ == "__main__":
app = Qtw.QApplication(sys.argv)
main_window = MainWindow() #---->first instance
main_window1 = MainWindow() #---->second instance
sys.exit(app.exec())
if you run then both, they take more ressouces,
so i suggest you create a button to close the first one, that alse start at the same time the second instance of your app,....
Unless you provide more reproductible example (a piece of code), this is how i can only go in advicing you,...(please confirm if it's working for you, me i always use this technic, & it's working),...thank you
I have a simple login application which prompts user for username and password.
there are 2 buttons, one for logging in and other for cancel.
in the slot for the cancel button, I have the following code
self.cancelbutton.clicked.connect(self.closeIt)
def closeIt(self):
self.close()
however when I hit the Esc Key, or click the 'X' in the QDialog, the application window disappears, but I do not get the command prompt back.
following is the code for the main function
app = QApplication(sys.argv)
form = x_LoginForm()
form.exec_()
form.close()
sys.exit(app.exec_())
I am not able to work out what I am doing wrong.
You're calling sys.exit(). That will immediately exit out of python. Also, it doesn't really make much sense to call form.exec_() and then call app.exec_()
You should only need the app.exec_()
app = QApplication(sys.argv)
form = x_LoginForm()
form.show()
sys.exit(app.exec_())
I was wondering how to connect two widgets together. I have two widgets i created on QtDesigner, one being a Login page, and another being a Main Menu. I want to connect them so that when the Login is successful, the user will be redirected to the Main Window, and the Login widget will close automatically. Does anyone know how to do this?
PS. I have the code for the main menu and login in separate .py files
You could do the following:
In your QApp create first a dialogue containing the login widget and execute the dialogue. Depending on the result, either (if login failed) quit the application (or reprompt the user for login), or (if login succeeded) instantiate the main window and show it.
Or:
Instantiate and show the main window. Immediately show an application-modal dialogue with the login widget. Depending on the result, either resume operation or quit the application.
Here a snippet from some code, that prompts the user for login and checks it against a DB. The login dialogue is defined as DlgLogin in another file.
#many imports
from theFileContainingTheLoginDialogue import DlgLogin
class MainWindow (QtGui.QMainWindow):
def __init__ (self, parent = None):
super (MainWindow, self).__init__ ()
self.ui = Ui_MainWindow ()
self.ui.setupUi (self)
dlg = DlgLogin (self)
if (dlg.exec_ () == DlgLogin.Accepted):
#check here whether you accept or reject the credentials
self.database = Database (*dlg.values)
if not self.database.check (): sys.exit (0)
else:
sys.exit (0)
self.mode = None
The dialogue class is the following (having two line-edit-widgets for the credentials):
from PyQt4 import QtGui
from dlgLoginUi import Ui_dlgLogin
class DlgLogin (QtGui.QDialog):
def __init__ (self, parent = None):
super (DlgLogin, self).__init__ ()
self.ui = Ui_dlgLogin ()
self.ui.setupUi (self)
#property
def values (self):
return [self.ui.edtUser.text (), self.ui.edtPassword.text () ]
The application itself reads:
#! /usr/bin/python3.3
import sys
from PyQt4 import QtGui
from mainWindow import MainWindow
def main():
app = QtGui.QApplication (sys.argv)
m = MainWindow ()
m.show ()
sys.exit (app.exec_ () )
if __name__ == '__main__':
main ()
I am trying to intercept paste() for a specific edit box. After much reading and head scratching I decided to try the big hammer and monkey patch. This didn't work for me either. Anyone know why?
import sys
from PyQt4 import QtGui
def myPaste():
print("paste") # Never gets here
if __name__ == "__main__":
# QtGui.QLineEdit.paste = myPaste # Try #1
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
window.setWindowTitle("monkey")
centralWidget = QtGui.QWidget(window)
edit = QtGui.QLineEdit(centralWidget)
# QtGui.QLineEdit.paste = myPaste # Try #2
edit.paste = myPaste # Try #3
window.setCentralWidget(centralWidget)
window.show()
app.exec_()
Based on feedback..i was able to use the event filter suggestion to solve my problem. Updated example code follows...
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
window.setWindowTitle("monkey")
centralWidget = QtGui.QWidget(window)
edit = QtGui.QLineEdit(centralWidget)
window.setCentralWidget(centralWidget)
def eventFilter(obj, e):
if isinstance(obj, QtGui.QLineEdit):
if (e.type() == QtCore.QEvent.KeyPress):
if (e.matches(QtGui.QKeySequence.Paste)):
obj.paste()
t=str(obj.text()).title() # Special handling here...uppercase each word for example
obj.setText(t)
return True
return False
else:
return QtGui.QMainWindow.eventFilter(obj, e)
window.eventFilter = eventFilter
edit.installEventFilter(window)
window.show()
app.exec_()
The reason you can't "monkey-patch" QLineEdit.paste() is because it's not a virtual function. The important thing about virtual functions is that when they are overridden, the reimplemented function will get called internally by Qt; whereas non-virtual overrides will only get called by Python code. So, since QLinedit.paste() isn't virtual, you will instead have to intercept all the events that would normally result in it being called internally by Qt.
That will mean reimplementing QLineEdit.keyPressEvent, so that you can trap the shortcuts for the default key bindings; and also QLineEdit.contextMenuEvent, so that you can modify the default context menu. And, depending on what you're trying to do, you might also need to override the default drag-and-drop handling. (If you prefer not to use a subclass, an event-filter can be used to monitor all the relevant events).
The QClipboard class provides access to the system clipboard, which will allow you to intercept the text before it is pasted. Every application has a single clipboard object, which can be accessed via QApplication.clipboard() or qApp.clipboard().
In order to do what you want you can subclass QLineEdit and create a method that provides the custom paste functionality that you want (paste method isn't virtual so if it is overriden it won't be called from Qt code). In addition you will need an event filter to intercept the shortcut for CTRL+V. Probably you will have to filter the middle mouse button too which is also used to paste the clipboard content. From the event filter you can call your replacement of paste method.
You can use the following code as starting point:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class myEditor(QLineEdit):
def __init__(self, parent=None):
super(myEditor, self).__init__(parent)
def myPaste(self):
self.insert("custom text pasted! ")
class myWindow(QMainWindow):
def __init__(self, parent=None):
super(myWindow, self).__init__(parent)
self.customEditor = myEditor(self)
self.setCentralWidget(self.customEditor)
self.customEditor.installEventFilter(self)
def eventFilter(self, obj, e):
if (obj == self.customEditor):
if (e.type() == QEvent.KeyPress):
if (e.matches(QKeySequence.Paste)):
self.customEditor.myPaste()
return True
return False
else:
return QMainWindow.eventFilter(obj, e)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = myWindow()
window.show()
app.exec_()
The event filter here only takes care of the keyboard shortcut for pasting. As I said you need to consider also other sources of the paste operation.
I am working with python plugins for QGIS.I have my main form as DlgQueryBuilder.py and another form as DlgDberror.py,which displays the error in the query.My DlgDberror.py
contains following:
class DlgDbError(QtGui.QWidget, Ui_DlgDbError):
def __init__(self,e,parent):
QtGui.QWidget.__init__(self)
Ui_DlgDbError.__init__(self)
self.setupUi(self)
msg = "<pre>" + e.msg.replace('<','<') + "</pre>"
self.txtMessage.setHtml(msg)
#staticmethod
def showError(e, parent):
dlg = DlgDbError(e,parent)
dlg.show()
The call to this from DlgQueryBuilder.py is "DlgDbError.showError(e, self)"
Everything goes smooth but when i try to run my main form DlgQueryBuilder.py,*DlgDberror.py* form is not shown.It dissapears within a second.
dlg.show() should work rite??
When showError exits, dlg is garbage collected and goes away which also destroys the underlying Qt objects and the dialog. I suspect you need to pass your dialog back to QGIS in some way so it can handle whatever is necessary with the dialog. So yes, show() works, but your program is destroying the dialog before it can do anything useful.
Perhaps you wanted exec_() instead? It will pop up the dialog and then block waiting for the user to close the dialog. This is known as a modal dialog. See http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qdialog.html