How to re-display a QDialog after hiding it? - python

I am working with python and pyqt. I have a dialog that I want to temporarily hide. After calling
dlg.hide()
I try calling
dlg.show()
but nothing happens. It is never re-displayed.
I am new to pyqt so any help is greatly appreciated.
Thanks in advance.

You are looking for the exec_ method that makes the dialog modal, see how this works:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtCore, QtGui
class myDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(myDialog, self).__init__(parent)
self.dialog = None
self.buttonShow = QtGui.QPushButton(self)
self.buttonShow.setText("Show Dialog")
self.buttonShow.clicked.connect(self.on_buttonShow_clicked)
self.buttonHide = QtGui.QPushButton(self)
self.buttonHide.setText("Close")
self.buttonHide.clicked.connect(self.on_buttonHide_clicked)
self.layout = QtGui.QVBoxLayout(self)
self.layout.addWidget(self.buttonShow)
self.layout.addWidget(self.buttonHide)
#QtCore.pyqtSlot()
def on_buttonHide_clicked(self):
self.accept()
#QtCore.pyqtSlot()
def on_buttonShow_clicked(self):
self.dialog = myDialog(self)
self.dialog.exec_()
class myWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(myWindow, self).__init__(parent)
self.buttonShow = QtGui.QPushButton(self)
self.buttonShow.setText("Show Dialog")
self.buttonShow.clicked.connect(self.on_buttonShow_clicked)
self.layout = QtGui.QVBoxLayout(self)
self.layout.addWidget(self.buttonShow)
self.dialog = myDialog(self)
#QtCore.pyqtSlot()
def on_buttonHide_clicked(self):
self.dialog.accept()
#QtCore.pyqtSlot()
def on_buttonShow_clicked(self):
self.dialog.exec_()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('myWindow')
main = myWindow()
main.show()
sys.exit(app.exec_())

Related

How to show another window

The project occurs loging in and signing in.
Im trying a transition from registerwindow to mainwindow and when we submit the window is automatically transit to mainwindow. There is only way to do this (at least for me) i have to import two python doc which named mainwindow.py and register.py, they are in same doc by the way.
This is the mainmenu.py
from PyQt5 import QtCore,QtGui,QtWidgets
from window.register import Ui_Form
class Ui_MainWindow(object):
def login(self):
self.window = QtWidgets.QWidget()
self.ui = Ui_Form()
self.ui.setupUi(self.window)
self.window.show()
MainWindow.hide()
and this is register.py
from PyQt5 import QtCore, QtGui, QtWidgets
from window.mainmenu import Ui_MainWindow
import sqlite3
class Ui_Form(object):
def submit(self):
sorgu2 = "Select * From users where nickname = ?"
sorgu = "INSERT INTO users values(?,?)"
self.cursor.execute(sorgu,(self.lineEdit.text(),self.lineEdit.text()))
self.connect.commit()
Form.hide()
self.window2 = QtWidgets.QMainWindow()
self.ui2 = Ui_MainWindow()
self.ui2.setupUi(self.window2)
self.window2.show()
Its supposed to be when i clicked to the button the register window will be hidden and mainmenu window will be show. Same thing for the mainmenu but the direct opposite
I know i am doing circular dependent imports but there is no other way but importing them to each other
If second window will be QDialog then you can hide main window, use exec() for QDialog and main window will wait till you close QDialog, and when it returns to main window then you can show it again.
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton("Show Second Window", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.hide() # hide main window
self.second = SecondWindow()
self.second.exec() # will wait till you close second window
self.show() # show main window again
class SecondWindow(QtWidgets.QDialog): # it has to be dialog
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton("Close It", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.close() # go back to main window
app = QtWidgets.QApplication([])
main = MainWindow()
app.exec()
The other popular method is to create two widgets with all contents and replace widgets in one window.
from PyQt5 import QtWidgets
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.button = QtWidgets.QPushButton("Show Second Window", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.close()
self.parent.set_content("Second")
class SecondWidget(QtWidgets.QWidget):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.button = QtWidgets.QPushButton("Close It", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.close()
self.parent.set_content("Main")
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.layout = QtWidgets.QVBoxLayout(self)
self.set_content("Main")
self.show()
def set_content(self, new_content):
if new_content == "Main":
self.content = MainWidget(self)
self.layout.addWidget(self.content)
elif new_content == "Second":
self.content = SecondWidget(self)
self.layout.addWidget(self.content)
app = QtWidgets.QApplication([])
main = MainWindow()
app.exec()
EDIT: Change window's content using QStackedLayout
from PyQt5 import QtWidgets
class FirstWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Show Second Stack", self)
self.button.clicked.connect(self.change_stack)
layout.addWidget(self.button)
def change_stack(self):
self.parent().stack.setCurrentIndex(1)
class SecondWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Show First Stack", self)
self.button.clicked.connect(self.change_stack)
layout.addWidget(self.button)
def change_stack(self):
self.parent().stack.setCurrentIndex(0)
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.stack = QtWidgets.QStackedLayout(self)
self.stack1 = FirstWidget(self)
self.stack2 = SecondWidget(self)
self.stack.addWidget(self.stack1)
self.stack.addWidget(self.stack2)
self.show()
app = QtWidgets.QApplication([])
main = MainWindow()
app.exec()

PyQt5 passing argument between two classes: lambda vs partial

I am trying to pass an argument between two PyQt5 classes. I used three methods:
Using lambda functions.
Wrapper function (similar to lambda function).
partial from functools module.
In the example below, I have two windows:
MainWindow has QLineEdit mw_line_edit and a QPushButton mw_open_new_dialog_button.
Dialog: has a QLineEdit line_edit and aQPushButton push_button.
When I click the button push_button, I want it to insert the content of line_edit to mw_line_edit.
Here is a minimal example:
import sys
from functools import partial
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtWidgets.QWidget(self)
self.setCentralWidget(self.central_widget)
self.mw_open_new_dialog_button = QtWidgets.QPushButton('Open New dialog', self)
self.mw_line_edit = QtWidgets.QLineEdit(self)
self.hlayout = QtWidgets.QHBoxLayout(self)
self.hlayout.addWidget(self.mw_open_new_dialog_button)
self.hlayout.addWidget(self.mw_line_edit)
self.central_widget.setLayout(self.hlayout)
self.mw_open_new_dialog_button.clicked.connect(self.open_new_dialog)
def open_new_dialog(self):
self.dlg = Dialog()
#self.dlg.clicked.connect(partial(self.write_something, self.dlg.line_edit.text())) # <<<<<<< This does not work
self.dlg.clicked.connect(lambda: self.write_something(self.dlg.line_edit.text())) # this works
#self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit.text()))# <<<<<<<<<<This does not work
self.dlg.exec()
#QtCore.pyqtSlot()
def write_something(self, text):
self.mw_line_edit.setText(text)
def wrapper(self, text):
return lambda: self.write_something(text)
class Dialog(QtWidgets.QDialog):
clicked = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(QtWidgets.QDialog, self).__init__(parent)
self.hlayout = QtWidgets.QHBoxLayout(self)
self.line_edit = QtWidgets.QLineEdit(self)
self.push_button = QtWidgets.QPushButton('Click me', self)
self.hlayout.addWidget(self.line_edit)
self.hlayout.addWidget(self.push_button)
self.label = QtWidgets.QLabel('I am a Qlabel', self)
self.hlayout.addWidget(self.label)
self.setLayout(self.hlayout)
self.push_button.clicked.connect(self.clicked)
def write_something(self, text):
print(text)
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec())
As you can see in the commented lines, only the following method works:
self.dlg.clicked.connect(lambda: self.write_something(self.dlg.line_edit.text()))
Why the other two do not work, i.e:
self.dlg.clicked.connect(partial(self.write_something, self.dlg.line_edit.text())) # <<<<<<< This does not work
self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit.text()))# <<<<<<<<<<This does not work
Thanks
1) functools.partial()
What arguments are you passing to partial? You are passing the method write_something and the text of self.dlg.line_edit at the time the connection is made.
And what is the value of that text? it is an empty string, this explains the failure.
Is there any solution for this case? Yes, instead of passing the text, pass the QLineEdit, and in the method write_something get the text and set it in the other QLineEdit:
def open_new_dialog(self):
self.dlg = Dialog()
self.dlg.clicked.connect(partial(self.write_something, self.dlg.line_edit))
self.dlg.exec()
def write_something(self, le):
self.mw_line_edit.setText(le.text())
2) wrapper
It is the same problem, you are passing the empty text that you have at the moment of the connection
Is there any solution? Yes, the same solution as the previous one.
def open_new_dialog(self):
self.dlg = Dialog()
self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit))
self.dlg.exec()
def write_something(self, text):
self.mw_line_edit.setText(text)
def wrapper(self, line):
return lambda: self.write_something(line.text())
Will there be a clean solution? Yes, create a signal that transports the text when you click.
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
self.mw_open_new_dialog_button = QtWidgets.QPushButton('Open New dialog')
self.mw_line_edit = QtWidgets.QLineEdit()
hlayout = QtWidgets.QHBoxLayout(central_widget)
hlayout.addWidget(self.mw_open_new_dialog_button)
hlayout.addWidget(self.mw_line_edit)
self.mw_open_new_dialog_button.clicked.connect(self.open_new_dialog)
#QtCore.pyqtSlot()
def open_new_dialog(self):
self.dlg = Dialog()
self.dlg.textSignal.connect(self.mw_line_edit.setText)
self.dlg.exec()
class Dialog(QtWidgets.QDialog):
textSignal = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(QtWidgets.QDialog, self).__init__(parent)
hlayout = QtWidgets.QHBoxLayout(self)
self.line_edit = QtWidgets.QLineEdit()
self.push_button = QtWidgets.QPushButton('Click me')
hlayout.addWidget(self.line_edit)
hlayout.addWidget(self.push_button)
self.label = QtWidgets.QLabel('I am a Qlabel')
hlayout.addWidget(self.label)
self.push_button.clicked.connect(self.sendText)
#QtCore.pyqtSlot()
def sendText(self):
self.textSignal.emit(self.line_edit.text())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec())

PyQt using classes to show button

Getting very stuck here, I am trying to learn how to use classes, and so simply want to show a button on a window when the button is in a different class. Here is the code I am trying to use:
#!/usr/bin/python3
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(0, 0, 800, 600)
main_menu = Menu()
self.show()
class Menu(QtGui.QWidget):
def __init__(self):
btn = QtGui.QPushButton("Quit")
btn.resize(btn.sizeHint())
btn.move(100,100)
btn.show()
print("Hello I am a menu")
def main():
app = QtGui.QApplication(sys.argv)
main_window = Window()
sys.exit(app.exec())
if __name__ == "__main__":
main()
This works so far as I get a window, but no button on it, howerver the print message I put in works. What am I doing wrong please?
You must initialize the parent class in Menu, in addition to passing the parent to that class and the button.
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(0, 0, 800, 600)
main_menu = Menu(self)
self.show()
class Menu(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
btn = QtGui.QPushButton("Quit", self)
btn.resize(btn.sizeHint())
btn.move(100,100)
print("Hello I am a menu")
def main():
app = QtGui.QApplication(sys.argv)
main_window = Window()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

How do i open a class from within another class by selecting an item on ToolBar?? Python/PyQt

I am trying to run class AddTQuestions from a def in class AddTest but it wont work!! It opens the window AddTQuestions for a split-second then closes it straight away?!
The code is shown here:
import sys
from PyQt4 import QtCore, QtGui
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
RunClassAction = QtGui.QAction(QtGui.QIcon('exit24.png'), 'Exit', self)
RunClassAction.triggered.connect(self.run)
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(RunClassAction)
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Why Wont this Woooorkkkkk')
self.show()
def run(self):
AddQuestion = AddTQuestions()
AddQuestion.show()
class AddTQuestions(QtGui.QMainWindow):
def __init__(self, parent=None):
super(AddTQuestions, self).__init__(parent)
self.welldone = QtGui.QLabel('WellDone')
self.button = QtGui.QPushButton('Press Me')
layout = QtGui.QVBoxLayout()
layout.addWidget(self.welldone)
layout.addWidget(self.button)
self.setLayout(layout)
print("hello")
if __name__ == '__main__':
app = QtGui.QApplication([])
window = Example()
window.show()
app.exec_()
The object get's garbage collected, since you don't hold any reference to it when the function ends.
add them as class variables like this and the window stays open.
self.AddQuestion = AddTQuestions()
self.AddQuestion.show()

How can I get the previous activated widget in PyQt?

I have a button and two tablewidgets.Pressing the button does two different things depending on which one of the tablewidgets was activated before the push of the button.How can I get the right widget?
You could for example use the focusInEvent to store the activated widget and return it when pressing the button, something like this:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyTableWidget(QtGui.QTableWidget):
focusIn = QtCore.pyqtSignal(QtCore.QObject)
def __init__(self, parent=None):
super(MyTableWidget, self).__init__(parent)
def focusInEvent(self, event):
self.focusIn.emit(self)
return super(MyTableWidget, self).focusInEvent(event)
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.lastFocusedTableWidget = None
self.tableWidgetFirst = MyTableWidget(self)
self.tableWidgetFirst.setObjectName("tableWidgetFirst")
self.tableWidgetFirst.focusIn.connect(self.on_tableWidget_focusIn)
self.tableWidgetSecond = MyTableWidget(self)
self.tableWidgetSecond.setObjectName("tableWidgetSecond")
self.tableWidgetSecond.focusIn.connect(self.on_tableWidget_focusIn)
self.pushButtonLastFocused = QtGui.QPushButton(self)
self.pushButtonLastFocused.setText("Print the last focused QTableWidget!")
self.pushButtonLastFocused.clicked.connect(self.on_pushButtonLastFocused_clicked)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.tableWidgetFirst)
self.layoutVertical.addWidget(self.tableWidgetSecond)
self.layoutVertical.addWidget(self.pushButtonLastFocused)
#QtCore.pyqtSlot(QtCore.QObject)
def on_tableWidget_focusIn(self, obj):
self.lastFocusedTableWidget = obj
#QtCore.pyqtSlot()
def on_pushButtonLastFocused_clicked(self):
print self.lastFocusedTableWidget.objectName()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.resize(333, 111)
main.show()
sys.exit(app.exec_())

Categories