Posts: 36
Threads: 10
Joined: Mar 2020
Hello, everyone. I am a beginner programmer developing an MDI application. So far, I have two files:
main.py (MainWindow with mdiArea and menuBar)
users.py (window that displays users)
I am able to run the users.py file from main.py by using import subprocess and then calling it:
subprocess.call(["python", "users.py"])
It works, but I need the Users window to be a subwindow in the main application. Can anyone please point me in the right direction? Thanks a lot for your time and help.
Posts: 1,838
Threads: 2
Joined: Apr 2017
You're going to need to explain in more detail and show code. It's not clear why you (think you) need a separate process.
Posts: 36
Threads: 10
Joined: Mar 2020
Aug-04-2021, 05:26 PM
(This post was last modified: Aug-05-2021, 02:32 PM by JayCee.)
I'm developing an MDI application which I know is going to be pretty large. It would make sense to me to split the code instead of having one huge Python file that holds everything. I come from the C# .Net world and I think code-splitting makes it easier to debug, easier to maintain.
The attached screenshot shows the User window outside the mdiArea and I would like to run it inside, otherwise it will totally defeat the purpose of developing an MDI application.
Attached Files
Thumbnail(s)
Posts: 1,032
Threads: 16
Joined: Dec 2016
Posts: 1,838
Threads: 2
Joined: Apr 2017
Yes, of course splitting an application up into separate files is important in any large project, but what I'm getting at is do those really need to be entirely separate programs? Can't they just be modules with functions and classes that you import where you need them (like one would do in C#, Java or anything else really)? I don't know what MDI is, so I don't know whether it imposes this separate program thing on you.
Posts: 36
Threads: 10
Joined: Mar 2020
(Aug-04-2021, 05:28 PM)Axel_Erfurt Wrote: Haven't you already achieved that here?
https://python-forum.io/thread-34470-pos...#pid145454
Nope, because in regards to that Post, the entire code is in the same file and now I want to split the code, otherwise it will be a nightmare to maintain.
Posts: 36
Threads: 10
Joined: Mar 2020
Aug-04-2021, 05:37 PM
(This post was last modified: Aug-05-2021, 02:45 PM by JayCee.)
They do not have to be separate programs. I guess they could be modules. The question now is how do I make the users.py file a module I can import. Here is the code to my users.py file:
import sys
import pymysql
from datetime import datetime
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMessageBox
rowNo = 1
connection = pymysql.connect(
host='--------',
user='--------',
password='-------',
db='------------')
cur = connection.cursor()
sql0 = "CREATE TEMPORARY TABLE users_temp AS SELECT * FROM users_view ORDER BY name"
cur.execute(sql0)
class Ui_Dialog(object):
def setupUi(self, myDialog):
myDialog.setObjectName("myDialog")
myDialog.resize(468, 291)
# ----------------------- Buttons -----------------------
self.pushButton_first = QtWidgets.QPushButton(myDialog)
self.pushButton_first.setGeometry(QtCore.QRect(50, 210, 75, 23))
self.pushButton_first.setObjectName("pushButton_first")
self.pushButton_previous = QtWidgets.QPushButton(myDialog)
self.pushButton_previous.setGeometry(QtCore.QRect(140, 210, 75, 23))
self.pushButton_previous.setObjectName("pushButton_previous")
self.pushButton_next = QtWidgets.QPushButton(myDialog)
self.pushButton_next.setGeometry(QtCore.QRect(230, 210, 75, 23))
self.pushButton_next.setObjectName("pushButton_next")
self.pushButton_last = QtWidgets.QPushButton(myDialog)
self.pushButton_last.setGeometry(QtCore.QRect(330, 210, 75, 23))
self.pushButton_last.setObjectName("pushButton_last")
self.pushButton_add = QtWidgets.QPushButton(myDialog)
self.pushButton_add.setGeometry(QtCore.QRect(140, 240, 75, 23))
self.pushButton_add.setObjectName("pushButton_add")
self.pushButton_edit = QtWidgets.QPushButton(myDialog)
self.pushButton_edit.setGeometry(QtCore.QRect(230, 240, 75, 23))
self.pushButton_edit.setObjectName("pushButton_edit")
self.pushButton_update = QtWidgets.QPushButton(myDialog)
self.pushButton_update.setGeometry(QtCore.QRect(230, 240, 75, 23))
self.pushButton_update.setObjectName("pushButton_update")
self.pushButton_cancel = QtWidgets.QPushButton(myDialog)
self.pushButton_cancel.setGeometry(QtCore.QRect(150, 240, 75, 23))
self.pushButton_cancel.setObjectName("pushButton_cancel")
self.pushButton_save = QtWidgets.QPushButton(myDialog)
self.pushButton_save.setGeometry(QtCore.QRect(230, 240, 75, 23))
self.pushButton_save.setObjectName("pushButton_save")
self.pushButton_delete = QtWidgets.QPushButton(myDialog)
self.pushButton_delete.setGeometry(QtCore.QRect(330, 240, 75, 23))
self.pushButton_delete.setObjectName("pushButton_delete")
# ----------------------- Input Fields -----------------------
self.lineEdit_id = QtWidgets.QLineEdit(myDialog)
self.lineEdit_id.setGeometry(QtCore.QRect(70, 80, 331, 20))
self.lineEdit_id.setObjectName("lineEdit_id")
self.lineEdit_name = QtWidgets.QLineEdit(myDialog, placeholderText="Name")
self.lineEdit_name.setGeometry(QtCore.QRect(70, 80, 331, 20))
self.lineEdit_name.setObjectName("lineEdit_name")
self.lineEdit_login = QtWidgets.QLineEdit(myDialog, placeholderText="Login")
self.lineEdit_login.setGeometry(QtCore.QRect(70, 110, 113, 20))
self.lineEdit_login.setObjectName("lineEdit_login")
self.lineEdit_pwd = QtWidgets.QLineEdit(myDialog, placeholderText="Password", echoMode=2)
self.lineEdit_pwd.setGeometry(QtCore.QRect(70, 140, 113, 20))
self.lineEdit_pwd.setObjectName("lineEdit_pwd")
self.reTranslateUi(myDialog)
QtCore.QMetaObject.connectSlotsByName(myDialog)
def reTranslateUi(self, myDialog):
_translate = QtCore.QCoreApplication.translate
myDialog.setWindowTitle(_translate("myDialog", "Users"))
self.pushButton_first.setText(_translate("myDialog", "<< First"))
self.pushButton_first.setObjectName("pushButton_first")
self.pushButton_first.clicked.connect(ShowFirst)
self.pushButton_previous.setText(_translate("myDialog", "< Previous"))
self.pushButton_previous.setObjectName("pushButton_previous")
self.pushButton_previous.clicked.connect(ShowPrevious)
self.pushButton_next.setText(_translate("myDialog", "Next >"))
self.pushButton_next.setObjectName("pushButton_next")
self.pushButton_next.clicked.connect(ShowNext)
self.pushButton_last.setText(_translate("myDialog", "Last >>"))
self.pushButton_last.setObjectName("pushButton_last")
self.pushButton_last.clicked.connect(ShowLast)
self.pushButton_add.setText(_translate("myDialog", "Add +"))
self.pushButton_add.setObjectName("pushButton_add")
self.pushButton_add.clicked.connect(addRecord)
self.pushButton_edit.setText(_translate("myDialog", "Edit"))
self.pushButton_edit.setObjectName("pushButton_edit")
self.pushButton_edit.clicked.connect(editRecord)
self.pushButton_save.setText(_translate("myDialog", "Save"))
self.pushButton_save.setObjectName("pushButton_save")
self.pushButton_save.clicked.connect(saveRecord)
self.pushButton_cancel.setText(_translate("myDialog", "Cancel"))
self.pushButton_cancel.setObjectName("pushButton_cancel")
self.pushButton_cancel.clicked.connect(cancelAll)
self.pushButton_update.setText(_translate("myDialog", "Atualizar"))
self.pushButton_update.setObjectName("pushButton_update")
self.pushButton_update.clicked.connect(updateRecord)
self.pushButton_delete.setText(_translate("myDialog", "Delete"))
self.pushButton_delete.setObjectName("pushButton_delete")
self.pushButton_delete.clicked.connect(deleteRecord)
self.pushButton_cancel.hide()
self.pushButton_save.hide()
self.pushButton_update.hide()
ShowFirst()
lockForm()
def ShowFirst():
global rowNo
sql = "SELECT number, name, login, pwd, id FROM users_temp"
cur.execute(sql)
row = cur.fetchone()
if row:
ui.lineEdit_name.setText(row[1])
ui.lineEdit_login.setText(row[2])
ui.lineEdit_pwd.setText(row[3])
ui.lineEdit_id.setText(str(row[4]))
rowNo = row[0]
else:
QMessageBox.critical(None, "Erro:", "Não foi possÃvel acessar os dados.\n Cheque o servidor.")
def ShowPrevious():
global rowNo
rowNo -= 1
sql = "SELECT number, name, login, pwd, id FROM users_temp WHERE number=%s"
cur.execute(sql, rowNo)
row = cur.fetchone()
if row:
ui.lineEdit_name.setText(row[1])
ui.lineEdit_login.setText(row[2])
ui.lineEdit_pwd.setText(row[3])
ui.lineEdit_id.setText(str(row[4]))
else:
rowNo += 1
def ShowNext():
global rowNo
rowNo += 1
sql = "SELECT number, name, login, pwd, id FROM users_temp WHERE number=%s"
cur.execute(sql, rowNo)
row = cur.fetchone()
if row:
ui.lineEdit_name.setText(row[1])
ui.lineEdit_login.setText(row[2])
ui.lineEdit_pwd.setText(row[3])
ui.lineEdit_id.setText(str(row[4]))
else:
rowNo -= 1
def ShowLast():
global rowNo
sql = "SELECT number, name, login, pwd, id FROM users_temp"
cur.execute(sql)
for row in cur.fetchall():
ui.lineEdit_name.setText(row[1])
ui.lineEdit_login.setText(row[2])
ui.lineEdit_pwd.setText(row[3])
ui.lineEdit_id.setText(str(row[4]))
rowNo = row[0]
def addRecord():
clearAll()
ui.pushButton_edit.hide()
ui.pushButton_delete.hide()
ui.pushButton_add.hide()
ui.pushButton_first.hide()
ui.pushButton_previous.hide()
ui.pushButton_next.hide()
ui.pushButton_last.hide()
ui.pushButton_save.show()
ui.pushButton_cancel.show()
unlockForm()
def editRecord():
ui.pushButton_edit.hide()
ui.pushButton_delete.hide()
ui.pushButton_add.hide()
ui.pushButton_first.hide()
ui.pushButton_previous.hide()
ui.pushButton_next.hide()
ui.pushButton_last.hide()
ui.pushButton_save.hide()
ui.pushButton_cancel.show()
ui.pushButton_update.show()
unlockForm()
def updateRecord():
try:
if ui.lineEdit_name.text() and ui.lineEdit_login.text() and ui.lineEdit_pwd.text() != "":
cur.execute("UPDATE usuarios SET user_real_name=%s, login=%s, pwd=%s WHERE cod_usuario=%s",
(ui.lineEdit_name.text(), ui.lineEdit_login.text(),
ui.lineEdit_pwd.text(), ui.lineEdit_id.text()))
connection.commit()
toggleButtonsVisibility()
QMessageBox.information(None, "Informação:", "Dados atualizados com sucesso!")
refreshData()
lockForm()
else:
QMessageBox.warning(None, "Atenção:", "Por favor preencha os campos em branco!")
except Exception as e:
QMessageBox.critical(None, "Erro:", "Não foi possÃvel atualizar os dados.\n Cheque o servidor. \n " + str(e))
def deleteRecord():
cur.execute("DELETE FROM usuarios WHERE cod_usuario =" + ui.lineEdit_id.text())
connection.commit()
clearAll()
toggleButtonsVisibility()
QMessageBox.information(None, "Informação:", "Usuário deletado com sucesso!")
refreshData()
def refreshData():
sql1 = "DROP TEMPORARY TABLE users_temp"
cur.execute(sql1)
sql2 = "CREATE TEMPORARY TABLE users_temp AS SELECT * FROM users_view ORDER BY name"
cur.execute(sql2)
ShowFirst()
def cancelAll():
ShowFirst()
ui.pushButton_edit.show()
ui.pushButton_delete.show()
ui.pushButton_add.show()
ui.pushButton_first.show()
ui.pushButton_previous.show()
ui.pushButton_next.show()
ui.pushButton_last.show()
ui.pushButton_save.hide()
ui.pushButton_cancel.hide()
ui.pushButton_update.hide()
def toggleButtonsVisibility():
ui.pushButton_add.show()
ui.pushButton_delete.show()
ui.pushButton_edit.show()
ui.pushButton_first.show()
ui.pushButton_previous.show()
ui.pushButton_next.show()
ui.pushButton_last.show()
ui.pushButton_save.hide()
ui.pushButton_save.hide()
ui.pushButton_cancel.hide()
ui.pushButton_update.hide()
def lockForm():
for fields in Dialog.findChildren(QtWidgets.QLineEdit):
fields.setReadOnly(True)
def unlockForm():
for fields in Dialog.findChildren(QtWidgets.QLineEdit):
fields.setReadOnly(False)
def clearAll():
for fields in Dialog.findChildren(QtWidgets.QLineEdit):
fields.clear()
def saveRecord():
try:
if ui.lineEdit_name.text() and ui.lineEdit_login.text() and ui.lineEdit_pwd.text() != "":
cur.execute('INSERT INTO usuarios (user_real_name, login, pwd, data_cadastro) VALUES(%s, %s, %s, %s)',
(ui.lineEdit_name.text(), ui.lineEdit_login.text(), ui.lineEdit_pwd.text(), datetime.today()))
connection.commit()
clearAll()
toggleButtonsVisibility()
QMessageBox.information(None, "Informação:", "Dados adicionados com sucesso!")
refreshData()
lockForm()
else:
QMessageBox.warning(None, "Atenção:", "Por favor preencha os campos em branco!")
except Exception as e:
QMessageBox.critical(None, "Erro:", "Não foi possÃvel inserir os dados.\n Cheque o servidor. \n " + str(e))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(Dialog.exec_())
Posts: 1,838
Threads: 2
Joined: Apr 2017
You haven't shown any code, so it's literally impossible to help further. Of course I'm not saying each single module needs to contain a single class - perhaps there are more in there. No-one can suggest anything without seeing any code. Have you been through a Python tutorial to understand classes? If you're an experienced C# programmer, this shouldn't be too hard.
Posts: 36
Threads: 10
Joined: Mar 2020
Aug-04-2021, 05:44 PM
(This post was last modified: Aug-05-2021, 02:32 PM by JayCee.)
I forgot to insert the code, but I edited the reply. It's there now.
Posts: 1,032
Threads: 16
Joined: Dec 2016
An Example for showing a second window
run win.py
win.py
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction
from PyQt5.QtGui import QIcon
import second_win
class MainWin(QMainWindow):
def __init__(self, parent = None):
super(MainWin, self).__init__(parent)
self.setupUI()
def setupUI(self):
self.setGeometry(0, 0, 600, 400)
self.file_tool_bar = self.addToolBar("File")
self.my_action = QAction(QIcon.fromTheme("folder"), "", triggered = self.show_second_win)
self.file_tool_bar.addAction(self.my_action)
def show_second_win(self):
print("open second win")
self.sw = second_win.SecondWin()
self.sw.show()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
win = MainWin()
win.setWindowTitle("Main Window")
win.show()
sys.exit(app.exec_()) second_win.py
from PyQt5.QtWidgets import QMainWindow, QApplication
class SecondWin(QMainWindow):
def __init__(self, parent = None):
super(SecondWin, self).__init__(parent)
self.setupUI()
def setupUI(self):
self.setGeometry(100, 100, 400, 300)
self.setWindowTitle("Second Window")
|