Не стоит использовать такой простой подход, чтобы проверить, существует ли файл, потому что он излишне потребляет много ресурсов ЦП.
Также, используя любой тип l oop (while / for или рекурсивный вызовы функций) - плохая идея при работе с пользовательским интерфейсом: как вы уже видели, он блокирует интерфейс; хотя решение , предложенное abhilb, может показаться работоспособным, оно просто делает пользовательский интерфейс отзывчивым, но в любом случае будет вызывать пики ЦП, даже после закрытия программы и создания файла.
PyQt уже имеет прослушиватель файлов, QFileSystemWatcher , и внешним системам с Qt следует избегать того, чтобы функциональность уже обеспечивала его, это учитывается не только для наблюдателя файлов, но и для потоков.
Еще один важный аспект, о котором следует помнить, это то, что Qt имеет свое собственное событие l oop, и для взаимодействия с ним не рекомендуется использовать потоки python (на самом деле, каждые * 1011) * Взаимодействие с пользовательским интерфейсом должно выполняться в основном потоке, даже при использовании потоков Qt).
Если вы действительно хотите использовать слушатель файла basi c (например, для учебных целей), вы должны по крайней мере добавьте в цикл официанта, и этот цикл имеет , чтобы быть в другом потоке, в противном случае GUI будет заблокирован в любом случае.
Ниже приведен вывод ementation полностью основан на Qt, основываясь на вашем коде.
import sys
from PyQt5 import QtCore, QtWidgets
fileToWatch = 'C:/Users/Wicaledon/PycharmProjects/myproject/a.txt'
editorProgram = 'notepad'
class ListenWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ListenWindow, self).__init__(parent)
self.setWindowTitle("Listen")
self.button_listen = QtWidgets.QPushButton('Listen', self)
font1 = self.button_listen.font()
font1.setPointSize(10)
self.button_listen.setFont(font1)
self.button_listen.setFixedSize(200, 50)
self.button_listen.clicked.connect(self.startToListen)
self.v_box1 = QtWidgets.QVBoxLayout(self)
self.v_box1.addWidget(self.button_listen)
# no parent with an already existing layout should be set for a new
# layout; in this case, the current widget already has the v_box1 layout
# set, therefore the new h_box1 layout should have no argument
self.h_box1 = QtWidgets.QHBoxLayout()
self.v_box1.addLayout(self.h_box1)
self.listener = QtCore.QFileSystemWatcher(self)
self.listener.directoryChanged.connect(self.checkFile)
def startToListen(self):
fileInfo = QtCore.QFileInfo(fileToWatch)
if fileInfo.exists():
self.createStart()
return
elif fileInfo.absolutePath() not in self.listener.directories():
self.listener.addPath(fileInfo.absolutePath())
# create an empty file so that there's no error when trying to open
# it in the editor
emptyFile = QtCore.QFile(fileToWatch)
emptyFile.open(emptyFile.WriteOnly)
emptyFile.close()
process = QtCore.QProcess(self)
process.start(editorProgram, [fileToWatch])
# optional: disable the interface until the program has quit
self.setEnabled(False)
process.finished.connect(lambda: self.setEnabled(True))
def checkFile(self, path):
fileInfo = QtCore.QFileInfo(fileToWatch)
if fileInfo.exists():
if self.h_box1:
# the layout already contains the start button, ignore
return
else:
self.createStart()
else:
# file has been [re]moved/renamed, maybe do something here...
pass
def createStart(self):
self.button_start = QtWidgets.QPushButton('Start', self)
font2 = self.button_start.font()
font2.setPointSize(10)
self.button_start.setFont(font2)
self.button_start.setFixedSize(200, 50)
self.h_box1.addWidget(self.button_start, 0, QtCore.Qt.AlignCenter)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = ListenWindow()
window.setWindowTitle('Login')
window.show()
sys.exit(app.exec_())