So what i would like to do is from the main Qt application start a bunch of separate Qt applications each on separate processes ... do their job then report to the main application when finished.
Could you guys point me in the right direction . I tried with multiprocessing but i get stuck initializing the separate Qt applications
Thank you
Something like this ... which is wrong
import sys
import multiprocessing
from multiprocessing import Pool
from PyQt4 import QtCore, QtGui ,QtNetwork
from PyQt4 import QtWebKit
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from PyQt4.QtGui import QApplication
class SimpleWin(QtGui.QWidget):
def __init__(self, parent=None):
super(SimpleWin, self).__init__(parent)
self.buton = QtGui.QPushButton("START")
self.buton.clicked.connect(self.RunJob)
hbox = QtGui.QHBoxLayout()
hbox.addWidget(self.buton)
self.setLayout(hbox)
def RunJob(self):
print "RUUN"
jobs = []
for i in range(5):
p = multiprocessing.Process(target=Render,)
print i
jobs.append(p)
p.start()
class Render(QWebView,multiprocessing.Process):
def __init__(self, prox ):
self.app = QApplication(sys.argv)
QWebPage.__init__(self)
# self.crawl()
self.load(QUrl("http://www.ip-score.com/"))
self.show()
self.app.exec_()
def main():
app = QtGui.QApplication(sys.argv)
browse = SimpleWin()
browse.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Related
I use pyttsx3 engine to convert text to speech. And when I click 'start' I create a thread with I target set to 'self.start' so the app doesn't freeze while speaking. And I want to STOP the thread and therefore the engine will stop automaticly. And I tried to rasie exception to kill the thread but it was so useless for my case...
The main qustion here is 'I want to kill the thread so I can stop the engine when clicking 'end' button'
my code:
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtCore
import sys
import time
import threading
import pyttsx3
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.move(50, 220)
self.resize(500, 500)
self.btn = QPushButton('start', self)
self.btn.move(10, 250)
self.btn.clicked.connect(self.create_a_thread)
self.btn2 = QPushButton('end', self)
self.btn2.move(10, 290)
self.btn2.clicked.connect(self.end)
self.engine = pyttsx3.init()
self.rate = self.engine.getProperty('rate')
self.engine.setProperty('rate', 75)
def start(self):
self.engine.say('I want to stop this thread')
self.engine.runAndWait()
def create_a_thread(self):
thread = threading.Thread(target=self.start, daemon=True)
thread.start()
def end(self):
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
ex.show()
sys.exit(app.exec_())
I am trying to edit the text in 'QTextEdit' but I got the error which is in the title above. I know that I shouldn't edit the widgets in the main app from another thread and I searched for some answers, But I didn't get the full answer that I want
This is a sample that produce the same error that I have
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtCore
import sys
import time
import threading
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.move(50, 220)
self.resize(500, 500)
self.text_edit = QTextEdit(self)
self.text_edit.resize(200, 200)
self.btn = QPushButton('start', self)
self.btn.move(10, 250)
self.btn.clicked.connect(lambda x : self.thread_creator(self.test))
self.btn2 = QPushButton('print', self)
self.btn2.move(10, 290)
self.btn2.clicked.connect(lambda x : print('dad'))
def test(self):
for i in range(99):
self.text_edit.setText(f'dad {i}')
time.sleep(0.1)
def thread_creator(self, function):
self.thread = threading.Thread(target=function)
self.thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
ex.show()
sys.exit(app.exec_())
i am stuck in call function from pushButton.
in my project:
app.py, which is the main file to run the project.
ui_mainWindow.py is the file consist of tab widget.
Account.py is the converted file from account.ui
main_Account.py is the file where i import Account.py file.
account_handler.py is the file where consist of functions.
now when i run my project by running app.py ,it will show all contents of ui_mainWindow.py .now if i choose account tab from tabwidget than it will show all contents of mainAccount.py. now if i hit a button from mainAccount.py than function will be call from account_handler.py.
everything working fine but while i hut pushButton nothin happen.
this is my previous post : PyQt5 push button method called from separate python file ,
i follow this separately and this working fine, but in my project samecode not working. can anyone tell me where i am wrong!
app.py
from importlib import reload
import PyQt5.QtCore as QtCore
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QMainWindow,QApplication
import sys
import files.interfaces.ui_mainWindow
import files.interfaces.dashboard
reload(files.interfaces.dashboard)
import files.main_Interfaces.mainAccount
reload(files.main_Interfaces.mainAccount)
import files.interfaces.account2
reload(files.interfaces.account2)
class MainWindow(QMainWindow, files.interfaces.ui_mainWindow.Ui_MainWindow):
def __init__(self):
# Base class
QMainWindow.__init__(self)
self.ui = files.interfaces.ui_mainWindow.Ui_MainWindow()
self.ui.setupUi(self)
self.setWindowTitle("PORTFOLIO ACCOUNTING")
# import tab1
self.TabWidget = QtWidgets.QWidget()
ui = files.interfaces.dashboard2.Ui_Form()
ui.setupUi(self.TabWidget)
self.ui.tabWidget.insertTab(0, self.TabWidget, "Dashboard")
# import tab2
self.TabWidget = QtWidgets.QWidget()
ui = files.main_Interfaces.mainAccount.MainWindow()
ui.setupUi(self.TabWidget)
self.ui.tabWidget.insertTab(1, self.TabWidget, "Account")
def main():
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("Portfolio Accounting")
application = MainWindow()
application.show()
app.exec_()
if __name__ == '__main__':
main()
main_Account.py
from PyQt5 import QtCore, QtGui, QtWidgets
from files.interfaces.account import Ui_Form
from event_handler.account_EventHndler import function2
class MainWindow(QtWidgets.QMainWindow,Ui_Form):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.pushButton_2.clicked.connect(function1)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
account_handler.py
def function1():
print("function called")
You code is a bit confusing since you use the same class names in different modules and there is an inconsistencies between the names of the modules you are importing and the names of the .py files you provided but I'm assuming that files.main_Interfaces.mainAccount.MainWindow refers to mainWindow in main_Account.py. In that case, in app.MainWindow.__init__ tab2 should probably be something like
# import tab2
self.TabWidget = files.main_Interfaces.mainAccount.MainWindow()
self.ui.tabWidget.insertTab(1, self.TabWidget, "Account")
I want to use startup function which should have while loop.
but I run the code my gui doesn't appear until while loop ends.
I tried with self.show() it can make show gui but it doesn't allow to use sys.exit()
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5 import uic
import time
form_class,QMainWindow=uic.loadUiType('youhua.ui')
class MyWindow(QMainWindow,form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
#self.show()
self.myfunc()
def myfunc(self):
k=1
stat=True
while stat:
k=k+1
time.sleep(1)
self.statusMessage.append(str(k))
QApplication.processEvents()
if k>10:
stat=False
#sys.exit()
if __name__=='__main__':
app=QApplication(sys.argv)
myWindow=MyWindow()
myWindow.show()
app.exec_()
If you need to perform an action again, you have several options.
For example, if each iteration takes very little time, without the possibility of blocking the main loop, you can replace the cycle with a timer (QTimer) and call the method each time, which is responsible for obtaining new data and updating the necessary interface elements in accordance with them:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic
from PyQt5.QtCore import QThread, QTimer
import time
#form_class, QMainWindow = uic.loadUiType('youhua.ui')
class MyWindow(QMainWindow): #, form_class):
def __init__(self):
super().__init__()
self.k = 0
centralWidget = QtWidgets.QWidget(self)
self.setCentralWidget(centralWidget)
self.button = QtWidgets.QPushButton('Start', self)
self.button.clicked.connect(self.read_data)
self.label_data = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignCenter)
self.label_data.setText('Pending')
layout = QtWidgets.QGridLayout(centralWidget)
layout.addWidget(self.label_data)
layout.addWidget(self.button)
self.timer = QtCore.QTimer(self)
self.timer.setInterval(1000)
self.timer.timeout.connect(self.read_data_from_sensor)
#QtCore.pyqtSlot()
def read_data(self):
''' Start / Stop reading at the touch of a button '''
if not self.timer.isActive():
self.timer.start()
self.button.setText("Stop")
else:
self.timer.stop()
self.button.setText("Start")
self.label_data.setText("Pending")
#QtCore.pyqtSlot()
def read_data_from_sensor(self):
dt = time.strftime("%Y-%m-%d %H:%M:%S")
self.label_data.setText(dt)
self.label_data.adjustSize()
self.k += 1
self.statusBar().showMessage('{} item(s)'.format(self.k))
if self.k > 10:
self.timer.stop()
self.button.setText("Start")
self.label_data.setText("Pending")
self.k = 0
if __name__=='__main__':
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
What you wrote may also work, but this is not very good. You can compare.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic
from PyQt5.QtCore import QThread
#import time
#form_class, QMainWindow = uic.loadUiType('youhua.ui')
class MyWindow(QMainWindow): #, form_class):
def __init__(self):
super().__init__()
# self.setupUi(self)
self.show()
self.myfunc()
def myfunc(self):
k = 0
stat = True
while stat:
k += 1
# time.sleep(1)
# self.statusMessage.append(str(k))
self.statusBar().showMessage('{} item(s)'.format(k))
QThread.msleep(1000)
QApplication.processEvents()
if k>10:
stat=False
#sys.exit()
if __name__=='__main__':
app = QApplication(sys.argv)
myWindow = MyWindow()
# myWindow.show()
app.exec_()
In your loop you are sleeping for 10 second, since you are creating a while loop on the main thread, the GUI wont show until the loop is done because it would be blocking the main thread. You can test this by removing time.sleep(1).
Without changing your code much, try this:
import sys,threading, time
from PyQt5.QtWidgets import QApplication
from PyQt5 import uic
form_class,QMainWindow=uic.loadUiType('youhua.ui')
class MyWindow(QMainWindow,form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
#self.show()
t = threading.Thread(target=self.myfunc)
t.start()
def myfunc(self):
k=1
stat=True
while stat:
k=k+1
time.sleep(1)
self.statusMessage.append(str(k))
QApplication.processEvents()
if k>10:
stat=False
#sys.exit() - if you are trying to close the window here use self.close()
if __name__=='__main__':
app=QApplication(sys.argv)
myWindow=MyWindow()
myWindow.show()
sys.exit(app.exec_())
I have a class GUI, where I set up all my widgets etc. for my GUI. I use threading to start a process from another class. This works fine, as long that other process just runs through. In some cases, I need to wait for a user input to proceed. I used tkmessagebox for this, but the messagebox doesn't appear and blocks the GUI without any error message. (It works when not started through the GUI).
Here's part of my code:
GUI part
from Tkinter import *
import Tkinter as ttk
import ttk
from tkMessageBox import *
from GUI_reader import Commandline_Reader
import threading
import Queue
class GUI:
def __init__(self,master):
self.master = master
self.argString='ds'
## self.workerThread()
button = ttk.Button(text='start', command=self.go).grid()
...
def go(self):
self.thread = threading.Thread(target=self.workerThread)
self.thread.daemon = True
self.thread.start()
...
def workerThread(self):
...
reader = Commandline_Reader(master, self.argString)
if reader.connect():
print 'success'
reader.run()
print 'success'
if __name__ == '__main__':
root = Tk()
client = GUI(root)
root.mainloop()
class commandline_reader:
import tkMessageBox
...
class Commandline_Reader:
def __init__(self, master, argString='')
self.master = master
...
def connect(self)
...
def run(self):
...
tkMessageBox.askokcancel('Calibration', 'Hit ok to start calibration', parent= self.master)
...
if __name__ == '__main__':
reader = Commandline_Reader(self,master)
if not reader.connect():
exit(-1)
if not reader.run():
exit(-2)