Python pyqt5 reset all widget inputs - python

I am using this method to have multiple windows GUI in a python script.
With a button press, I open one of the two forms, that have multiple textEdits and comboBoxes, used to fill a word teamplate easier.
Now, I want to reset all the inputs after I finished filling the form, and save the document.
What behaviour I want:
From main window, open one of the forms depending on 2 ComboBoxes index (type of document, and the client's gender).
After I fill the form and exit it, I go back to the main window, and when I open again a form, the text edits are empty and the combo boxes are on index 0.
But i can't make it to work, either the inputs are not resetted, either I kill the popup window and the main window.
I can't only kill the popup, I can only hide it and show it again.
# import some PyQt5 modules
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QWidget
from PyQt5.QtGui import QImage
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QTimer
from lib.eco_barbat_ui import *
from lib.eco_femeie_ui import *
from lib.eco_main_ui import *
class eco_abd_barbat(QWidget):
def __init__(self):
# call QWidget constructor
super().__init__()
# self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.ui = Ui_EcoAbdBarbat()
self.ui.setupUi(self)
def display(self):
self.show()
class eco_abd_femeie(QWidget):
def __init__(self):
# call QWidget constructor
super().__init__()
# self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.ui = Ui_EcoAbdFemeie()
self.ui.setupUi(self)
def display(self):
self.show()
class MainWindow(QWidget):
# class constructor
def __init__(self):
# call QWidget constructor
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.eco_abd_barbat = eco_abd_barbat()
self.eco_abd_femeie = eco_abd_femeie()
self.ui.pushButton.clicked.connect(self.open)
def open(self):
if self.ui.tip.currentIndex() == 0 and self.ui.sex.currentIndex()==0:
self.eco_abd_femeie.ui.qnume = self.ui.nume.toPlainText()
self.eco_abd_femeie.ui.qprenume = self.ui.prenume.toPlainText()
self.eco_abd_femeie.ui.qvarsta = self.ui.varsta.toPlainText()
self.eco_abd_femeie.ui.qdomiciliu = self.ui.domiciliu.toPlainText()
self.eco_abd_femeie.show()
elif self.ui.tip.currentIndex() == 0 and self.ui.sex.currentIndex()==1:
self.eco_abd_barbat.ui.qnume=self.ui.nume.toPlainText()
self.eco_abd_barbat.ui.qprenume = self.ui.prenume.toPlainText()
self.eco_abd_barbat.ui.qvarsta = self.ui.varsta.toPlainText()
self.eco_abd_barbat.ui.qdomiciliu = self.ui.domiciliu.toPlainText()
self.eco_abd_barbat.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
# create and show mainWindow
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())

This is the code that make it work for me, I cant explain 100% why it works, but i think before I reloaded the same variable over and over, as now I am forcing it to reload the ui from the file containing it every time the variable is accesed.
For some reason, without the self in front of variable (on self.formWindow, in open function), the second window would just close a split second after it opened.
This works for me, I mostly understand the reason why is performing like this, but if someone can make things clear about the self part, I'm happy to learn.
# import some PyQt5 modules
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QWidget
from PyQt5.QtGui import QImage
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QTimer
from lib.eco_barbat_ui import *
from lib.eco_femeie_ui import *
from lib.eco_main_ui import *
class eco_abd_barbat(QWidget):
def __init__(self):
# call QWidget constructor
super().__init__()
# self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.ui = Ui_EcoAbdBarbat()
self.ui.setupUi(self)
class eco_abd_femeie(QWidget):
def __init__(self):
# call QWidget constructor
super().__init__()
# self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.ui = Ui_EcoAbdFemeie()
self.ui.setupUi(self)
class MainWindow(QWidget):
# class constructor
def __init__(self):
# call QWidget constructor
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.open)
def select(self):
if self.ui.tip.currentIndex() == 0 and self.ui.sex.currentIndex() == 0:
return eco_abd_femeie()
else:
return eco_abd_barbat()
def open(self):
self.formWindow=self.select()
self.formWindow.ui.qnume = self.ui.nume.toPlainText()
self.formWindow.ui.qprenume = self.ui.prenume.toPlainText()
self.formWindow.ui.qvarsta = self.ui.varsta.toPlainText()
self.formWindow.ui.qdomiciliu = self.ui.domiciliu.toPlainText()
self.formWindow.show()

Related

QT Python: How to properly reimplement data method for QSqlTableModel for it to successfully update database?

I am using QSqlTableModel and QTableView to represent my database. In the last column, called "Validated" I have a value either 1 or 0 (this will be a checkbox, but for simplicity leaving it like this). If the value is 1, the whole row should turn green, otherwise left as normal colour.
The model works fine without reimplementing the data method. However, when implementing the data method as follows:
def data(self,index,role):
if (role == Qt.BackgroundRole) and (self.record(index.row()).value("VALIDATED") == 1):
return QColor(0,128,0)
return super().data(index, role)
The table is updated with the changes and the colouring works, but the database is now never updated with the changes. I have tried adding a datachanged signal as well, but no luck.
I have followed the format given by previous questions such as PyQt - trouble with reimplementing data method of QSqlTableModel. And no such luck.
Any help would be greatly appreciated.
See below for the whole simplified code:
import sys, logging, os
from PySide2.QtCore import Qt
from PySide2.QtSql import QSqlDatabase
from PySide2.QtWidgets import QApplication, QTabWidget, QVBoxLayout, QMainWindow, QAction, QPushButton, QWidget, QAbstractScrollArea, QTableView, QGridLayout
from PySide2.QtGui import QKeySequence, QColor
from PySide2.QtSql import QSqlTableModel
log = logging.getLogger("test-logger")
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
class SQLTableModel(QSqlTableModel):
def __init__(self, db_table):
QSqlTableModel.__init__(self)
self.setEditStrategy(QSqlTableModel.OnRowChange)
self.setTable(db_table)
self.select()
log.info(self.database())
def data(self,index,role):
if (role == Qt.BackgroundRole) and (self.record(index.row()).value("VALIDATED") == 1):
return QColor(0,128,0)
return super().data(index, role)
class TableWidget(QWidget):
def __init__(self, db_table, statusBar):
QWidget.__init__(self)
# Getting the Model
self.tabledb = db_table
self.model = SQLTableModel(db_table)
self.statusBar = statusBar
self.CreateUI()
def CreateUI(self):
# Creating a QTableView
self.table_view = QTableView()
self.table_view.setModel(self.model)
self.table_view.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.table_view.setColumnHidden(0, True)
self.main_layout = QGridLayout()
self.main_layout.addWidget(self.table_view)
self.setLayout(self.main_layout)
self.table_view.show()
class MainWindow(QMainWindow):
''' Sets up main window ui, with multiple tabed tables'''
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("test")
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("test")
self.db.open()
self.CreateUI()
self.show()
def CreateUI(self):
''' Create UI elements '''
##Setup database sheets
sheet_table = TableWidget("Product_Structure",self.statusBar)
self.setCentralWidget(sheet_table)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

I want to call a child window but carry on execution of the main code when it returns but my simple program does not continue

Here is my code. The two GUIs I created with Qt designer each has one push button. After starting the main code and pushing the button the call to sayHello runs and then the second window appears. I want to stop the sayHello code running until after I return from the child window. Pressing the button in the child window returns to main code but nothing else happens.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
from PyQt5 import uic
#load both ui files
uifile_1 = 'main.ui'
form_1, base_1 = uic.loadUiType(uifile_1)
uifile_2 = 'child.ui'
form_2, base_2 = uic.loadUiType(uifile_2)
class MainPage(base_1, form_1):
def __init__(self):
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
from PyQt5 import uic
#load both ui files
uifile_1 = 'main.ui'
form_1, base_1 = uic.loadUiType(uifile_1)
uifile_2 = 'child.ui'
form_2, base_2 = uic.loadUiType(uifile_2)
class MainPage(base_1, form_1):
def __init__(self):
super(base_1,self).__init__()
self.setupUi(self)
self.pushButtonCallChild.clicked.connect(self.change)
def change(self):
self.main = ChildPage()
self.main.show()
self.sayHello()
def sayHello(self):
print('Hello')
return
class ChildPage(base_2, form_2):
def __init__(self):
super(base_2, self).__init__()
self.setupUi(self)
self.pushButtonSelectSheetOK.clicked.connect(self.byebye)
def byebye(self):
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainPage()
ex.show()
sys.exit(app.exec_())

PyQt5 TypeError for openPersitentEditor

Hi everyone so I was doing some exam prep with PYQT5 and I created an application from an exercise in my workbook where we have to make it display a list of courses and when you click them it opens a message box with the course name also there is a button so that the user can add a course to the list. The add button is suppoused to open a QlineEdit on the last item in the listWidget, so the user can edit the field however I keep getting a TypeError message:
line 67, in onAddButton
self.mylistWidget.openPersistentEditor(self, modelItem)
TypeError: openPersistentEditor(self, QListWidgetItem): argument 1 has unexpected type 'UNISACourses'
import sys
from PyQt5.QtWidgets import (QListWidget, QLineEdit, QWidget, QMessageBox, QHBoxLayout, QAbstractItemView,
QApplication, QVBoxLayout, QPushButton, QButtonGroup)
from PyQt5.QtCore import pyqtSlot
from PyQt5 import Qt, QtGui
class MyListWidget(QListWidget, QLineEdit, QWidget):
"""
Subclassed QListWidget to allow for the closing of open editors and other modifications
"""
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Return:
print("Closing any persistent editor")
self.closePersistentEditor(self.model().index(self.count() - 1))
else:
super().keyPressEvent(event)
class UNISACourses(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# Main Window Settings
self.setGeometry(300, 300, 350, 250)
self.setWindowTitle('Courses')
# Layout
self.main_layout = QVBoxLayout(self)
self.setLayout(self.main_layout)
# Main Widget
self.mylistWidget = MyListWidget()
self.mylistWidget.addItems(["COS1511", "COS1521", "COS1512", "MNB1512", "INF1505", "FAC1502"])
self.main_layout.addWidget(self.mylistWidget)
# Define a layout for the other buttons to exist in for flexibility with resizing
self.btn_add = QPushButton("Add", clicked=self.onAddButton)
self.btn_delete = QPushButton("Delete", clicked=self.onDeleteButton)
hbox = QHBoxLayout()
hbox.addWidget(self.btn_add)
hbox.addWidget(self.btn_delete)
self.main_layout.addLayout(hbox)
# Define any additional behavior of the list
self.mylistWidget.itemDoubleClicked.connect(self.onClicked)
def onClicked(self, item):
QMessageBox.information(self, "Info", item.text())
#pyqtSlot()
def onAddButton(self):
"""
Opens a QLineEdit editor on the last item in the listwidget, allowing the user to edit the field.
NOTE: The user must click outside of the editor field then press Enter in order to close the editor
"""
self.mylistWidget.addItem('')
modelItem = self.mylistWidget.model().index(self.mylistWidget.count() - 1)
self.mylistWidget.openPersistentEditor(self, modelItem)
#pyqtSlot()
def onDeleteButton(self):
for item in self.mylistWidget.selectedItems():
self.mylistWidget.takeItem(self.mylistWidget.row(item))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = UNISACourses()
ex.show()
sys.exit(app.exec_())
You are passing two incorrect arguments (self and a QModelIndex) to QListWidget.openPersistentEditor which accepts one QListWidgetItem. Use the QListWidget.item method to get the item. You can also add QListWidget.setCurrentItem so it gets selected right away and ready to edit.
def onAddButton(self):
self.mylistWidget.addItem('')
modelItem = self.mylistWidget.item(self.mylistWidget.count() - 1)
self.mylistWidget.openPersistentEditor(modelItem)
self.mylistWidget.setCurrentItem(modelItem)
Same fix here:
def keyPressEvent(self, event):
if event.key() == Qt.Key_Return:
print("Closing any persistent editor")
self.closePersistentEditor(self.item(self.count() - 1))
else:
super().keyPressEvent(event)
Also the Qt Namespace class for Qt.Key_Return is inside the QtCore Module.
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5 import QtGui

Implement QThread with QProgressBar in PySide (or PyQt) during calculation

I would like to know how to implement QProgressBar, which shows the progress of calculation in main thread.
Please refer to below codes.
import sys
from PySide2.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QProgressBar
from PySide2.QtCore import QThread
class BarThread(QThread):
# Progress Bar UI Definition
def __init__(self):
QThread.__init__(self)
self.window = QWidget()
self.pgsb = QProgressBar()
self.lay = QVBoxLayout()
self.lay.addWidget(self.pgsb)
self.window.setLayout(self.lay)
self.isRun = False
# Thread Function Definition
def run(self):
self.window.show()
while self.isRun:
self.pgsb.setValue(self.percent)
print(self.percent)
if self.percent == 100:
self.isRun = False
class Tool(QWidget):
# Main UI Definition
def __init__(self):
windowWidth = 300
windowHeight = 300
QWidget.__init__(self)
self.setWindowTitle("Example")
self.resize(windowWidth, windowHeight)
self.bt = QPushButton('Numbering')
self.layout = QVBoxLayout()
self.layout.addWidget(self.bt)
self.setLayout(self.layout)
# Main Function Link Definition
self.bt.clicked.connect(self.numbering)
# Main Function Definition
def numbering(self):
bth = BarThread()
bth.start()
bth.isRun = True
for x in range(0,100000):
bth.percent = x/1000
print(x)
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = Tool()
widget.show()
sys.exit(app.exec_())
You can copy and paste directly onto your python IDE.
(it needs PySide2. It can be installed with 'pip install pyside2' in your prompt).
This code executes simple numbering, however, this doesn't show numbering progress.
How can I solve this problem? Thank you in advance.
P.S. I'm using Windows 10 with PyCharm.
You have at least the following errors:
You must not modify the GUI from another thread, in your case the run method is executed in another thread but you try to modify the value of the QProgressBar, in addition to displaying a widget which is not allowed. If you want to modify the GUI with the information provided in the execution in the secondary thread you must do it through signals since they are thread-safe
The for loop is the blocking task so it must be executed in another thread.
Considering the above, the solution is:
import sys
from PySide2.QtWidgets import (
QApplication,
QWidget,
QPushButton,
QVBoxLayout,
QProgressBar,
)
from PySide2.QtCore import QThread, Signal
class ProgressWidget(QWidget):
def __init__(self, parent=None):
super(ProgressWidget, self).__init__(parent)
self.pgsb = QProgressBar()
lay = QVBoxLayout(self)
lay.addWidget(self.pgsb)
class BarThread(QThread):
progressChanged = Signal(int)
def run(self):
percent = 0
for x in range(0, 100000):
percent = x / 100
self.progressChanged.emit(percent)
class Tool(QWidget):
"""Main UI Definition"""
def __init__(self, parent=None):
super(Tool, self).__init__(parent)
self.setWindowTitle("Example")
self.resize(300, 300)
self.bt = QPushButton("Numbering")
layout = QVBoxLayout(self)
layout.addWidget(self.bt)
# Main Function Link Definition
self.bt.clicked.connect(self.numbering)
self.bar_thread = BarThread(self)
self.progress_widget = ProgressWidget()
self.bar_thread.progressChanged.connect(self.progress_widget.pgsb.setValue)
# Main Function Definition
def numbering(self):
self.bar_thread.start()
self.progress_widget.show()
def closeEvent(self, event):
super(Tool, self).closeEvent(event)
self.bar_thread.quit()
self.bar_thread.wait()
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = Tool()
widget.show()
sys.exit(app.exec_())

PyQt5 behavior of setParent to display QWidget without layout

There has been a small problem with a little project of mine using PyQt5. I tried to add a random QWidget (in this example a QPushbutton) to a custom QWidget. However, I don't understand the behavior of the "setParent" function. When I use it outside of the custom QWidget, the QPushButton is displayed. When I use it in a declared function of the custom Widget, the QPushButton is occluded and I have no chance of displaying it outside of adding a layout (which I don't want). Here an example of the source code:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class customWidget(QWidget):
def __init__(self):
super().__init__()
self.addButton()
def addButton(self):
button = QPushButton('not_showing')
button.setParent(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
button = QPushButton('showing')
button.setParent(w)
button.move(50,50)
w.resize(600,600)
w.move(1000,300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
There is no change, when adding the parent during the initialization of the QPushButton.
When the function addButton exits, the button is removed.
If you want to see the button, try this:
class customWidget(QWidget):
def __init__(self):
super().__init__()
self.addButton()
self.button = None
def addButton(self):
if self.button is None:
self.button = QPushButton('not_showing')
self.button.setParent(self)
You do not have this problem in the main function because this function does not return until the application is stopped.
EDIT: The comment was right, but you also missed some arguments. This will work
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class customWidget(QWidget):
def __init__(self, parent=None):
super(customWidget, self).__init__(parent)
self.addButton()
def addButton(self):
button = QPushButton('not_showing')
button.setParent(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = customWidget()
button = QPushButton('showing')
button.setParent(w)
button.move(50,50)
w.resize(600,600)
w.move(1000,300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

Categories