show text after enter key pressed - python

I want show text after enter key pressed
from PyQt5.QtWidgets import QWidget, QApplication, QPlainTextEdit, QVBoxLayout, QLabel
from PyQt5.QtCore import Qt
import sys
class PlainTextEdit(QPlainTextEdit):
def __init__(self, parent):
super().__init__(parent=parent)
close_window = ClosingWindow()
vbox = QVBoxLayout()
self.close_window.setLayout(vbox)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Enter:
self.close_window.label_display.setText("Enter key pressed")
class ClosingWindow(QWidget):
def __init__(self):
super().__init__()
plainText = PlainTextEdit(self)
self.initUI()
def initUI(self):
vbox = QVBoxLayout()
label_display = QLabel("Text Here")
self.setLayout(vbox)
self.setWindowTitle("Message Box")
self.setGeometry(200, 200, 500, 300)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
close_win = ClosingWindow()
sys.exit(app.exec_())

Your code has the following errors:
You are creating an infinite loop: You are creating a PlainTextEdit within a ClosingWindow, and in that PlainTextEdit you are creating another ClosingWindow, and in that other ClosingWindow you are creating a PlainTextEdit, etc. Every time you use the constructor of a class you are creating a different object, so the "close_window" created in PlainTextEdit is different from the "close_win".
Each class must have a single responsibility (1), in your case the responsibility of PlainTextEdit is to notify that it was pressed enter, and in that case you must use a signal.
The enter key on the keyboard does not correspond to Qt::Key_Enter but Qt::Key_Return, it only corresponds to Qt::Key_Return on the keypad.
It is not necessary to create a layout in PlainTextEdit.
Considering the above, the solution is:
from PyQt5 import QtCore, QtWidgets
class PlainTextEdit(QtWidgets.QPlainTextEdit):
sendTextSignal = QtCore.pyqtSignal(str)
def keyPressEvent(self, event):
if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
self.sendTextSignal.emit("Enter key pressed")
else:
self.sendTextSignal.emit("Not Enter key pressed")
super().keyPressEvent(event)
class ClosingWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
plainText = PlainTextEdit()
label_display = QtWidgets.QLabel("Text Here")
plainText.sendTextSignal.connect(label_display.setText)
vbox = QtWidgets.QVBoxLayout(self)
vbox.addWidget(plainText)
vbox.addWidget(label_display)
self.setWindowTitle("Message Box")
self.setGeometry(200, 200, 500, 300)
self.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
close_win = ClosingWindow()
sys.exit(app.exec_())
(1) Single responsibility principle

Related

How to show new QMainWindow in every loop in PyQT5?

I'm trying to write a Python program using PyQt5 that will display a window in each iteration of the for loop. I would like to close after incrementing and displaying the next window. However, I do not know how to stop the loop every iteration and at the moment I am getting 6 windows at once.
main.py
import sys
from PyQt5.QtWidgets import (QLineEdit, QVBoxLayout, QMainWindow,
QWidget, QDesktopWidget, QApplication, QPushButton, QLabel,
QComboBox, QFileDialog, QRadioButton)
from PyQt5.QtCore import pyqtSlot, QByteArray
from alert import Window2
from test import test
class SG(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(300, 150)
self.setWindowTitle('TEST')
self.resultsGen = QPushButton('TEST', self)
self.resultsGen.clicked.connect(lambda: self.on_click())
self.show()
#pyqtSlot()
def on_click(self):
test(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
sg = SG()
sys.exit(app.exec_())
alert.py
from PyQt5.QtWidgets import (QLineEdit, QVBoxLayout, QMainWindow,
QWidget, QDesktopWidget, QApplication, QPushButton, QLabel,
QComboBox, QFileDialog, QRadioButton)
from PyQt5.QtCore import pyqtSlot, QByteArray
from PyQt5.QtGui import QPixmap
from PyQt5 import QtGui, QtCore
class Window2(QMainWindow):
def __init__(self):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
self.setWindowTitle("Window22222")
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QVBoxLayout(self.central_widget)
label = QLabel(self)
pixmap = QPixmap('cropped/8.png')
label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
lay.addWidget(label)
self.textbox = QLineEdit(self)
self.textbox.move(20, 20)
self.textbox.resize(280, 40)
# Create a button in the window
self.button = QPushButton('Show text', self)
self.button.move(20, 80)
# connect button to function on_click
self.button.clicked.connect(lambda: self.on_clickX())
self.show()
#pyqtSlot()
def on_clickX(self):
textboxValue = self.textbox.text()
print(textboxValue)
self.textbox.setText("")
self.hide()
test.py
from alert import Window2
def test(self):
for x in range(6):
w = Window2()
As soon as you run the for cycle, all the code of the initialization will be executed, which includes the show() call you used at the end of initPopup().
A simple solution is to create a new signal that is emitted whenever you hide a window, and connect that signal to a function that creates a new one until it reaches the maximum number.
main.py:
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
from alert import Window2
class SG(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.alerts = []
def initUI(self):
self.resize(300, 150)
self.setWindowTitle('TEST')
self.resultsGen = QPushButton('TEST', self)
self.resultsGen.clicked.connect(self.nextAlert)
self.show()
def nextAlert(self):
if len(self.alerts) >= 6:
return
alert = Window2()
self.alerts.append(alert)
alert.setWindowTitle('Window {}'.format(len(self.alerts)))
alert.closed.connect(self.nextAlert)
alert.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
sg = SG()
sys.exit(app.exec_())
alert.py:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window2(QMainWindow):
closed = pyqtSignal()
def __init__(self):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QVBoxLayout(self.central_widget)
label = QLabel(self)
pixmap = QPixmap('cropped/8.png')
label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
lay.addWidget(label)
self.textbox = QLineEdit(self)
lay.addWidget(self.textbox)
# Create a button in the window
self.button = QPushButton('Show text', self)
lay.addWidget(self.button)
# connect button to function on_click
self.button.clicked.connect(lambda: self.on_clickX())
self.show()
#pyqtSlot()
def on_clickX(self):
textboxValue = self.textbox.text()
print(textboxValue)
self.textbox.setText("")
self.hide()
self.closed.emit()
Just note that with this very simplified example the user might click on the button of the "SG" widget even if an "alert" window is visibile. You might prefer to use a QDialog instead of a QMainWindow and make the main widget a parent of that dialog.
main.py:
class SG(QWidget):
# ...
def nextAlert(self):
if len(self.alerts) >= 6:
return
alert = Window2(self)
# ...
alert.py:
class Window2(QDialog):
closed = pyqtSignal()
def __init__(self, parent):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
# a QDialog doesn't need a central widget
lay = QVBoxLayout(self)
# ...
Also, if an alert window is closed using the "X" button the new one will not be shown automatically. To avoid that, you can implement the "closeEvent" and ignore the event, so that the user will not be able to close the window until the button is clicked. As QDialogs can close themself when pressing the escape key, I'm also ignoring that situation.
alert.py:
class Window2(QMainWindow):
# ...
def closeEvent(self, event):
event.ignore()
def keyPressEvent(self, event):
if event.key() != Qt.Key_Escape:
super().keyPressEvent(event)

How can I get more input text in PyQt5 InputDialog?

I want get more than one input text from user in PyQt5.QtWidgets QInputDialog ... in this code I can just get one input text box and I want get more input text box when I was clicked the button. See the picture to more information ...
from PyQt5.QtWidgets import (QApplication,QWidget,QPushButton,QLineEdit,QInputDialog,QHBoxLayout)
import sys
class FD(QWidget):
def __init__(self):
super().__init__()
self.mysf()
def mysf(self):
hbox = QHBoxLayout()
self.btn = QPushButton('ClickMe',self)
self.btn.clicked.connect(self.sd)
hbox.addWidget(self.btn)
hbox.addStretch(1)
self.le = QLineEdit(self)
hbox.addWidget(self.le)
self.setLayout(hbox)
self.setWindowTitle("InputDialog")
self.setGeometry(300,300,290,150)
self.show()
def sd(self):
text , ok = QInputDialog.getText(self,'InputDialog','EnterYourName = ')
if ok:
self.le.setText(str(text))
if __name__ == '__main__':
app = QApplication(sys.argv)
F = FD()
sys.exit(app.exec_())
QInputDialog is a convenience class to retrieve a single input from the user.
If you want more fields, use a QDialog.
For example:
class InputDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.first = QLineEdit(self)
self.second = QLineEdit(self)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self);
layout = QFormLayout(self)
layout.addRow("First text", self.first)
layout.addRow("Second text", self.second)
layout.addWidget(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def getInputs(self):
return (self.first.text(), self.second.text())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = InputDialog()
if dialog.exec():
print(dialog.getInputs())
exit(0)
Here's is a general solution, which accepts any number of inputs, based on Dimitry Ernot's answer.
from PyQt5.QtWidgets import QApplication, QLineEdit, QDialogButtonBox, QFormLayout, QDialog
from typing import List
class InputDialog(QDialog):
def __init__(self, labels:List[str], parent=None):
super().__init__(parent)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self)
layout = QFormLayout(self)
self.inputs = []
for lab in labels:
self.inputs.append(QLineEdit(self))
layout.addRow(lab, self.inputs[-1])
layout.addWidget(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def getInputs(self):
return tuple(input.text() for input in self.inputs)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = InputDialog(labels=["First","Second","Third","Fourth"])
if dialog.exec():
print(dialog.getInputs())
exit(0)

How to record a pressed key combination in the PyQT5 dialog window

I open the dialog from the main window, where by clamping the keys, I fill the line with their names. The problem is that I can not understand where you need to do a cycle of checking all the keys on their state. Maybe there is another way to get the keys pressed? Or where you need to listen to the clamping so that the dialog box does not hang and the string is updated.
MainWindow:
def showBindings(self, param):
from dialogs import KeyBindingsDialog
self.dialog = KeyBindingsDialog()
self.dialog.show()
Dialog:
class KeyBindingsDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(KeyBindingsDialog, self).__init__(parent)
self.ui = KeyBindings()
self.ui.setupUi(self)
Use QKeySequenceEdit:
from PyQt5 import QtCore, QtGui, QtWidgets
class KeySequenceEdit(QtWidgets.QKeySequenceEdit):
def keyPressEvent(self, event):
super(KeySequenceEdit, self).keyPressEvent(event)
seq_string = self.keySequence().toString(QtGui.QKeySequence.NativeText)
if seq_string:
last_seq = seq_string.split(",")[-1].strip()
le = self.findChild(QtWidgets.QLineEdit, "qt_keysequenceedit_lineedit")
self.setKeySequence(QtGui.QKeySequence(last_seq))
le.setText(last_seq)
self.editingFinished.emit()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._keysequenceedit = KeySequenceEdit(editingFinished=self.on_editingFinished)
button = QtWidgets.QPushButton("clear", clicked=self._keysequenceedit.clear)
hlay = QtWidgets.QHBoxLayout(self)
hlay.addWidget(self._keysequenceedit)
hlay.addWidget(button)
#QtCore.pyqtSlot()
def on_editingFinished(self):
sequence = self._keysequenceedit.keySequence()
seq_string = sequence.toString(QtGui.QKeySequence.NativeText)
print("sequence: ", seq_string)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())

PyQt Dual Purpose ENTER Key Press

I’m using PyQt5 and Python 3.6. I want to use the ENTER (or RETURN) key for dual purposes.
If the user enters text into the combo box and then hits the ENTER key, then I want the text from the combo box to be appended to a list. In all other situations, I want the ENTER key to serve as a shortcut for a push button.
I can’t find the correct decision for how the handle when ENTER is pressed. Here is a code sample. I’m looking to a decision in the returnDecision(self) function (toward the bottom of the script).
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QShortcut
from PyQt5.QtWidgets import QComboBox
from PyQt5.QtGui import QKeySequence
from PyQt5.QtCore import Qt, QSize
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
btn = QPushButton('Button', self)
btn.move(100, 50)
btn.clicked.connect(self.btnPrint)
self.comboBox = QComboBox(self)
self.comboBox.setEditable(True)
self.comboBox.move(100, 150)
self.comboBox.setMinimumSize(QSize(150, 0))
self.comboBox.setEditText("Initial Text")
self.comboBox.editTextChanged.connect(self.cboxPrint)
enter = QShortcut(QKeySequence(Qt.Key_Return), self)
enter.activated.connect(self.returnDecision)
self.textList = []
self.show()
def btnPrint(self):
print("Button was pressed")
def btnAction(self):
print("RETURN pressed when NOT editing combo box")
self.btnPrint()
def cboxPrint(self):
print(self.comboBox.currentText())
def cboxAction(self):
print("RETURN pressed when editing combo box")
self.textList.append(self.comboBox.currentText())
print(self.textList)
def returnDecision(self):
if ENTER KEY WAS PRESSED WHILE EDITING COMBO BOX:
self.cboxAction()
else:
self.btnAction()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Any suggestions?
One way to solve this is to use a custom subclass of the QComboBox and override the keyPressEvent method. Then also implement a keyPressEvent in your widget and handle each differently.
class CustomCombo(QtWidgets.QComboBox):
enter_pressed = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Return:
self.enter_pressed.emit()
else:
QtWidgets.QComboBox.keyPressEvent(self, event)
# if the key is not return, handle normally
class Example(QWidget):
def __init__(self):
# Code here
self.combo_box = CustomCombo(self)
self.combo_box.enter_pressed.connect(self.cboxAction)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Return:
self.btnAction()

How to detect dialog's close event?

Hi everyone.
I am making a GUI application using python3.4, PyQt5 in windows 7.
Application is very sample. User clicks a main window's button, information dialog pops up. And when a user clicks information dialog's close button (window's X button), system shows confirm message. This is all.
Here's my code.
# coding: utf-8
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel
class mainClass(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
openDlgBtn = QPushButton("openDlg", self)
openDlgBtn.clicked.connect(self.openChildDialog)
openDlgBtn.move(50, 50)
self.setGeometry(100, 100, 200, 200)
self.show()
def openChildDialog(self):
childDlg = QDialog(self)
childDlgLabel = QLabel("Child dialog", childDlg)
childDlg.resize(100, 100)
childDlg.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
mc = mainClass()
sys.exit(app.exec_())
Result screen shot is...
In this situation, I've added these code in mainClass class.
def closeEvent(self, event):
print("X is clicked")
This code works only when the main window is closed. But what I want is closeEvent function works when childDlg is to closed. Not main window.
What should I do?
You have added, the method closeEvent in the class mainClass.
So you have reimplemented the method closeEvent of your QMainwindow and not the method closeEvent of your childDlg. To do it, you have to subclass your chilDlg like this:
# coding: utf-8
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel
class ChildDlg(QDialog):
def closeEvent(self, event):
print("X is clicked")
class mainClass(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
openDlgBtn = QPushButton("openDlg", self)
openDlgBtn.clicked.connect(self.openChildDialog)
openDlgBtn.move(50, 50)
self.setGeometry(100, 100, 200, 200)
self.show()
def openChildDialog(self):
childDlg = ChildDlg(self)
childDlgLabel = QLabel("Child dialog", childDlg)
childDlg.resize(100, 100)
childDlg.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
mc = mainClass()
sys.exit(app.exec_())
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel
class mainClass(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
openDlgBtn = QPushButton("openDlg", self)
openDlgBtn.clicked.connect(self.openChildDialog)
openDlgBtn.move(50, 50)
self.setGeometry(100, 100, 200, 200)
self.show()
def openChildDialog(self):
childDlg = QDialog(self)
childDlgLabel = QLabel("Child dialog", childDlg)
childDlg.closeEvent = self.CloseEvent
childDlg.resize(100, 100)
childDlg.show()
def CloseEvent(self, event):
print("X is clicked")
if __name__ == "__main__":
app = QApplication(sys.argv)
mc = mainClass()
sys.exit(app.exec_())

Categories