Closing a window with close() will close all open windows - python

I am using Python and I have a main window with a button that opens another window which contain stackedWidget, when the user click "Finish" on the second window I want to close it. but when i try to use self.close() method it closing the main windows as well.
here is the part in my code that handle the Finish click event on the second window:
def click_next(self):
if self.next.text()!="Finish>":
if self.stackedWidget.currentIndex()!=2:
self.stackedWidget.setCurrentIndex(self.stackedWidget.currentIndex()+1)
else:
self.next.setText("Finish>")
self.stackedWidget.setCurrentIndex(self.stackedWidget.currentIndex() + 1)
else:
self.close()
Is there another way to close one window and keep the main open.
Thanks.
So for the example I created 2 windows ( main and screen1), the button in main will open screen1 and the button in screen1 expected to close only screen1 but it close both windows.
code for main window:
from PyQt5 import QtCore, QtGui, QtWidgets
from screen1 import Ui_screen1
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(584, 567)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.button = QtWidgets.QPushButton(self.centralwidget, clicked=lambda:
self.gotoscreen1())
self.button.setGeometry(QtCore.QRect(220, 260, 131, 51))
self.button.setObjectName("buton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 584, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def gotoscreen1(self):
self.window = QtWidgets.QMainWindow()
self.ui = Ui_screen1()
self.ui.setupUi(self.window)
self.window.show()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.button.setText(_translate("MainWindow", "go to screen1"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
code for screen1:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_screen1(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(384, 567)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.button = QtWidgets.QPushButton(self.centralwidget, clicked=lambda: self.close())
self.button.setGeometry(QtCore.QRect(120, 260, 131, 51))
self.button.setObjectName("buton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 584, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def close(self):
self.close()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.button.setText(_translate("MainWindow", "Close"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_screen1()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

The problem isn't that it is closing both windows, it's that your whole app is crashing because it has reached the maximum recursion depth.
The issue is with your close method.
def close(self):
self.close()
All this is doing is calling itself over and over and over again until it crashes the program.
To fix this simply remove the close method completely, then in your setupUi method change the line that creates the self.button to:
self.button = QtWidgets.QPushButton(self.centralwidget, clicked=MainWindow.close)
I would also recommend subclassing QMainWindow instead of using the uic-like design.

Related

PyQT: get real time print output in window

I'm working on a GUI for calling a function 'my_function' when the button 'my_button' is pushed.
This function processes data iteratively. It contains a 'for' loop, and at each iteration it prints out a message that shows the progress of my function. I would like this prints to be displayed in my GUI (in this example in a textEdit widget), in real time. How could I do that?
I would like to make it clear that I need real time display. I found some solutions online, but all prints only appear when the function finishes execution. I need the prints to display in real time in order to appreciate the function progress. Thanks in advance for your tips!
Here's a minimal reproductible example (I obtained the template via qt designer):
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(163, 225)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.formLayout = QtWidgets.QFormLayout(self.centralwidget)
self.formLayout.setObjectName("formLayout")
self.my_button = QtWidgets.QPushButton(self.centralwidget)
self.my_button.setObjectName("my_button")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.my_button)
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setObjectName("textEdit")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.textEdit)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 163, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.my_button.clicked.connect(self.my_function)
def my_function(self):
for idx in range(10):
print('Executing iteration '+str(idx)+' ...')
time.sleep(1) # replaces time-consuming task
print('Finished!')
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.my_button.setText(_translate("MainWindow", "Execute"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Golden rule of Qt: You should not execute tasks that consume a lot of time in the main thread of the GUI since they block the event loop of Qt.
Considering the above, you must execute the time-consuming task in another thread and send the information to the GUI thread through signals.
On the other hand you should not modify the class generated by Qt Designer, instead create another class that inherits from the appropriate widget and is filled in with the initial class.
import threading
import time
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(163, 225)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.formLayout = QtWidgets.QFormLayout(self.centralwidget)
self.formLayout.setObjectName("formLayout")
self.my_button = QtWidgets.QPushButton(self.centralwidget)
self.my_button.setObjectName("my_button")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.my_button)
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setObjectName("textEdit")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.textEdit)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 163, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.my_button.setText(_translate("MainWindow", "Execute"))
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
valueChanged = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.valueChanged.connect(self.on_value_changed)
self.my_button.clicked.connect(self.on_clicked)
#QtCore.pyqtSlot()
def on_clicked(self):
threading.Thread(target=self.my_function, daemon=True).start()
#QtCore.pyqtSlot(int)
def on_value_changed(self, value):
self.textEdit.append("Value: {}".format(value))
def my_function(self):
for idx in range(10):
self.valueChanged.emit(idx)
print("Executing iteration " + str(idx) + " ...")
time.sleep(1) # replaces time-consuming task
print("Finished!")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

How to refresh the Label text in my app when i click the Refresh Button?

I Want this app to refresh the 'label' data (Which is a datetime) when i click the Refresh Button.
I tried pushButton.clicked.connect(ui.setupUi(MainWindow)), but it is not working, im out of clue how to do that.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
import datetime
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(200, 200)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(30, 30, 121, 61))
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
import datetime
dt = str(datetime.datetime.now())
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", dt))
pushButton = QtWidgets.QPushButton(self.centralwidget)
pushButton.setGeometry(QtCore.QRect(120, 150, 75, 23))
pushButton.setObjectName("pushButton")
# pushButton.clicked.connect(ui.setupUi(MainWindow))
pushButton.setText(_translate("MainWindow", "Refresh"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
After clicking the Refresh button the time should update.
You really shouldn't re-initialize the ui for that, but just set the text for the label.
Also, since datetime.datetime.now() is "dynamic", you should use a lambda or, better, a dedicated slot.
The "simpler" solution, based on your code, is use this where you have the commented code:
pushButton.clicked.connect(lambda: self.label.setText(str(datetime.datetime.now())))
Or, sometimes better, the same thing in a specific method:
def retranslateUi(self, MainWindow):
# ...
pushButton.clicked.connect(self.setCurrentDate)
# ...
def setCurrentDate(self):
self.label.setText(str(datetime.datetime.now()))
You were there almost. Using pushButton.clicked.connect() is correct, but you don't need to recall the initUI function.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
import datetime
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(200, 200)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(30, 30, 121, 61))
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
dt = str(datetime.datetime.now())
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", dt))
pushButton = QtWidgets.QPushButton(self.centralwidget)
pushButton.setGeometry(QtCore.QRect(120, 150, 75, 23))
pushButton.setObjectName("pushButton")
pushButton.clicked.connect(lambda: self.update_time())
pushButton.setText(_translate("MainWindow", "Refresh"))
def update_time(self):
self.label.setText(str(datetime.datetime.now()))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I made it in a seperate function so you can add more things to it if you want. You could also make pushButton a class member so you can check the state in update_time(). Or you could pass it as an function argument.

Pyqt5: Dialogue box disappears immediately after appearing [duplicate]

This question already has answers here:
Variable scopes in Python classes
(4 answers)
Closed 2 years ago.
I have a situation in which I want a dialogue box to appear when a button is clicked. I used Qt designer to create a main window as well as a dialogue box. By looking at some online tutorials and answers on StackOverflow I managed to write this code
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(557, 383)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(180, 70, 201, 81))
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.newWindow)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 557, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "new window"))
def newWindow(self):
dialog = QtWidgets.QDialog()
self.myOtherWindow = Ui_Dialog()
self.myOtherWindow.setupUi(dialog)
dialog.show()
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
if __name__ == "__main__":
import sys
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
The problem is that when I click the pushbutton, the dialogue box appears for an instance and then disappears. What am I missing?
WARNING! Never change the .ui file
All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(557, 383)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(180, 70, 201, 81))
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.newWindow)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 557, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "new window"))
"""
def newWindow(self):
self.dialog = QtWidgets.QDialog()
self.myOtherWindow = Ui_Dialog()
self.myOtherWindow.setupUi(self.dialog)
self.dialog.show()
"""
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
def newWindow(self):
dialog = QtWidgets.QDialog()
dialog.setWindowTitle("Dialog")
dialog.setGeometry(800, 300, 400, 300)
dialog.exec_()
if __name__ == "__main__":
import sys
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
window = MainWindow()
window.show()
sys.exit(app.exec_())

Resizing table widget when window is maximized

I have a simple pyqt UI in which there is a table widget. I want the widget to resize when I resize the main window. There is a similar question posted on stackOverflow (Resizing table columns when window is maximized), but the answers given do not solve my purpose. In particular I tried usingself.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
. It resizes the column width of the table according to the table widget geometry but does not resize the widget itself when I resize the main window. I'm using pyqt5 and spyder IDE.
Here is an example
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(566, 475)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setWindowTitle("Transactional Data")
self.tableWidget.setGeometry(QtCore.QRect(60, 30, 461, 381))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(7)
self.tableWidget.setRowCount(5)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 566, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Try it:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(566, 475)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout_2.addLayout(self.verticalLayout_2)
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setObjectName("tableWidget")
self.verticalLayout_2.addWidget(self.tableWidget)
self.tableWidget.setWindowTitle("Transactional Data")
self.tableWidget.setColumnCount(7)
self.tableWidget.setRowCount(5)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setHorizontalHeaderLabels(['A','B','C','D','E','F','G'])
self.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 24))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

Reload qml in QQuickView source

I have test.qml file and in PyQt5 am using
self.view = QQuickView()
self.view.setResizeMode(QQuickView.SizeRootObjectToView)
self.view.setSource(QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__),'test.qml')))
I have a button when it is clicked it overwrite the test.qml and call view again to read the test.qml file but it still display the old test.qml not the new one. Why?
Is it something with QQmlEngine clearComponentCache()
sample of the code:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QUrl
from PyQt5.QtQuick import QQuickView
import os
class Ui_MainWindow(object):
def add(self):
# call a function in a nother python file that will open test.qml and overwite it
# when i call the test.qml again it will show the old version not the new one
self.view.setSource(QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__),'root.qml')))
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(420, 380, 113, 32))
self.pushButton.setObjectName("pushButton")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setGeometry(QtCore.QRect(170, 50, 551, 311))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
vbox = QtWidgets.QVBoxLayout(self.frame)
# loading the qml for the first time
self.view = QQuickView()
self.view.setResizeMode(QQuickView.SizeRootObjectToView)
self.view.setSource(QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__),'root.qml')))
self.widget = QtWidgets.QWidget.createWindowContainer(self.view)
vbox.addWidget(self.widget)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.pushButton.clicked.connect(self.add)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I have not worked with QQuickView yet but rather prefer QQmlApplicationEngine. With it, I used an approach similar to the one outlined here.
I guess you could add a method like this to your main window class:
def reload(self):
self.view.engine().clearComponentCache()
self.view.setSource(
QUrl.fromLocalFile(
os.path.join(os.path.dirname(__file__),'root.qml')))
The clearComponentCache() method causes the engine to discard any previously loaded QML documents. On the next load operation (e.g. by using setSource() on your view), the engine will hence be force to reload the file from disk.

Categories