Seperating concerns in PyQt5 GUI app. Need seperate Qthread for concurrency - python

I have a simple GUI window made using PyQt5 Library.
`
import sys, csv, time
from datetime import datetime
from time import strftime,localtime
import threading
import pandas as pd
import numpy as np
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QTextEdit, QInputDialog, QLineEdit
from PyQt5 import QtCore
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5 import uic
from trade import trade
from pyqtgraph import PlotWidget
import pyqtgraph as pg
from itertools import islice
class UpdateThread(QThread):
signal = pyqtSignal()
def __init__(self, gui):
QThread.__init__(self)
self.gui = gui
def run(self):
try:
# timer = pg.QtCore.QTimer()
# timer.timeout.connect(UI.update_plot(self))
# timer.start(50)
while(True):
self.signal.emit()
time.sleep(5)
except Exception as e:
print(e)
class UI(QMainWindow):
gui = None
p_l = 0.0
display_trades = ''
def __init__(self):
super(UI, self).__init__()
global gui
gui = uic.loadUi('rightside.ui', self)
self.initUI()
self.timer_thread = UpdateThread(gui)
self.timer_thread.signal.connect(self.update_plot)
self.timer_thread.start()
def initUI(self):
self.prices = self.read_prices()
trades = self.get_trades()
list_trade_prices = trades[0].values.tolist()
list_trade_sizes = trades[1].values.tolist()
list_trade_ids = trades[4].drop_duplicates().values.tolist()
as_floats = np.array(list_trade_prices).astype(np.float)
self.set_fields(self.prices)
gui.update_button.clicked.connect(self.on_click)
gui.cancel_button.clicked.connect(self.on_exit)
self.show()
def get_trades(self):
df = pd.DataFrame()
# Get 50 most recent trades
trades = islice(trade.get_product_trades(), 192)
for x in reversed(list(trades)):
# if x['trade_id'] > last_id:
if x['side'] == 'buy':
#more trades that hit the bid force price down
new_row = {0:x['price'], 1:x['size'], 2:1, 3:time.mktime(datetime.timetuple(datetime.now())), 4:x['trade_id']}
df = df.append(new_row, ignore_index=True)
bid_side = True
else:
#more trades that hit the offer force force price up
new_row = {0:x['price'], 1:x['size'], 2:0, 3:time.mktime(datetime.timetuple(datetime.now())), 4:x['trade_id']}
df = df.append(new_row, ignore_index=True)
df = df.drop_duplicates([4], keep='last')
return df
def update_plot(self):
global gui
#set results_chart
trades = UI.get_trades(self)
list_trade_prices = trades[0].values.tolist()
last_price = list_trade_prices[-1]
as_floats = np.array(list_trade_prices).astype(np.float)
gui.results.setText("{0:,.2f}".format(float(last_price)))
gui.results_chart.clear()
gui.results_chart.plot(as_floats)
gui.statusBar().showMessage('Connected')
self.monitor_prices(last_price)
prices = self.read_prices()
self.set_fields(prices)
def get_open_trades(self, btc):
sum_buys = 0.0
open_trades = []
if float(btc) != 0:
for i in trade.get_last_fills():
if i['side'] == 'buy':
sum_buys += float(i['size'])
open_trades.append([i['price'], i['size']])
if sum_buys >= float(btc):
break
return open_trades
def monitor_prices(self, last_price):
global gui
date_local = strftime("%A, %d %b %Y %H:%M:%S", localtime())
stop_enter_price = float(gui.enter_box.toPlainText())
usd = gui.usd_display.text().replace(',', '')
btc = gui.btc_display.text()
trade_amount = ''
if float(last_price) > stop_enter_price and stop_enter_price != 0.0:
if float(usd) > 10.00:
trade_amount = "{0:.2f}".format((float(usd)+(float(btc)*float(last_price)))*0.02718)
result = trade.buy_market(trade_amount)
gui.statusBar().showMessage(str(result))
gui.enter_box.setText('')
with open('stop_enter.txt', 'w') as enter:
enter.write('0.0')
with open('../trades/buys.csv','a') as buys:
writer = csv.writer(buys)
writer.writerow([date_local, last_price, trade_amount, result])
open_trades = self.get_open_trades(btc)
display_trades = ''
trade_amount = 0.0
total_amount = 0.0
STOP_RATE = 0.02
if len(open_trades) != 0:
highest_entry_price = float(open_trades[0][0])
lowest_entry_price = float(open_trades[0][0])
#find lowest price and set stop-loss 2% below that and increment it up
for i,j in enumerate(open_trades):
difference = (float(last_price) - float(open_trades[i][0]))*float(open_trades[i][1])
total_amount += difference
per_diff = str((float(last_price) - float(open_trades[i][0])) / float(open_trades[i][0]))
display_trades += f'{"{0:.3f}".format(float(per_diff)*100)}%\t'
gui.statusBar().showMessage(display_trades)
if highest_entry_price < float(open_trades[i][0]):
highest_entry_price = float(open_trades[i][0])
if lowest_entry_price > float(open_trades[i][0]):
lowest_entry_price = float(open_trades[i][0])
#1R
if float(per_diff) < -STOP_RATE:
if float(btc) > 0.001:
trade_amount = "{0:.8f}".format(float(j[1]))
response = trade.sell_market(trade_amount)
with open('stop_loss.txt', 'w') as enter:
enter.write('0.0')
gui.statusBar().showMessage(str(response))
if float(last_price) < float(gui.stop_box.toPlainText()):
if float(btc) > 0.001:
trade_amount = "{0:.8f}".format(float(btc))
response = trade.sell_market(trade_amount)
gui.statusBar().showMessage(str(response))
def on_click(self):
global gui
enter_price = gui.enter_box.toPlainText()
stop_price = gui.stop_box.toPlainText()
self.write_prices('stop_enter.txt', enter_price)
self.write_prices('stop_loss.txt', stop_price)
gui.statusBar().showMessage('Updated Successfully!')
time.sleep(1.618)
gui.statusBar().showMessage('')
def on_exit(self):
sys.exit(0)
def write_disk(self, date_local, current_price, trade_amount, note, response):
with open('../trades/sells.csv','a') as sells:
writer = csv.writer(sells)
writer.writerow([date_local, current_price, trade_amount, note, response])
def take_it(self, risk_reward, btc):
if float(btc) > 0.001:
response = trade.sell_market(btc)
# playsound(path+'/sounds/sellit.mp3')
write_disk(date_local, current_price, trade_amount, risk_reward, response)
def write_prices(self, file_name, price):
with open(file_name, 'w') as file:
file.write(price)
def set_fields(self, prices):
global gui, p_l
last_price_data = trade.get_last_price()
last_price = last_price_data['price']
last_fill_data = None
while(True):
last_fill_data = trade.get_last_fill()
if 'trade_id' in last_fill_data:
break
last_fill = '0.0'
if last_fill_data['side'] != 'sell':
last_fill = last_fill_data['price']
p_l = float(last_price) - float(last_fill)
gui.enter_box.setText(prices[0])
gui.stop_box.setText(prices[1])
gui.results.setText("{0:,.2f}".format(p_l))
gui.in_price.setText("{0:,.2f}".format(float(last_fill)))
gui.usd_display.setText("{0:,.2f}".format(float(trade.get_usd())))
gui.btc_display.setText("{0:,.8f}".format(float(trade.get_btc())))
def read_prices(self):
content = []
with open('stop_enter.txt', 'r') as enter:
stop_enter = enter.readlines()
content.append(stop_enter[0].rstrip())
with open('stop_loss.txt', 'r') as stop:
stop_loss = stop.readlines()
content.append(stop_loss[0].rstrip())
return content
app = QApplication(sys.argv)
ex = UI()
app.exec_()
`
I am not too familiar with qthreads and how to get them to work. And advice would be greatly appreciated. I just want to Updatethread to call the update_plot once every like 2 seconds or so. Thought this would be pretty simple but this is giving me a headache at this point.
I tried putting the Qtimer in the other thread but then I get an error like 'cannot start timer from other thread'
Thanks for all you help my programmer friends.

For some timing updates it's better to use QTimer and its signal timeout:
from PyQt5.QtCore import QTimer
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
self.timer = QTimer(self)
self.timer.timeout.connect(self.self.update_plot)
# Set 2 seconds interval and start the timer
self.timer.start(2000)
def update_slot(self):
#...

Related

ufunc 'fmin' did not contain a loop with signature matching types When trying to make graph

I can't make graph with qt6 beacouse when I set values it gives me error: numpy.core._exceptions._UFuncNoLoopError: ufunc 'fmin' did not contain a loop with signature matching types (dtype('<U1'), dtype('<U1')) -> None
Theres my code:
import sys
from PySide6.QtWidgets import QApplication
from PySide6 import *
import pyqtgraph as pg
uiclass, baseclass = pg.Qt.loadUiType("mainwindow.ui")
class MainWindow(uiclass, baseclass):
def __init__(self):
super().__init__()
self.setupUi(self)
self.plot([1,2,3,4,5,6,7,8,9,10], [20,20,20,20,20,20,20,20,20,20])
self.pushButton.clicked.connect(lambda: self.changeColorTeeth1())
self.pushButton_2.clicked.connect(lambda: self.changeColorTeeth2())
self.pushButton_3.clicked.connect(lambda: self.changeColorTeeth3())
self.pushButton_4.clicked.connect(lambda: self.changeColorTeeth4())
self.pushButton_5.clicked.connect(lambda: self.changeColorTeeth5())
self.pushButton_6.clicked.connect(lambda: self.changeColorTeeth6())
self.SaveGraphButton.clicked.connect(lambda: self.Save())
def plot(self, teethsize, height):
self.graphWidget.plot(teethsize, height)
self.graphWidget_2.plot(teethsize, height)
def Save(self):
print("Save runned!")
Teeth1 = self.Teeth1.toPlainText()
Teeth2 = self.Teeth2.toPlainText()
Teeth3 = self.Teeth3.toPlainText()
Teeth4 = self.Teeth4.toPlainText()
Teeth5 = self.Teeth5.toPlainText()
Teeth6 = self.Teeth6.toPlainText()
Teeth7 = self.Teeth7.toPlainText()
Teeth8 = self.Teeth8.toPlainText()
Teeth9 = self.Teeth9.toPlainText()
Teeth10 = self.Teeth10.toPlainText()
Teeth11 = self.Teeth11.toPlainText()
Teeth12 = self.Teeth12.toPlainText()
Teeth13 = self.Teeth13.toPlainText()
Teeth14 = self.Teeth14.toPlainText()
self.plot([Teeth1,Teeth2,Teeth3,Teeth4,Teeth5,Teeth6,Teeth7,Teeth8,Teeth9,Teeth10,Teeth11,Teeth12,Teeth13,Teeth14], [20,20,20,20,20,20,20,20,20,20,20,20,20,20])
def changeColorTeeth1(self):
g = open('config.txt', 'r')
buttonClicked = int(g.read())
print("Button State:", buttonClicked)
g.close()
f = open('config.txt', 'w')
if buttonClicked == 0:
self.pushButton.setStyleSheet(f"background-color : orange;")
buttonClicked = 1
elif buttonClicked == 1:
self.pushButton.setStyleSheet(f"background-color : red;")
buttonClicked = 2
elif buttonClicked == 2:
self.pushButton.setStyleSheet(f"background-color : white;")
buttonClicked = 0
b = f.write(str(buttonClicked))
f.close()
...
I tried to add str and int but it still doesn't worked!

How to listen user while playing chunk of audio with qt and simpleaudio

I am trying to play an audio signal with simpleaudio inside a GUI application where the user should react to the content of the chunk played and push a button. At the moment the users push the button I would like to change to the next track. This is all done using the slot and signals from qt in Python 3.x using pytq5. Even when my GUI does not freeze I do not understand why I cannot read the button action during (between) the chunks of audio that are been played, instead all actions are readed after all tracks finish.
My code looks like this:
Module to handle the tracks and chunks
import simpleaudio as sa
import numpy as np
class MusicReactor:
def __init__(self):
self.timeProTone = ...
self.deltaT = ...
self.maxVolSkal = ...
self.minVolSkal = ...
self.frequencySample = ...
self.currentTestedEar = ...
def test_function(self, frequency):
# array of time values
times = np.arange(0, self.timeProTone, self.deltaT)
# generator to create a callable object with new volume each time
for time in times:
# get the volume and set the volume to the starting sequence
currentVolume = (self.maxVolSkal-self.minVolSkal)/self.timeProTone * time + self.minVolSkal
self.setVolumeScalar(currentVolume)
# create chunk the tone as a numpy array
audio = createTone(frequency, self.deltaT, self.frequencySample, self.currentTestedEar)
yield audio, currentVolume
def createTone(frequency, duration, frequencySampled, currentTestedEar = TestEar.Both):
# Generate array with seconds*sample_rate steps, ranging between 0 and seconds
tt = np.linspace((0, 0), (duration, duration), int(duration * frequencySampled), False)
#populate the other ear with zeros
if currentTestedEar is not TestEar.Both:
tt[:, 1-currentTestedEar.value] = 0 # This strategy works only if the note creation i a sinusoidal : sin(0) = 0
# Generate a 440 Hz sine wave
note = np.sin(frequency * tt * 2 * np.pi)
# normalize to 16-bit range
note *= 32767 / np.max(np.abs(note))
# Ensure that highest value is in 16-bit range
audio = note * (2 ** 15 - 1) / np.max(np.abs(note))
# Convert to 16-bit data
audio = audio.astype(np.int16)
return audio
def playTone(audio, frequencySample, num_channels=1, bytes_per_sample=2):
# Start playback
play_obj = sa.play_buffer(audio, num_channels, bytes_per_sample, frequencySample)
# Wait for playback to finish before exiting
play_obj.wait_done()
def generateRndFreq(minF,maxF):
freq = np.random.uniform(low=minF, high=maxF)
return freq
Now the GUI class and its corresponding worker class
class HearingTest_ui(QWidget):
# Send info through signals to subthreads
sig_int_sender = pyqtSignal(int)
hearingObjSender = pyqtSignal( Hearing.HearingTest)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
uic.loadUi("testForm.ui", self)
self.Both_rB.toggled.connect(self.onTogle_earTested)
self.Links_rB.toggled.connect(self.onTogle_earTested)
self.Recht_rB.toggled.connect(self.onTogle_earTested)
# Method 2 Test
self.ML_startButton.clicked.connect(self.runMethod2Test)
self.setMaxMLProgressBar()
self.ml_nTests = self.ML_spinBox.value()
self.ML_spinBox.valueChanged.connect(self.setNTests)
self.ML_spinBox.valueChanged.connect(self.setMaxMLProgressBar)
# Hearing Test Object
self.HT = Hearing.MusicReactor()
def runMethod2Test(self):
# Preprocessing
self.HT.choose_ear(self.testedEarTuple) # reads a tpogle to assign a channel for the chunk of music
# thread and worker configuration
# Step 2: Create a QThread object
self.ml_thread = QThread(parent=self)
# Step 3: Create a worker object
self.ml_worker = ML_Worker(self.ml_nTests)
# Step 4: Move worker to the thread
self.ml_worker.moveToThread(self.ml_thread)
# Step 5: Connect signals and slots
#self.ml_thread.started.connect(partial(self.ml_worker.actualLongTaskFromHearingTest, self.HT))
self.hearingObjSender.connect(self.ml_worker.actualLongTaskFromHearingTest)
self.ml_worker.progress.connect(self.updateProgressbar)
self.ML_spinBox.valueChanged.connect(self.ml_worker.set_maxTests)
self.sig_int_sender.connect(self.ml_worker.set_maxTests)
self.ML_yesButton.clicked.connect(self.ml_worker.change_Flag)
self.ml_worker.request_playchunk.connect(self.ml_worker.sendAudio2queue)
self.ml_worker.finished.connect(self.ml_thread.quit)
self.ml_worker.finished.connect(self.ml_worker.deleteLater)
self.ml_thread.finished.connect(self.ml_thread.deleteLater)
# Final resets
self.ml_worker.changeButtonStatus.connect(self.ML_startButton.setEnabled)
# start thread
print("clicked runMethodOfLimits")
self.ml_thread.start()
self.hearingObjSender.emit(self.HT)
class ML_Worker(QObject):
finished = pyqtSignal()
progress = pyqtSignal(int)
retrieve = pyqtSignal()
changeButtonStatus = pyqtSignal(bool)
request_playchunk = pyqtSignal(np.ndarray, int, Hearing.MusicReactor)
def __init__(self,nTest):
super().__init__()
self.__abort = False
self.nTests = nTest
self.MoLFlag = False
def abort(self):
self.__abort = True
#pyqtSlot(int)
def set_maxTests(self, val):
print(type(val))
logging.info(f"set_maxTests.... {val}")
self.nTests = val
#pyqtSlot()
def change_Flag(self):
print("clicked")
self.MoLFlag = True
# def of long runnning task
#pyqtSlot(Hearing.MusicReactor)
def actualLongTaskFromHearingTest(self, HTObj):
self.changeButtonStatus.emit(False)
self.progress.emit(0)
self.retrieve.emit()
print(self.nTests)
start = 0
for i in range(self.nTests):
self.MoLFlag = False
j = i + 1
print("start", i)
# create the frequency for the test
chunk_freq = Hearing.generateRndFreq(0, 10000)
#create chunks as generator
for chunk, volume in HTObj.test_function(chunk_freq):
# play chunk of the audio
self.request_playchunk.emit(chunk, 2, HTObj) # this is my current method, by using the signals and slots
# Hearing.playTone(chunk, HTObj.frequencySample, num_channels=2)^# previously I tried something like this, which resulted in the same behavior
print(volume)
if self.MoLFlag:
print(self.MoLFlag)
break
self.progress.emit(j)
self.changeButtonStatus.emit(True)
self.finished.emit()
#pyqtSlot(np.ndarray, int, Hearing.MusicReactor)
def sendAudio2queue(self, chunk, channels, HTObj):
Hearing.playTone(chunk, HTObj.frequencySample, num_channels=channels)
If somebody could take I look I would be very gratefull. I would really like to understand why this is happening. I believe it has something to do with the thread queue, probably I would need to open a new thread which is in charge of the music while the otherone takes care of the GUI reactions, but still I do not understand why it does not break the loop (with the generator) when I click the "ML_yesButton".
It is not necessary to use threads in this case. The wait_done() method blocks the thread where it is executed so that the application does not terminate before finishing playing the audio.
In this case a QTimer can be used to check if the audio finished playing.
import simpleaudio as sa
import numpy as np
from PyQt5.QtCore import pyqtSignal, QObject, Qt, QTimer
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
class AudioManager(QObject):
started = pyqtSignal()
finished = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self._play_obj = None
self._timer = QTimer(interval=10)
self._timer.timeout.connect(self._handle_timeout)
def start(self, audio_data, num_channels, bytes_per_sample, sample_rate):
self._play_obj = sa.play_buffer(
audio_data, num_channels, bytes_per_sample, sample_rate
)
self._timer.start()
self.started.emit()
def stop(self):
if self._play_obj is None:
return
self._play_obj.stop()
self._play_obj = None
self.finished.emit()
def _handle_timeout(self):
if self._play_obj is None:
return
if not self.running():
self.stop()
def running(self):
return self._play_obj.is_playing()
def create_tone(duration, fs, f):
tt = np.linspace((0, 0), (duration, duration), int(duration * fs), False)
note = np.sin(f * tt * 2 * np.pi)
note *= 32767 / np.max(np.abs(note))
audio = note * (2 ** 15 - 1) / np.max(np.abs(note))
audio = audio.astype(np.int16)
return audio
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.audio_manager = AudioManager()
self.audio_manager.started.connect(self.handle_started)
self.audio_manager.finished.connect(self.handle_finished)
self.button = QPushButton("Start", checkable=True)
self.button.toggled.connect(self.handle_toggled)
lay = QVBoxLayout(self)
lay.addWidget(self.button, alignment=Qt.AlignCenter)
def handle_toggled(self, state):
if state:
frequency = np.random.uniform(low=0, high=10000)
tone = create_tone(60, 1000, frequency)
self.audio_manager.start(tone, 1, 2, 16000)
else:
self.audio_manager.stop()
self.button.setText("Start")
def handle_started(self):
self.button.setChecked(True)
self.button.setText("Stop")
def handle_finished(self):
self.button.setChecked(False)
self.button.setText("Start")
def main():
import sys
app = QApplication(sys.argv)
widget = Widget()
widget.resize(640, 480)
widget.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Why does my CleanScreen function not work?

This is my current project (Python 3.8). Your supposed to be able to draw things on your screen. This is not my full version. Its just for explanation purposes. The problem is that if you run run.py it doesn't clear the screen. Shouldn't the new Frame just push the old one out of frame? Do you know what my problem is?
main.py:
import os
import time
from datetime import datetime
import logging
import ctypes
class ConsoleGameEngine:
def __init__(self, windowWidth, windowHeight):
logging.basicConfig(filename=f'debug\{datetime.now().strftime("%H-%M-%S")}-main.log',level=logging.DEBUG)
self.screenWidth = windowWidth
self.screenHeight = windowHeight
self.var = ""
self.pixel = u"\u2591"#u"\u25A1"
self.lightShade = u"\u2591"
self.mediumShade = u"\u2592"
self.darkShade = u"\u2593"
os.system(f'mode con: cols={self.windowWidth} lines={self.windowHeight}')
"""
SCREEN ACCESS:
self.screen[y][x]
"""
self.clearScreenVar = [[" " for w in range(self.screenWidth)] for h in range(self.screenHeight)]
self.screen = self.clearScreenVar
def clearScreen(self):
"""
for y in range(self.windowHeight):
for x in range(self.windowHeight):
self.screen[y][x] = " "
"""
self.screen = self.clearScreenVar
def drawPixel(self,x,y,shade=u"\u2591"):
try:
self.screen[y][x] = shade
except Exception as e:
logging.warning(datetime.now().strftime("%H:%M:%S~")+str(e)+f"~Failed drawing pixel at x: {x} and/or y: {y}")
def sleep(self, t = 1):
time.sleep(t)
def printScreen(self):
print("".join(["".join(x) for x in self.screen]))
run.py:
from main import ConsoleGameEngine
win = ConsoleGameEngine(120, 40)
x = 0
while True:
win.drawPixel(x,20)
win.printScreen()
win.sleep(0.1)
win.clearScreen()
x += 1

Python is crashing while trying to clear combobox in pyqt5

I started today with qt compiler, so I don't have much experience in building gui. My project is about to create dynamic smart check boxes to define axes and at the end to plot several subplots to a figure.
I tried to create dynamic combo boxes that change every time I change my current selection in the combo box.
The big issue is that it crash every time i try to change a selection in the combo box.
I tried to use .clear() method but it crash every time I clicked on it.
Edit: I changed the code to make producible code. After clicking on "Load Files", you will be able the combo boxes filled. If you will change the combo box "Choose message" for example, the python crash.
The GUI
# ------------------------------------------------- -----
# ---------------------- main.py ------------------- ----
# --------------------------------------------- ---------
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.uic import loadUi
from PyQt5.QtCore import pyqtSlot
import threading , os, subprocess, importlib, platform
# Decode_class = 'MAVLinkBinFileDecoder'
# Module = importlib.import_module(Decode_class)
from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar )
import numpy as np
import random
class MatplotlibWidget(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
loadUi("gui.ui", self)
self.setWindowTitle ( "PyQt5 & Matplotlib Example GUI" )
self.loadfiles = 0
self.first_run = 0
self.progressBar.setProperty("value", 0)
# self.pushButton_load_files.setEnabled(False)
self.pushButton_add_to_graph.setEnabled(False)
self.pushButton_choose_xml_file.clicked.connect(self.open_xml_FileNamesDialog)
self.pushButton_choose_bin_files.clicked.connect(self.open_bin_FileNamesDialog)
self.pushButton_load_files.clicked.connect(self.load_files)
self.comboBox_choose_file.currentIndexChanged.connect(self.selectionchange_file)
self.comboBox_message.currentIndexChanged.connect(self.selectionchange_message)
self.comboBox_system_id.currentIndexChanged.connect(self.selectionchange_system_id)
self.pushButton_save_plot.clicked.connect(self.update_graph)
self.file_to_graph_demo = [({'HEARTBEAT':[{'type':[12],'autopilot':[0]},{'type':[2,2,0],'autopilot':[0,0,0]}], 'CHAMBER_STATUS':[{'time_boot_ms':[1,1,1], 'chamber_num':[1,2,3]}], 'ATTITUDE':[{'test':[0,0,0,],'check':[1,1,1]}, {'test':[0,0,0,],'check':[1,1,1]}, 0 , 0, {'test':[0,0,0,],'check':[1,1,1]}]},'test')]
self.addToolBar(NavigationToolbar(self .MplWidget.canvas, self))
#pyqtSlot()
def open_xml_FileNamesDialog(self):
self.loadfiles += 1
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
self.filename, _ = QFileDialog.getOpenFileNames(self, "QFileDialog.getOpenFileNames()", "",
"Xml Files (*.xml)", options=options)
if self.loadfiles == 2:
self.pushButton_load_files.setEnabled(True)
self.pushButton_choose_xml_file.setVisible(False)
#pyqtSlot()
def open_bin_FileNamesDialog(self):
self.loadfiles += 1
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
self.list_of_file_paths, _ = QFileDialog.getOpenFileNames(self, "QFileDialog.getOpenFileNames()", "",
"Bin Files (*.bin)", options=options)
if self.loadfiles == 2:
self.pushButton_load_files.setEnabled(True)
self.pushButton_choose_bin_files.setVisible(False)
#pyqtSlot()
def load_files(self):
# parse = Module.Logic_bin_to_mat_parser(self.filename[0])
# parse.generate_dialect_from_xml() # Run Mavgenerate xml function
# value = 19
# self.progressBar.setProperty("value", value)
# self.file_to_graph = []
# for path in self.list_of_file_paths: # Parse and create Matlab from each bin file
# parse.decode_messages(path)
# parse.create_dictionary_of_amount_of_messages_by_type()
# parse.parse_bin_to_mat()
# self.file_to_graph.append((parse.save, parse.file_base_name))
# parse.convert_parse_dictionary_to_mat()
# value += (100 - 20) / len(self.list_of_file_paths)
# self.progressBar.setProperty("value", value)
# value = 100
# self.progressBar.setProperty("value", value)
# self.pushButton_load_files.setVisible(False)
# self.progressBar.setVisible(False)
for option in self.file_to_graph_demo:
self.comboBox_choose_file.addItem(option[1])
#pyqtSlot()
def selectionchange_file(self):
self.first_run += 1
combobox_enty = self.comboBox_choose_file.currentText()
self.file_idx = self.comboBox_choose_file.findText(combobox_enty)
list_of_messages = []
for message in self.file_to_graph_demo[self.file_idx][0].items():
list_of_messages.append(message[0])
if self.first_run >= 1:
self.comboBox_message.clear()
self.comboBox_message.addItems(list_of_messages)
#pyqtSlot()
def selectionchange_message(self):
self.first_run += 1
self.combobox_entry_message = self.comboBox_message.currentText()
self.message_idx = self.comboBox_message.findText(self.combobox_entry_message)
list_of_system_ids = []
count = 0
for idx, system_id in enumerate(self.file_to_graph_demo[self.file_idx][0][self.combobox_entry_message]):
if system_id != 0:
count += 1
list_of_system_ids.append(str(idx+1))
if self.first_run >= 2:
self.comboBox_system_id.clear()
self.comboBox_system_id.addItems(list_of_system_ids)
#pyqtSlot()
def selectionchange_system_id(self):
self.combobox_entry_system_id = int(self.comboBox_system_id.currentText())-1
self.system_id_idx = self.comboBox_system_id.findText(str(self.combobox_entry_system_id))
for field in self.file_to_graph_demo[self.file_idx][0][self.combobox_entry_message][self.system_id_idx]:
self.comboBox_y_axis.addItem(field)
self.comboBox_x_axis.addItem(field)
def update_graph(self):
fs = 500
f = random.randint(1, 100)
ts = 1 / fs
length_of_signal = 100
t = np . linspace (0, 1, length_of_signal )
cosinus_signal = np . cos ( 2 * np . pi * f * t )
sinus_signal = np . sin ( 2 * np . pi * f * t )
self.MplWidget.canvas.axes.clear()
self.MplWidget.canvas.axes.plot(t,cosinus_signal)
self.MplWidget.canvas.axes.plot(t,sinus_signal)
self.MplWidget.canvas.axes.legend(('cosinus', 'sinus'), loc='upper right')
self.MplWidget.canvas.axes.set_title(' Cosinus - Sinus Signal')
self.MplWidget.canvas.draw()
if __name__ == '__main__':
app=QApplication([])
app.setStyle('Fusion')
window=MatplotlibWidget()
window.show()
app.exec_()
Your issue seems to be in MatplotlibWidget.selectionchange_system_id(). You are trying to cast the current text of self.comboBox_system_id to an int, but this will cause an exception when the current text can't be converted. This is the case just after self.comboBox_system_id is cleared because at that point the current text of the combi box is an empty string. The easiest way to get around this is to test if the current text can be cast to an integer first before continuing, i.e.
def selectionchange_system_id(self):
if self.comboBox_system_id.currentText().isdigit():
self.combobox_entry_system_id = int(self.comboBox_system_id.currentText())-1
...

PYQT5 Physics Calculator

I am making a physics calculator that takes values from the person and uses a calculation to show the answer. the problem is that when i press submit to take the values and save them as variable and show a button to show the answer, the app closes and sublime text shows REPL closed. i have no idea why. please help
import sys
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QToolTip , QCheckBox, QLCDNumber,QLineEdit,QInputDialog#just compile the modules like this
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel
def ObjectDensity():
dflabel = QLabel("Please Enter Density of Fluid: ",w)
dflabel.move(25,220)
dflabel.show()
dfte = QLineEdit(w)
dfte.move(25,260)
dfte.show()
Weight2 = QLabel("Please Enter Weight:",w)
Weight2.move(25,300)
Weight2.show()
Wte = QLineEdit(w)
Wte.move(25,340)
Wte.show()
AIW2 = QLabel("Enter Apperent Immersed Weight: ",w)
AIW2.move(25,380)
AIW2.show()
aiwte = QLineEdit(w)
aiwte.move(25,420)
aiwte.show()
ansbutton = QPushButton("Submit",w)
ansbutton.move(50,480)
ansbutton.show()
ansbutton.clicked.connect(lambda: f1(dfte,Wte,aiwte,ansdo))
# df1 = dfte.text()
# w2 = Wte.text()
# aiw6 = aiwte.text()
def f1(dfte,Wte,aiwte,ansdo):
df1 = int(dfte.text())
w2 = int(Wte.text())
aiw6 = int(aiwte.text())
# ansdo = ((w2/w2-aiw6)*df1)
# ans4 = int(ansdo)
ans = QPushButton("press to show answer",w)
ans.move(50,250)
ans.show()
ans.clicked.connect(lambda:f2(w2,aiw6,df1))
def f2(w2,aiw6,df1):
ansdo = ((w2/w2-aiw6)*df1)
ans4 = int(ansdo)
answer = QLabel(ans4,w)
answer.move(75,300)
answer.show()
def arch():
l_archimedes = QLabel("Archimedes' Law",w)
l_archimedes.move(25,80)
l_archimedes.show()
l_archimedes2 = QLabel("Density of Object/Density of Fluid = Weight/(Weight - Apparent Immersed Weight)",w)
l_archimedes2.move(25,110)
l_archimedes2.show()
Archimedeslaw = QLabel("What Do You Want to Solve For:",w)
Archimedeslaw.move(25,145)
Archimedeslaw.show()
dop = QPushButton("Density of Object",w)
dop.move(25,160)
dop.show()
dop.clicked.connect(ObjectDensity)
DF = QPushButton("Density of Fluid",w)
DF.move(200,160)
DF.show()
Weight = QPushButton("Weight",w)
Weight.move(375,160)
Weight.show()
AIW = QPushButton("Apperent Immersed Weight",w)
AIW.move(500,160)
AIW.show()
app = QApplication(sys.argv)
w = QWidget()
w.resize(900,600)
w.move(460,0)
w.setWindowTitle("Physics Laws")
L1 = QLabel("Welcome To Physics Laws",w,)
L1.move(25,0)
b1 = QPushButton("Archimedes Law",w)
b1.move(25,45)
b1.clicked.connect(arch)
w. show()
sys.exit(app.exec_())
Try it:
import sys
from PyQt5.QtWidgets import (QWidget, QApplication, QPushButton, QLabel,
QToolTip, QCheckBox, QLCDNumber,
QLineEdit, QInputDialog) # ??? just compile the modules like this
from PyQt5.QtGui import QIcon
def ObjectDensity():
dflabel = QLabel("Please Enter Density of Fluid: ",w)
dflabel.move(25,220)
dflabel.show()
dfte = QLineEdit(w)
dfte.move(25,260)
dfte.show()
Weight2 = QLabel("Please Enter Weight:",w)
Weight2.move(25,300)
Weight2.show()
Wte = QLineEdit(w)
Wte.move(25,340)
Wte.show()
AIW2 = QLabel("Enter Apperent Immersed Weight: ",w)
AIW2.move(25,380)
AIW2.show()
aiwte = QLineEdit(w)
aiwte.move(25,420)
aiwte.show()
ansbutton = QPushButton("Submit",w)
ansbutton.move(50,480)
ansbutton.show()
ansbutton.clicked.connect(lambda: f1(dfte,Wte,aiwte )) #,ansdo)) # <------------------
# df1 = dfte.text()
# w2 = Wte.text()
# aiw6 = aiwte.text()
def f1(dfte,Wte,aiwte): #,ansdo): # <------------------
df1 = int(dfte.text())
w2 = int(Wte.text())
aiw6 = int(aiwte.text())
# ansdo = ((w2/w2-aiw6)*df1)
# ans4 = int(ansdo)
ans = QPushButton("press to show answer", w)
#ans.move(50,250)
ans.move(50, 520) # <------------------
ans.show()
answer.hide() # <------------------
ans.clicked.connect(lambda: f2(w2, aiw6, df1))
def f2(w2, aiw6, df1):
print("def f2(w2=`{}`, \naiw6=`{}`, \ndf1=`{}`):".format(w2, aiw6, df1) )
ansdo = ((w2/w2-aiw6)*df1) # w2/w2 = 1 <--- ???
#ans4 = int(ansdo)
#answer = QLabel(ans4, w)
#answer.move(75,300)
answer.setText(str(ansdo)) # <------------------
answer.show() # <------------------
def arch():
l_archimedes = QLabel("Archimedes' Law",w)
l_archimedes.move(25,80)
l_archimedes.show()
l_archimedes2 = QLabel("Density of Object/Density of Fluid = Weight/(Weight - Apparent Immersed Weight)",w)
l_archimedes2.move(25,110)
l_archimedes2.show()
Archimedeslaw = QLabel("What Do You Want to Solve For:",w)
Archimedeslaw.move(25,145)
Archimedeslaw.show()
dop = QPushButton("Density of Object",w)
dop.move(25,160)
dop.show()
dop.clicked.connect(ObjectDensity)
DF = QPushButton("Density of Fluid",w)
DF.move(200,160)
DF.show()
Weight = QPushButton("Weight",w)
Weight.move(375,160)
Weight.show()
AIW = QPushButton("Apperent Immersed Weight",w)
AIW.move(500,160)
AIW.show()
app = QApplication(sys.argv)
w = QWidget()
w.resize(900,600)
w.move(460,0)
w.setWindowTitle("Physics Laws")
L1 = QLabel("Welcome To Physics Laws",w,)
L1.move(25,0)
b1 = QPushButton("Archimedes Law",w)
b1.move(25,45)
b1.clicked.connect(arch)
answer = QLabel(w) # <------------------
answer.move(50, 550) # <------------------
w. show()
sys.exit(app.exec_())

Categories

Resources