I want the data to be updated after clicking the button update, but it dont work. please tell me how to implement this. I try to close the window, call the function LOADDATA and open it again, but nothing happens. The data remains, but in database information deleting
import sys, os
from PyQt5.uic import loadUi
from PyQt5 import QtWidgets, QtCore
import mariadb
try:
connection = mariadb.connect(
user="root",
password="******",
host="localhost",
port=3306,
database="vista")
except:
print("...")
cursor = connection.cursor()
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("workplace.ui",self)
self.tableWidget.setColumnWidth(0, 35)
self.tableWidget.setColumnWidth(1, 75)
self.tableWidget.setColumnWidth(2, 75)
self.tableWidget.setColumnWidth(3, 70)
self.tableWidget.setHorizontalHeaderLabels(["ID", "NAME", "PHONE", "DATE"])
self.loaddata()
self.pushButton.clicked.connect(self.delete)
self.pushButton_2.clicked.connect(self.update)
self.pushButton_3.clicked.connect(self.exit)
def loaddata(self):
tablerow = 0
cursor.execute(f"SELECT * FROM vista.workplace ORDER BY 'id'")
value = cursor.fetchall()
self.tableWidget.setRowCount(40)
for row in value:
self.tableWidget.setItem(tablerow, 0, QtWidgets.QTableWidgetItem(row[0]))
self.tableWidget.setItem(tablerow, 1, QtWidgets.QTableWidgetItem(row[1]))
self.tableWidget.setItem(tablerow, 2, QtWidgets.QTableWidgetItem(row[2]))
self.tableWidget.setItem(tablerow, 3, QtWidgets.QTableWidgetItem(row[3]))
tablerow += 1
QtCore.QTimer.singleShot(1000, self.loaddata)
def delete(self):
idplace = self.lineEdit.text()
cursor.execute(f"DELETE from vista.workplace WHERE id = '{idplace}'")
connection.commit()
print("Deleting!")
def update(self):
self.close()
self.loaddata()
self.show()
print("Update!")
def exit(self):
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Related
I had set a fixed size on my Login window however once you login in and it takes you to the LoadingBar window the size restrictions stay even though I set a new fixed size. This leaves my window with blank area. I have tried looking for similar posts but have not found any. This may have a very simple fix and I may have made a very stupid mistake. I would appreciate any help and an explantion. There is no error when running the code
#IMPORTS
import sys, os, sqlite3
import random, datetime
from PyQt5 import QtCore, QtGui, uic
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import QtWidgets #, QtWebEngineWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox
import sqlite3
import time
#WINDOWS
window1 = uic.loadUiType("login.ui")[0]
window2 = uic.loadUiType("SIGNUP.ui")[0]
window3 = uic.loadUiType("main.ui")[0]
window4 = uic.loadUiType("login_loadingbar.ui")[0]
#CLASSES AND MODULES
class Login(QtWidgets.QMainWindow, window1):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
#Set title
self.setWindowTitle('Login Window')
self.setFixedWidth(480)
self.setFixedHeight(620)
self.loginButton.clicked.connect(self.loginfunction)
self.password_field.setEchoMode(QtWidgets.QLineEdit.Password)
self.signupHereButton.clicked.connect(self.gotocreate)
def loginfunction(self):
username = self.username_field.text() #ctansley0#imdb.com
password = self.password_field.text() #ptWYccjTQSKX
if len(username) == 0 or len(password) == 0:
self.login_text.setText("Please input all fields")
else:
conn = sqlite3.connect("customersSQL.db")
cur = conn.cursor()
query = 'SELECT password FROM customer_data WHERE email = \''+username+"\'"
cur.execute(query)
result_pass = cur.fetchone()[0]
if result_pass == password:
self.login_text.setText("Successfully logged in")
gotoload = LoadingBar()
widget.addWidget(gotoload)
widget.setCurrentIndex(widget.currentIndex()+1)
gotoload.progress()
else:
self.login_text.setText("Incorrect username or password")
def gotocreate(self):
createacc=CreateAcc()
widget.addWidget(createacc)
widget.setCurrentIndex(widget.currentIndex()+1)
class CreateAcc(QtWidgets.QMainWindow, window2):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
#title
self.setWindowTitle('Signup Window')
#Push button
self.signupButton.clicked.connect(self.createaccfunction)
self.passwordSignup_field.setEchoMode(QtWidgets.QLineEdit.Password)
self.confirmPass_field.setEchoMode(QtWidgets.QLineEdit.Password)
def createaccfunction(self):
'This is the create account function where it takes the users input and addes it into the database'
email = self.usernameSignUp_field.text()
password = self.confirmPass_field.text()
if self.passwordSignup_field.text()==self.confirmPass_field.text():
password=self.passwordSignup_field.text()
self.signup_text.setText("Successfully created account")
conn = sqlite3.connect("customersSQL.db")
cur = conn.cursor()
#query1 = """INSERT INTO customer_data (email,password)
# VALUES(?,?)""", (email,password)
print (email,password)
cur.execute("""INSERT INTO customer_data (email,password)
VALUES(?,?)""", (email,password))
conn.commit()
time.sleep(3)
login=Login()
widget.addWidget(login)
widget.setCurrentIndex(widget.currentIndex()+1)
class LoadingBar(QtWidgets.QMainWindow, window4):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
#title
self.setWindowTitle('Loading')
self.setWindowFlag(Qt.FramelessWindowHint)
self.setFixedHeight(693)
self.setFixedWidth(351)
#makes progress bar go from 0-100, time scaled
def progress(self):
for i in range(100):
time.sleep(0.1)
self.login_progressBar.setValue(i)
QtWidgets.QApplication.processEvents()
class MainWindow(QtWidgets.QMainWindow, window3):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
app=QApplication(sys.argv)
w1=Login()
widget=QtWidgets.QStackedWidget()
widget.addWidget(w1)
widget.show()
app.exec_()
I have 1 combobox editable username and 1 line edit password i want load user list from database sqlite3 to combobox. After load list i want action on itemlist combobox get password current selected user from database.
pyqt5 application
table columns
table records
######Combo Box 2 - PM's
self.groupBox_2 = QtWidgets.QGroupBox(self.tab)
self.groupBox_2.setGeometry(QtCore.QRect(10, 140, 191, 51))
self.groupBox_2.setObjectName("groupBox_2")
self.comboBox_3 = QtWidgets.QComboBox(self.groupBox_2)
self.comboBox_3.setGeometry(QtCore.QRect(10, 20, 171, 22))
self.comboBox_3.setObjectName("comboBox_3")
self.comboBox_3.addItems(self.pm_Combo)
def pm_Combo(self):
conn = sqlite3.connect('testdb.db')
c = conn.cursor()
c.execute("SELECT DISTINCT projectmanager FROM testtable2")
pmList = c.fetchall()
conn.commit()
conn.close()
Assuming that the table is called "user" then you can use the userData to save the information and set it in the QLineEdit when the currentIndex of the QComboBox changes:
import os
import sqlite3
import sys
from PyQt5 import QtWidgets, QtSql
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.username_combo = QtWidgets.QComboBox()
self.password_lineedit = QtWidgets.QLineEdit()
button_login = QtWidgets.QPushButton(self.tr("Login"))
lay = QtWidgets.QFormLayout(self)
lay.addRow(self.tr("Username:"), self.username_combo)
lay.addRow(self.tr("Password:"), self.password_lineedit)
lay.addRow(button_login)
self.username_combo.currentIndexChanged.connect(self.update_password)
self.load_usernames()
def load_usernames(self):
current_dir = os.path.dirname(os.path.realpath(__file__))
db_path = os.path.join(current_dir, "testdb.db")
self.username_combo.clear()
with sqlite3.connect(db_path) as conn:
cursor = conn.execute("SELECT DISTINCT username, password FROM User")
for result in cursor.fetchall():
username, password = result
self.username_combo.addItem(username, password)
def update_password(self):
self.password_lineedit.setText(self.username_combo.currentData())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Another possible solution is to use QSqlQueryModel with QDataWidgetMapper:
import os
import sys
from PyQt5 import QtWidgets, QtSql
def create_connection():
current_dir = os.path.dirname(os.path.realpath(__file__))
db_path = os.path.join(current_dir, "testdb.db")
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(db_path)
if not db.open():
print("error: {}".format(db.lastError().text()))
return False
return True
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.username_combo = QtWidgets.QComboBox()
self.password_lineedit = QtWidgets.QLineEdit()
button_login = QtWidgets.QPushButton(self.tr("Login"))
lay = QtWidgets.QFormLayout(self)
lay.addRow(self.tr("Username:"), self.username_combo)
lay.addRow(self.tr("Password:"), self.password_lineedit)
lay.addRow(button_login)
self.load_data()
def load_data(self):
self.model = QtSql.QSqlQueryModel()
self.model.setQuery("""SELECT DISTINCT username, password FROM User""")
self.mapper = QtWidgets.QDataWidgetMapper()
self.mapper.setModel(self.model)
self.mapper.addMapping(self.password_lineedit, 1)
self.username_combo.currentIndexChanged.connect(self.mapper.setCurrentIndex)
self.username_combo.setModel(self.model)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
if not create_connection():
sys.exit(-1)
w = Widget()
w.show()
sys.exit(app.exec_())
I need to make simple GUI which can connect with sql.
How can I pass variables from one window -> second?
My problem is:
I have window with login panel (QLogin.py), which is testing connection with sql server. If it can cannect - good, log in. If not, return error. It works
In my main window (QApp.py) i need to do sql queries and return result in my qtablewidget (etc.)
I wanted pass variables:login = self.username.text() & pwd = self.password.text() from QLogin to QApp to make new connection to do queries, but it doesnt work.
Maybe someone sees better option how to solve it?
To sum up: After entering IMEI in QApp.py i would like to do sql query by using credentials & connection engine from QLogin.py.
Enter sql login & password in QLogin.py
Enter IMEI and press button -> run sql query
QLogin.py
# -- coding: utf-8 --
from PyQt5.QtWidgets import QLineEdit,QDialogButtonBox,QFormLayout,QDialog,QMessageBox
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
import qdarkstyle
import sqlalchemy
class LoginDialog(QDialog):
def __init__(self, parent=None):
super(LoginDialog,self).__init__(parent)
self.init_ui()
def init_ui(self):
### delete question mark
self.setWindowFlags(self.windowFlags()
^ Qt.WindowContextHelpButtonHint)
### login & password fields
self.username = QLineEdit(self)
self.password = QLineEdit(self)
self.password.setEchoMode(QLineEdit.Password)
loginLayout = QFormLayout()
loginLayout.addRow("Username", self.username)
loginLayout.addRow("Password", self.password)
self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttons.accepted.connect(self.control)
self.buttons.rejected.connect(self.reject)
layout = QtWidgets.QVBoxLayout(self)
layout.addLayout(loginLayout)
layout.addWidget(self.buttons)
self.setLayout(layout)
### set window title & stylesheet
self.setWindowTitle('Login Box')
self.setWindowIcon(QtGui.QIcon('dc1.png'))
self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
###lock resize
self.setSizeGripEnabled(False)
self.setFixedSize(self.sizeHint())
###log by usins sql credentials
def control(self):
ser = ########
base = #########
login = self.username.text()
pwd = self.password.text()
timeout = 5
self.engine = sqlalchemy.create_engine(
"mssql+pyodbc://{username}:{pwd}#10.96.5.17\dqinstance/{dbname}?driver=SQL+Server+Native+Client+11.0".format(
dbname=base, username=login, pwd=pwd), connect_args={'timeout': timeout})
try:
connection = self.engine.connect()
connection.close()
self.accept()
except:
QMessageBox.warning(self, 'Error', "Wrong username or password! \n\n"
"Please use the SQL Server credentials ")
It looks like:
QApp.py
# -- coding: utf-8 --
from PyQt5 import QtCore, QtGui, QtWidgets
from QLogin import LoginDialog
import qdarkstyle
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow,self).__init__(parent)
self.main_frame()
self.center() #center frame
self.layout_init() #widgets layout
def main_frame(self):
### actions on meenubar
exitAct = QtWidgets.QAction('&Exit', self)
exitAct.setShortcut('Ctrl+Q')
exitAct.setStatusTip('Exit application')
exitAct.triggered.connect(self.close)
self.statusBar()
### menubar
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAct)
fileMenu = menubar.addMenu('&Help')
### basic geometry and color
self.setWindowTitle('Test Window')
self.setWindowIcon(QtGui.QIcon('dc1.png'))
self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
def layout_init(self):
grid = QtWidgets.QGridLayout()
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
### widgets
self.tablewidget = QtWidgets.QTableWidget() #frame
self.textbox = QtWidgets.QLineEdit()
self.textbox.setPlaceholderText('IMEI')
self.textbox.setEnabled(True)
self.textbox.setValidator(QtGui.QDoubleValidator())
self.pb = QtWidgets.QPushButton(self.tr("Run process"))
self.pb.setDisabled(True)
self.textbox.textChanged.connect(self.disableButton)
self.pb.clicked.connect(self.on_clicked)
### make vidgets alive
self.centralWidget().setLayout(grid)
grid.addWidget(self.textbox)
grid.addWidget(self.tablewidget)
grid.addWidget(self.pb)
### center main window
def center(self):
qr = self.frameGeometry()
cp = QtWidgets.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def disableButton(self):
if len(self.textbox.text())> 0:
self.pb.setDisabled(False)
else:
self.pb.setDisabled(True)
### run process button
def on_clicked(self):
if len(self.textbox.text())== 0:
pass
else:
print('test')
def sql_query(self):
self.sql = "SELECT " \
"FI.FileNameTransformed, " \
"FI.OrderItemCode, " \
"FIR.Imported," \
"FR.Row " \
"FROM[PROD_WAREX2].[dbo].[FileRows] FR " \
"JOIN[PROD_WAREX2].[dbo].[FileImportRows]FIR ON FR.RowId = FIR.RowId" \
"JOIN[PROD_WAREX2].[dbo].[FileImports] FI ON FIR.FileImportId = FI.Id" \
"WHERE FR.Row LIKE : e1"
self.e1 = '%'&self.textbox.text()&'%'
QMain.py
import sys
from PyQt5.QtWidgets import QApplication
from QLogin import LoginDialog
from QApp import MainWindow
if __name__ == '__main__':
app = QApplication(sys.argv)
login = LoginDialog()
if not login.exec_():
sys.exit(-1)
window = MainWindow()
window.show()
sys.exit(app.exec_())
The solution is simple, get credentials from login object and then pass it to window object:
class LoginDialog(QDialog):
# ...
def credentials():
return self.username.text(), self.password.text()
# ...
class MainWindow(QtWidgets.QMainWindow):
# ...
def setCredentials(self, credentials):
self._credentials = credentials
# ...
def sql_query(self):
base = #########
username, pwd = self._credentials
self.engine = sqlalchemy.create_engine(
"mssql+pyodbc://{username}:{pwd}#10.96.5.17\dqinstance/{dbname}?driver=SQL+Server+Native+Client+11.0".format(
dbname=base, username=username, pwd=pwd), connect_args={'timeout': timeout})
try:
connection = self.engine.connect()
# ...
except:
QMessageBox.warning(self, 'Error', "Wrong username or password! \n\n"
"Please use the SQL Server credentials ")
if __name__ == '__main__':
app = QApplication(sys.argv)
login = LoginDialog()
if login.exec_() != QtWidgets.QDialog.Accepted:
sys.exit(-1)
window = MainWindow()
window.setCredentials(login.credentials()) # <----
window.show()
sys.exit(app.exec_())
I have sql query. My push button connects with sql - it takes long time. During it, my GUI is not responding - is it possible to make it responds?
QtCore.QCoreApplication.processEvents() doesnt work.
QApp.py
# -- coding: utf-8 --
from PyQt5 import QtGui, QtWidgets, QtCore
import qdarkstyle
import pyodbc
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow,self).__init__(parent)
self.main_frame()
self.center() #center frame
self.layout_init() #widgets layout
def main_frame(self):
### actions on meenubar
exitAct = QtWidgets.QAction('&Exit', self)
exitAct.setShortcut('Ctrl+Q')
exitAct.setStatusTip('Exit application')
exitAct.triggered.connect(self.close)
self.statusBar()
moreinfo = QtWidgets.QAction('&Help',self)
moreinfo.setStatusTip('More information')
moreinfo.triggered.connect(self.information)
self.statusBar()
### menubar
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAct)
fileMenu = menubar.addMenu('&Help')
fileMenu.addAction(moreinfo)
### basic geometry and color
self.setWindowTitle('Villain')
self.setWindowIcon(QtGui.QIcon('dc1.png'))
self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
def layout_init(self):
self.grid = QtWidgets.QGridLayout()
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
### widgets
self.tablewidget = QtWidgets.QTableWidget()
self.tablewidget.setColumnCount(4)
self.tablewidget.setHorizontalHeaderLabels(["FileNameTransformed", "OrderItemCode", "Imported", "Row"])
self.tablewidget.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.tablewidget.horizontalHeader().setStretchLastSection(True)
self.tablewidget.resizeColumnsToContents()
self.tablewidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.tablewidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
#self.tablewidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.textbox = QtWidgets.QLineEdit()
self.textbox.setPlaceholderText('IMEI')
self.textbox.setEnabled(True)
regexp = QtCore.QRegExp('^(0\d+|[1-9][0-9]+)$') #IMEI = only int
self.textbox.setValidator(QtGui.QRegExpValidator(regexp))
self.pb = QtWidgets.QPushButton(self.tr("Run process"))
self.pb.setDisabled(True)
self.textbox.textChanged.connect(self.disableButton)
self.pb.clicked.connect(self.on_clicked_pb)
self.clearbutton = QtWidgets.QPushButton(self.tr("Clear all"))
self.clearbutton.setDisabled(True)
self.clearbutton.clicked.connect(self.on_clicked_clear)
### make vidgets alive
self.centralWidget().setLayout(self.grid)
self.grid.addWidget(self.textbox)
self.grid.addWidget(self.tablewidget)
self.grid.addWidget(self.pb)
self.grid.addWidget(self.clearbutton)
### center main window
def center(self):
qr = self.frameGeometry()
cp = QtWidgets.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def information(self):
QtWidgets.QMessageBox.information(self,'Information','Version: 1.19.11.18\n'\
'This is the prototype of the application\n\n'\
'Please, contact karol.chojnowski#digitalcaregroup.com for comments and suggestions\n\n'\
'Digital Care - Data Processing Team')
def disableButton(self):
if len(self.textbox.text())> 0:
self.pb.setDisabled(False)
self.clearbutton.setDisabled(False)
else:
self.pb.setDisabled(True)
self.clearbutton.setDisabled(True)
### run process button
#QtCore.pyqtSlot()
def on_clicked_pb(self):
if len(self.textbox.text()) == 0:
pass
else:
self.sql_query()
### clear all
#QtCore.pyqtSlot()
def on_clicked_clear(self):
if len(self.textbox.text())> 0:
self.textbox.clear()
self.tablewidget.setRowCount(0)
self.tablewidget.setColumnWidth(3, 200)
def setCredentials(self, credentials):
self._credentials = credentials
def sql_query(self):
ser = "10.96.6.14"
base = "PROD_WAREX2"
username, pwd = self._credentials
QtCore.QCoreApplication.processEvents()
try:
self.connection = pyodbc.connect(driver='{SQL Server}', server=ser, database=base,
user=username, password=pwd)
cursor = self.connection.cursor()
self.res = cursor.execute(""" SELECT FI.FileNameTransformed,
FI.OrderItemCode,
FIR.Imported,
FR.Row
FROM [FileRows] AS FR
JOIN [FileImportRows] AS FIR ON FR.RowId = FIR.RowId
JOIN [FileImports] AS FI ON FIR.FileImportId = FI.Id
WHERE FR.Row LIKE ? """, ('%' + self.textbox.text() + '%'))
if not cursor.rowcount:
QtWidgets.QMessageBox.information(self, 'IMEI', "No items found")
cursor.close()
pass
else:
self.tablewidget.setRowCount(0)
for row, form in enumerate(self.res):
self.tablewidget.insertRow(row)
for column, item in enumerate(form):
newitem = QtWidgets.QTableWidgetItem(str(item))
self.tablewidget.setItem(row, column, newitem)
cursor.close()
self.table_performance()
self.tablewidget.sortItems(0, order=QtCore.Qt.DescendingOrder)
except:
QtWidgets.QMessageBox.warning(self, 'Error', "Something went wrong\n\n"\
"Contact karol.chojnowski#digitalcaregroup.com")
QtWidgets.QMessageBox.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
def table_performance(self):
self.tablewidget.resizeColumnsToContents()
self.tablewidget.setColumnWidth(3, 2500)
self.tablewidget.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
main .py:
Villain.py
# -- coding: utf-8 --
import sys
from PyQt5 import QtWidgets,QtGui
from QLogin import LoginDialog
from QApp import MainWindow
import os
def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
login = LoginDialog()
login.setWindowIcon(QtGui.QIcon(resource_path('dc1.png')))
if login.exec_() != QtWidgets.QDialog.Accepted:
sys.exit(-1)
window = MainWindow()
window.setWindowIcon(QtGui.QIcon(resource_path('dc1.png')))
window.setGeometry(500, 150, 800, 500)
window.setCredentials(login.credentials()) # <----
window.show()
sys.exit(app.exec_())
The use of processEvents() implies in most cases a bad design. If you have a heavy task, do not execute it in the main thread, execute it in another thread and send the necessary data to the main thread by means of signals or with QMetaObject::invokeMethod() (this last option will be used since it is not necessary so much connection).
On the other hand you should only add the stylesheet once, if there are new widgets they will take as a basis the stylesheet.
# -- coding: utf-8 --
import threading
from PyQt5 import QtGui, QtWidgets, QtCore
import qdarkstyle
import pyodbc
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow,self).__init__(parent)
self.main_frame()
self.center() #center frame
self.layout_init() #widgets layout
def main_frame(self):
### actions on meenubar
exitAct = QtWidgets.QAction('&Exit', self, shortcut='Ctrl+Q', statusTip='application')
exitAct.triggered.connect(self.close)
moreinfo = QtWidgets.QAction('&Help',self, statusTip='More information')
moreinfo.triggered.connect(self.information)
### menubar
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAct)
fileMenu = menubar.addMenu('&Help')
fileMenu.addAction(moreinfo)
### basic geometry and color
self.setWindowTitle('Villain')
self.setWindowIcon(QtGui.QIcon('dc1.png'))
self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
def layout_init(self):
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
### widgets
self.tablewidget = QtWidgets.QTableWidget()
self.tablewidget.setColumnCount(4)
self.tablewidget.setHorizontalHeaderLabels(["FileNameTransformed", "OrderItemCode", "Imported", "Row"])
self.tablewidget.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.tablewidget.horizontalHeader().setStretchLastSection(True)
self.tablewidget.resizeColumnsToContents()
self.tablewidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.tablewidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
#self.tablewidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.textbox = QtWidgets.QLineEdit()
self.textbox.setPlaceholderText('IMEI')
self.textbox.setEnabled(True)
regexp = QtCore.QRegExp('^(0\d+|[1-9][0-9]+)$') #IMEI = only int
self.textbox.setValidator(QtGui.QRegExpValidator(regexp))
self.pb = QtWidgets.QPushButton(self.tr("Run process"))
self.pb.setDisabled(True)
self.textbox.textChanged.connect(self.disableButton)
self.pb.clicked.connect(self.on_clicked_pb)
self.clearbutton = QtWidgets.QPushButton(self.tr("Clear all"))
self.clearbutton.setDisabled(True)
self.clearbutton.clicked.connect(self.on_clicked_clear)
### make vidgets alive
grid = QtWidgets.QGridLayout(central_widget)
grid.addWidget(self.textbox)
grid.addWidget(self.tablewidget)
grid.addWidget(self.pb)
grid.addWidget(self.clearbutton)
self.table_performance()
### center main window
def center(self):
qr = self.frameGeometry()
cp = QtWidgets.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def information(self):
QtWidgets.QMessageBox.information(self,'Information','Version: 1.19.11.18\n'\
'This is the prototype of the application\n\n'\
'Please, contact karol.chojnowski#digitalcaregroup.com for comments and suggestions\n\n'\
'Digital Care - Data Processing Team')
#QtCore.pyqtSlot()
def disableButton(self):
val = bool(self.textbox.text())
self.pb.setDisabled(not val)
self.clearbutton.setDisabled(not val)
### run process button
#QtCore.pyqtSlot()
def on_clicked_pb(self):
if self.textbox.text():
threading.Thread(target=self.sql_query, daemon=True).start()
### clear all
#QtCore.pyqtSlot()
def on_clicked_clear(self):
if self.textbox.text():
self.textbox.clear()
self.tablewidget.setRowCount(0)
self.tablewidget.setColumnWidth(3, 200)
def setCredentials(self, credentials):
self._credentials = credentials
def table_performance(self):
self.tablewidget.resizeColumnsToContents()
self.tablewidget.setColumnWidth(3, 2500)
self.tablewidget.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
#QtCore.pyqtSlot(str, str)
def show_warning(self, title, msg):
QtWidgets.QMessageBox.information(self, title, msg)
#QtCore.pyqtSlot()
def clear_items(self):
self.tablewidget.setRowCount(0)
#QtCore.pyqtSlot(int, int, str)
def add_item(self, row, column, val):
if row >= self.tablewidget.rowCount():
self.tablewidget.insertRow(self.tablewidget.rowCount())
newitem = QtWidgets.QTableWidgetItem(val)
self.tablewidget.setItem(row, column, newitem)
#QtCore.pyqtSlot()
def sort_items(self):
self.tablewidget.sortItems(0, order=QtCore.Qt.DescendingOrder)
def sql_query(self):
ser = "10.96.6.14"
base = "PROD_WAREX2"
username, pwd = self._credentials
try:
connection = pyodbc.connect(driver='{SQL Server}', server=ser, database=base,
user=username, password=pwd)
cursor = connection.cursor()
res = cursor.execute(""" SELECT FI.FileNameTransformed,
FI.OrderItemCode,
FIR.Imported,
FR.Row
FROM [FileRows] AS FR
JOIN [FileImportRows] AS FIR ON FR.RowId = FIR.RowId
JOIN [FileImports] AS FI ON FIR.FileImportId = FI.Id
WHERE FR.Row LIKE ? """, ('%' + self.textbox.text() + '%'))
if not cursor.rowcount:
QtCore.QMetaObject.invokeMethod(self, "show_warning",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, 'IMEI'), QtCore.Q_ARG(str, "No items found"))
else:
QtCore.QMetaObject.invokeMethod(self, "clear_items", QtCore.Qt.QueuedConnection)
QtCore.QThread.msleep(10)
for row, form in enumerate(res):
for column, item in enumerate(form):
QtCore.QMetaObject.invokeMethod(self, "add_item",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(int, row), QtCore.Q_ARG(int, column), QtCore.Q_ARG(str, str(item)))
QtCore.QThread.msleep(10)
QtCore.QMetaObject.invokeMethod(self, "sort_items", QtCore.Qt.QueuedConnection)
cursor.close()
except:
QtCore.QMetaObject.invokeMethod(self, "show_warning",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, 'Error'), QtCore.Q_ARG(str, "Something went wrong\n\n"\
"Contact karol.chojnowski#digitalcaregroup.com"))
I'm new to PyQt and Python as a whole (more familiar with Java) and I'm trying to make an application where data is inserted and retrieved into the database. For the connection to the database, I'm using mysql connector. I'm able to insert and retrieve data just fine but I'm not sure how to implement the GUI portion of my application. What I want to do is have a login window that connected to the database for the main window to then insert data read from the file into the database and retrieve data based on what was selected by the user. Clicking "Sign in" should close the Login Window and open the Main Windows which shows a progress bar while inserting and should display results which users can sort by ( have not implemented it yet.
What are ways I could improve my program? My program sometimes hangs.
How could I go about my approach?
Is there an equivalent to Java's JFrame.dispose() in Python which closes then Window and clicking on a button?
The Login Window:
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import QPushButton, QLabel
from PyQt4.QtGui import QPlainTextEdit
from PyQt4.QtGui import QLineEdit
from MainGUI import MainGUI
import time
class LoginGUI(QtGui.QMainWindow):
def __init__(self):
super(LoginGUI, self).__init__()
self.setGeometry(730, 350, 500, 300)
self.setWindowTitle("Login")
self.initGUI()
def initGUI(self):
titleLabel = QLabel("Login", self)
titleLabel.move(200, 20)
titleLabel.setFont(QtGui.QFont("", 20))
loginLabel = QLabel("Username: ", self)
loginLabel.move(135, 120)
passwordLabel = QLabel("Password: ", self)
passwordLabel.move(135, 150)
loginText = QPlainTextEdit("root", self)
loginText.move(195, 120)
passwordText = QLineEdit("",self)
passwordText.move(195, 150)
passwordText.setEchoMode(QtGui.QLineEdit.Password)
loginBtn = QtGui.QPushButton("Sign in", self)
loginBtn.clicked.connect(lambda:
self.connectToDB(loginText.toPlainText(), passwordText.text()))
loginBtn.resize(loginBtn.sizeHint())
loginBtn.move(170, 250)
quitBtn = QtGui.QPushButton("Quit", self)
quitBtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
quitBtn.resize(quitBtn.sizeHint())
quitBtn.move(245,250)
self.show()
def connectToDB(self,username,password):
pmg = MainGUI()
pmg.prep("D:\\folder\\data.csv", username, password)
pmg.run()
#logonGUI.close()
#mainApp = QtGui.QApplication(sys.argv)
#mainGUI = MainGUI()
#sys.exit(app.exec_())
#return pmg
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
logonGUI = LoginGUI()
sys.exit(app.exec_())
The Main Window:
other imports
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import QPushButton, QLabel
from PyQt4.QtGui import QPlainTextEdit
from PyQt4.QtCore import QEventLoop
from viewer.DataSource import DataSource
class MainGUI(QtGui.QMainWindow):
theFile = None
username = None
password = None
source = None
con = None
rowsInserted = 0
progressBar = None
completed = 0
def __init__(self):
#app = QtGui.QApplication(sys.argv)
#mainGUI = MainGUI()
#sys.exit(app.exec_()).
super(MainGUI, self).__init__()
self.setGeometry(730, 350, 1000, 600)
self.setWindowTitle("MainWindow")
self.initGUI()
#self.show()
def prep(self, x, username, password):
try:
self.theFile = open(x, "r")
self.username = username
self.password = password
#Connect to db and pass connection to each class.
#Close connection at the end in a Finally statement.
self.source = DataSource()
self.con = self.source.getConnection(username, password)
except FileNotFoundError:
print("No file of {} found.".format(x))
def initGUI(self):
titleLabel = QLabel("MainWindow", self)
titleLabel.resize(200, 20)
titleLabel.move(450, 30)
titleLabel.setFont(QtGui.QFont("", 20))
quitBtn = QtGui.QPushButton("Quit", self)
quitBtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
quitBtn.resize(quitBtn.sizeHint())
quitBtn.move(800,550)
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setGeometry(200, 80, 250, 20)
def run(self):
with self.theFile as data:
lines = data.readlines()[1:]
for line in lines:
QtCore.QCoreApplication.processEvents(flags=QEventLoop.AllEvents)
#Line with QtCore supposed to be indented.
cleanDataFromDB(self.con)
insertData(self.con)
dao.retrieve(userInput)
try:
if self.con != None:
self.con.close()
except:
print("Error closing the database.")
I have found my solution.
I have made my instance of the MainGUI global so that it doesn't close.
def connectToDB(self,username,password):
global pmg
pmg = MainGUI()
pmg.prep("D:\\folder\\data.csv", username, password)
pmg.run()
self.close()
I have made some changes to my MainGUI itself by adding some show() statements to the title and button for before in initGUI() and after the loop of run(), and having repaint() after the show() after the loop.
def initGUI(self):
titleLabel = QLabel("MainWindow", self)
titleLabel.resize(200, 20)
titleLabel.move(450, 30)
titleLabel.setFont(QtGui.QFont("", 20))
titleLabel.hide()
quitBtn = QtGui.QPushButton("Quit", self)
quitBtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
quitBtn.resize(quitBtn.sizeHint())
quitBtn.move(800,550)
quitBtn.hide()
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setGeometry(200, 80, 250, 20)
self.progressBar.show()
def run(self):
with self.theFile as data:
lines = data.readlines()[1:]
for line in lines:
QtCore.QCoreApplication.processEvents()
cleanDataFromDB(self.con)
insertData(self.con)
progressBar.hide()
titleLabel.show()
quitBtn.show()
self.repaint()
Thanks for taking your time to help me. :D