Creating a userform with PyQt5 - python

There are lots of tutorials out there that show you how to create userforms in Python, but I can't find any which then show you how to retrieve whatever is entered into that form.
Here's an example I found where the userform looks perfect, but the buttons don't do anything:
from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout)
import sys
class Dialog(QDialog):
NumGridRows = 3
NumButtons = 4
def __init__(self):
super(Dialog, self).__init__()
self.createFormGroupBox()
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
buttonBox.accepted.connect(self.accept)
# buttonBox.accepted.connect(self.getInfo)
buttonBox.rejected.connect(self.reject)
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.formGroupBox)
mainLayout.addWidget(buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("Form Layout - pythonspot.com")
# def getInfo(self):
# shost = self.Name.text()
# print(shost)
def createFormGroupBox(self):
self.formGroupBox = QGroupBox("Form layout")
layout = QFormLayout()
layout.addRow(QLabel("Name"), QLineEdit())
layout.addRow(QLabel("Country"), QComboBox())
layout.addRow(QLabel("Age"), QSpinBox())
self.formGroupBox.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Dialog()
sys.exit(dialog.exec_())
The commented lines are lines that I added that don't work. Obviously self.Name.text() isn't the right syntax, but I can't figure out what is.

There are lot of things that you are missing in the code.
e.g buttonBox.accepted.connect(self.accept) accept button is connected to dummy accept. you need to connect this button to your self.getInfo,
To answer why you are failing to retrieve values: you do not have object handles from your QLineEdit, QComboBox, QSpinBox which means you cannot access them later to read the updated text.
Following is the fixed code which will connect accept to self.getInfo(self) and upon pressing OK it will print the values in Name, Country, Age fields .
from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout)
import sys
class Dialog(QDialog):
NumGridRows = 3
NumButtons = 4
def __init__(self):
super(Dialog, self).__init__()
self.formGroupBox = QGroupBox("Form layout")
self.ageSpinBar = QSpinBox()
self.countryComboBox = QComboBox()
self.countryComboBox.addItems(["Pakistan", "USA", "UAE"])
self.nameLineEdit = QLineEdit()
self.createFormGroupBox()
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self.getInfo)
# buttonBox.accepted.connect(self.getInfo)
self.buttonBox.rejected.connect(self.reject)
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.formGroupBox)
mainLayout.addWidget(self.buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("Form Layout - pythonspot.com")
def getInfo(self):
print("Person Name : {0}".format(self.nameLineEdit.text()))
print("Country : {0}".format(self.countryComboBox.currentText()))
print("Age : {0}".format(self.ageSpinBar.text()))
self.close()
def createFormGroupBox(self):
layout = QFormLayout()
layout.addRow(QLabel("Name"), self.nameLineEdit)
layout.addRow( QLabel("Country"),self.countryComboBox)
layout.addRow( QLabel("Age"), self.ageSpinBar)
self.formGroupBox.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Dialog()
sys.exit(dialog.exec_())
Note : self.close() will close the window if you don't want to close just comment this line out.
Hope this helps :)

Related

System tray application would detect hotkey with PyQt5 - QSystemTrayIcon

I want to create an application with a system tray icon. This app should detect the hotkey and react to it, even if the app is not focused (icon tray).
Example: I want to show the window, then I press Alt + X. The window is showing.
I tried using some global hotkey libraries but whenever the window is showing by hotkey, it freezes. The Show option in my QMenu still working.
I'm new to programming, thanks!
Here is my code:
from PyQt5.QtCore import QSize, Qt
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit, QVBoxLayout, QHBoxLayout, QWidget, QSystemTrayIcon, QMenu
from PyQt5.QtGui import QIcon, QKeySequence
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('GTyperP5')
self.setWindowIcon(QIcon('GTyperP5.ico'))
self.setFixedSize(QSize(192, 64))
self.setWindowFlag(Qt.WindowMinimizeButtonHint, False)
self.textInput = QLineEdit()
self.typeButton = QPushButton('Type')
self.typeButton.setFixedSize(QSize(50, 25))
self.typeButton.clicked.connect(self.cut_all)
self.textInput.returnPressed.connect(self.typeButton.click)
self.cancelButton = QPushButton('Cancel')
self.cancelButton.setFixedSize(QSize(50, 25))
self.cancelButton.clicked.connect(self.hide_window)
layout = QVBoxLayout()
layout.addWidget(self.textInput, alignment = Qt.AlignHCenter | Qt.AlignTop)
layout_ex = QHBoxLayout()
layout_ex.addWidget(self.cancelButton, alignment = Qt.AlignRight)
layout_ex.addWidget(self.typeButton, alignment = Qt.AlignLeft)
layout.addLayout(layout_ex)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
self.trayIcon = QSystemTrayIcon(QIcon('GTyperP5.ico'), parent = app)
self.trayIcon.setToolTip('GTyperP5')
menu = QMenu()
showAction = menu.addAction('Show')
showAction.triggered.connect(self.show_window)
exitAction = menu.addAction('Exit')
exitAction.triggered.connect(app.quit)
self.trayIcon.setContextMenu(menu)
self.trayIcon.show()
self.trayIcon.showMessage('GTyperP5 has started!', 'Thank you for using! :D', QIcon('GTyperP5.ico'), msecs = 10000)
self.trayIcon.activated.connect(self.doubleClick)
def closeEvent(self, event):
self.hide_window()
event.ignore()
def doubleClick(self, reason):
if reason == QSystemTrayIcon.DoubleClick:
self.show_window()
def cut_all(self):
clip = QApplication.clipboard()
clip.clear(mode = clip.Clipboard)
clip.setText(self.textInput.text(), mode = clip.Clipboard)
self.textInput.setText('')
self.hide_window()
def hide_window(self):
self.trayIcon.show()
self.hide()
def show_window(self):
self.trayIcon.hide()
self.show()
self.raise_()
self.textInput.setFocus()
app = QApplication([])
window = MainWindow()
window.show()
app.exec()

connect pushbuttons to lineedits

I have a problem with my python code, it's a QTablewidget with Qpushbuttons and Qline_edits inside each cell, We want a file path (after selecting this file from the file browser) to be written in the line edit when we click on its pushbutton and to store the output files so we can use them after.
from PyQt5.QtWidgets import (
QMainWindow,
QApplication,
QPushButton,
QFileDialog,
QGridLayout,
QLineEdit,
QTableWidget,
QHBoxLayout,
QWidget,
)
from PyQt5.QtCore import pyqtSlot
import sys
from functools import partial
global list_C
list_C=[]
class boxlayout(QWidget):
def __init__(self):
super(boxlayout,self).__init__()
layout=QHBoxLayout()
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
boxlayout.le=QLineEdit()
boxlayout.btn=QPushButton()
layout.addWidget(boxlayout.le)
layout.addWidget(boxlayout.btn)
self.setLayout(layout)
class Main(QMainWindow):
def __init__(self):
super().__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
mainlayout = QGridLayout(centralWidget)
self.table = QTableWidget(self)
self.table.resize(640, 480)
self.table.setColumnCount(3)
self.table.setRowCount(4)
mainlayout.addWidget(self.table)
save_button=QPushButton('OK')
mainlayout.addWidget(save_button)
save_button.clicked.connect(self.save_as_list)
for i in range(4):
for j in range(3):
self.table.setCellWidget(i,j, boxlayout())
boxlayout.btn.clicked.connect(partial(self.open_dialog, boxlayout.le))
#pyqtSlot(QLineEdit)
def open_dialog(self, le: QLineEdit):
file_name = QFileDialog.getOpenFileName(
self,
"Open File",
"${HOME}",
"All Files (*)",
)
le.setText(file_name[0])
def save_as_list(self):
for i in range(4):
for j in range(3):
item=self.table.cellWidget(i,j).le.text()
list_C.append(item)
print(list_C) #output=['last le value','last le value',...]
if __name__ == "__main__":
app = QApplication(sys.argv)
main_gui = Main()
main_gui.show()
sys.exit(app.exec())
Here is a minimal example:
from PyQt5.QtWidgets import (
QMainWindow,
QApplication,
QPushButton,
QFileDialog,
QFrame,
QGridLayout,
QLineEdit,
)
from PyQt5.QtCore import pyqtSlot
import sys
from functools import partial
class Main(QMainWindow):
def __init__(self):
super().__init__()
top_frame = QFrame(self)
self.setCentralWidget(top_frame)
self.grid = QGridLayout(top_frame)
for i in range(10):
btn = QPushButton(top_frame)
le = QLineEdit(top_frame)
btn.clicked.connect(partial(self.open_dialog, le))
btn.setText("open file system dialog")
self.grid.addWidget(btn, i, 0)
self.grid.addWidget(le, i, 1)
#pyqtSlot(QLineEdit)
def open_dialog(self, le: QLineEdit):
file_name = QFileDialog.getOpenFileName(
self,
"Open File",
"${HOME}",
"All Files (*)",
)
le.setText(file_name[0])
if __name__ == "__main__":
app = QApplication(sys.argv)
main_gui = Main()
main_gui.show()
sys.exit(app.exec())
The key thing here is to pass the QLineEdit to the file selector method.
Here we are doing it with: lambda: self.open_dialog(le)

PyQt5, I need not to print continuously but instead it only changes the QLabel

I need it to be not continuously printing but instead it only change the QLabel,
I dont need to add more, just whenever you write in Line edit it should replace the existing text. I need it like a stocks
This is the code:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QLabel, QLineEdit
from PyQt5.QtCore import pyqtSlot
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.hbox = QHBoxLayout()
self.game_name = QLabel("Stocks:", self)
self.game_line_edit = QLineEdit(self)
self.search_button = QPushButton("Print", self)
self.search_button.clicked.connect(self.on_click)
self.hbox.addWidget(self.game_name)
self.hbox.addWidget(self.game_line_edit)
self.hbox.addWidget(self.search_button)
self.setLayout(self.hbox)
self.show()
#pyqtSlot()
def on_click(self):
game = QLabel(self.game_line_edit.text(), self)
self.hbox.addWidget(game)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
You have to create a QLabel, set it in the layout and only update the text with setText():
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QLabel, QLineEdit
from PyQt5.QtCore import pyqtSlot
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.game_name = QLabel("Stocks:")
self.game_line_edit = QLineEdit()
self.search_button = QPushButton("Print")
self.search_button.clicked.connect(self.on_click)
self.game = QLabel()
hbox = QHBoxLayout(self)
hbox.addWidget(self.game_name)
hbox.addWidget(self.game_line_edit)
hbox.addWidget(self.search_button)
hbox.addWidget(self.game)
self.show()
#pyqtSlot()
def on_click(self):
self.game.setText(self.game_line_edit.text())
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())

Capturing Text with QLineEdit, QPushButton and displaying that text with QLabel pypt5

I'm trying to capture Text with a click on a QPushButton and Display it in a QLabel with pyqt5
I really new to this stuff so go easy on me !
here is the code I have so far:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QLabel, QLineEdit
from PyQt5.QtCore import pyqtSlot
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
hbox = QHBoxLayout()
game_name = QLabel("Game Name:", self)
game_line_edit = QLineEdit(self)
search_button = QPushButton("Search", self)
search_button.clicked.connect(self.on_click)
hbox.addWidget(game_name)
hbox.addWidget(game_line_edit)
hbox.addWidget(search_button)
self.setLayout(hbox)
self.show()
#pyqtSlot()
def on_click(self):
game = QLabel(game_line_edit.text(), self)
hbox.addWidget(game)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
I keep getting this error:
game = QLabel(game_line_edit.text(), self)
NameError: name 'game_line_edit' is not defined
I am not sure why game_line_edit is not defined but have a feeling it's because it not is the same "class" as my on_click class but am not sure
any help would be appreciated
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QLabel, QLineEdit
from PyQt5.QtCore import pyqtSlot
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.hbox = QHBoxLayout()
self.game_name = QLabel("Game Name:", self)
self.game_line_edit = QLineEdit(self)
self.search_button = QPushButton("Search", self)
self.search_button.clicked.connect(self.on_click)
self.hbox.addWidget(self.game_name)
self.hbox.addWidget(self.game_line_edit)
self.hbox.addWidget(self.search_button)
self.setLayout(self.hbox)
self.show()
#pyqtSlot()
def on_click(self):
game = QLabel(self.game_line_edit.text(), self)
self.hbox.addWidget(game)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())

PyQt5: Want to start a specific subprocess with a button click

One day old in terms of experience with PyQT, I followed sample code HERE to do this, but I am clueless as to how I could separate the start download part from the start GUI part, so that I can instead start that when I press the OK (startBtn)button. Also, know the command I do doesn't do anything but give you an error, but I know that works.
Any help appreciated!
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QAction, qApp, QDesktopWidget, QPushButton, QHBoxLayout, QVBoxLayout, QTextEdit
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QThread, QProcess
import sys
class GUI(QProcess):
def __init__(self):
super().__init__()
# Create an instance variable here (of type QTextEdit)
startBtn = QPushButton('OK')
stopBtn = QPushButton('Cancel')
#startBtn.clicked.connect()
stopBtn.clicked.connect(qApp.exit)
self.hbox = QHBoxLayout()
self.hbox.addStretch(1)
self.hbox.addWidget(startBtn)
self.hbox.addWidget(stopBtn)
self.edit = QTextEdit()
self.edit.setWindowTitle("QTextEdit Standard Output Redirection")
self.vbox = QVBoxLayout()
self.vbox.addStretch(1)
self.vbox.addWidget(self.edit)
self.vbox.addLayout(self.hbox)
#setLayout(self.vbox)
self.central=QWidget()
#self.vbox.addWidget(self.edit)
self.central.setLayout(self.vbox)
self.central.show()
def readStdOutput(self):
self.edit.append(str(self.readAllStandardOutput()))
def main():
app = QApplication(sys.argv)
qProcess = GUI()
qProcess.setProcessChannelMode(QProcess.MergedChannels);
qProcess.start("youtube-dl")
qProcess.readyReadStandardOutput.connect(qProcess.readStdOutput);
return app.exec_()
if __name__ == '__main__':
main()
2 notes:
If you also know how to disable the OK button when you press it, until the process is finished, then I'd love to know.
Not all imports are used, but I can clean that later. PyCharm show which is used and not. Cleanup is for later.
To do what you ask you have to have some considerations:
youtube-dl requires parameters, like the url, for this I have placed a QLineEdit.
To know when the process starts and ends, we use the signal: stateChanged(newState)
Complete code:
import sys
from PyQt5.QtCore import QProcess
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QTextEdit, QLabel, QLineEdit
class GUI(QProcess):
def __init__(self, parent=None):
super(GUI, self).__init__(parent=parent)
# Create an instance variable here (of type QTextEdit)
self.startBtn = QPushButton('OK')
self.stopBtn = QPushButton('Cancel')
self.hbox = QHBoxLayout()
self.hbox.addStretch(1)
self.hbox.addWidget(self.startBtn)
self.hbox.addWidget(self.stopBtn)
self.label = QLabel("Url: ")
self.lineEdit = QLineEdit()
self.lineEdit.textChanged.connect(self.EnableStart)
self.hbox2 = QHBoxLayout()
self.hbox2.addWidget(self.label)
self.hbox2.addWidget(self.lineEdit)
self.edit = QTextEdit()
self.edit.setWindowTitle("QTextEdit Standard Output Redirection")
self.vbox = QVBoxLayout()
self.vbox.addStretch(1)
self.vbox.addLayout(self.hbox2)
self.vbox.addWidget(self.edit)
self.vbox.addLayout(self.hbox)
self.central = QWidget()
self.central.setLayout(self.vbox)
self.central.show()
self.startBtn.clicked.connect(self.startDownload)
self.stopBtn.clicked.connect(self.kill)
self.stateChanged.connect(self.slotChanged)
self.EnableStart()
def slotChanged(self, newState):
if newState == QProcess.NotRunning:
self.startBtn.setDisabled(False)
elif newState == QProcess.Running:
self.startBtn.setDisabled(True)
def startDownload(self):
self.start("youtube-dl", [self.lineEdit.text()])
def readStdOutput(self):
self.edit.append(str(self.readAllStandardOutput()))
def EnableStart(self):
self.startBtn.setDisabled(self.lineEdit.text() == "")
def main():
app = QApplication(sys.argv)
qProcess = GUI()
qProcess.setProcessChannelMode(QProcess.MergedChannels)
qProcess.readyReadStandardOutput.connect(qProcess.readStdOutput)
return app.exec_()
if __name__ == '__main__':
main()
Screenshot:

Categories