Remove PyQt5.Qwt dependency from the GUI client
PyQt5.Qwt isn't pip-installable; it only existed via the apt package python3-pyqt5.qwt, so pip-installing client/requirements.txt's plain PyPI PyQt5 always crashed with "No module named 'PyQt5.Qwt'". Qwt was only used for 3 QwtSlider widgets (Slider_temp_soll, Slider_pwr_soll, Slider_speed_soll). Swap them for stock QSlider in brewpi.ui, regenerate brewpi_win.py via pyuic5, and update brewpi_gui.py's setLowerBound/setUpperBound calls to QSlider's integer-only setMinimum/setMaximum. The GUI now runs from a plain `pip install -r client/requirements.txt` venv with no system PyQt5 packages required. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -80,7 +80,7 @@ commands back on (e.g. `{"TempCtrl": {"Soll": {"Temp": 65}}}`).
|
||||
- Python 3.8+
|
||||
- Server (`brewpi/requirements.txt`): `numpy`, `scipy`, `websockets`, `dpath`,
|
||||
and `pyserial`/`spidev` if using real hardware backends.
|
||||
- Client (`client/requirements.txt`): `PyQt5` (and `PyQt5.Qwt` for plotting).
|
||||
- Client (`client/requirements.txt`): `PyQt5`.
|
||||
|
||||
Install with:
|
||||
|
||||
|
||||
+21
-46
@@ -517,7 +517,7 @@
|
||||
<property name="title">
|
||||
<string>Controller</string>
|
||||
</property>
|
||||
<widget class="QwtSlider" name="Slider_temp_soll">
|
||||
<widget class="QSlider" name="Slider_temp_soll">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
@@ -526,20 +526,14 @@
|
||||
<height>281</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="lowerBound">
|
||||
<double>0.000000000000000</double>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="upperBound">
|
||||
<double>100.000000000000000</double>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="scaleMaxMajor">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="scaleMaxMinor">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="scaleStepSize">
|
||||
<double>0.000000000000000</double>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_6">
|
||||
@@ -600,7 +594,7 @@
|
||||
<property name="title">
|
||||
<string>Heater</string>
|
||||
</property>
|
||||
<widget class="QwtSlider" name="Slider_pwr_soll">
|
||||
<widget class="QSlider" name="Slider_pwr_soll">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
@@ -609,20 +603,14 @@
|
||||
<height>281</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="lowerBound">
|
||||
<double>0.000000000000000</double>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="upperBound">
|
||||
<double>100.000000000000000</double>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="scaleMaxMajor">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="scaleMaxMinor">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="scaleStepSize">
|
||||
<double>0.000000000000000</double>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="checkbox_heater_activate">
|
||||
@@ -674,7 +662,7 @@
|
||||
<string>Activate</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QwtSlider" name="Slider_speed_soll">
|
||||
<widget class="QSlider" name="Slider_speed_soll">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>40</x>
|
||||
@@ -683,20 +671,14 @@
|
||||
<height>281</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="lowerBound">
|
||||
<double>0.000000000000000</double>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="upperBound">
|
||||
<double>100.000000000000000</double>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="scaleMaxMajor">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="scaleMaxMinor">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="scaleStepSize">
|
||||
<double>0.000000000000000</double>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_11">
|
||||
@@ -3745,13 +3727,6 @@
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QwtSlider</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qwt_slider.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<designerdata>
|
||||
|
||||
@@ -105,7 +105,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
if 'Temp' in submsg:
|
||||
self.lcdNumber_temp_soll.display(str(submsg['Temp']))
|
||||
if self.slider_temp_soll_initial_update:
|
||||
self.Slider_temp_soll.setValue(submsg['Temp'])
|
||||
self.Slider_temp_soll.setValue(int(round(submsg['Temp'])))
|
||||
self.slider_temp_soll_initial_update = False
|
||||
if 'Rate' in submsg:
|
||||
subsubmsg = submsg['Rate']
|
||||
@@ -133,14 +133,14 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
elif "Power" in key:
|
||||
self.lcdNumber_power_heater.display(msg['Power'])
|
||||
if self.slider_pwr_initial_update:
|
||||
self.Slider_pwr_soll.setValue(msg['Power'])
|
||||
self.Slider_pwr_soll.setValue(int(round(msg['Power'])))
|
||||
self.slider_pwr_initial_update = False
|
||||
elif "Capabilities" in key:
|
||||
submsg = msg['Capabilities']
|
||||
if "Power" in submsg:
|
||||
submsg = submsg['Power']
|
||||
self.Slider_pwr_soll.setLowerBound(submsg['Min'])
|
||||
self.Slider_pwr_soll.setUpperBound(submsg['Max'])
|
||||
self.Slider_pwr_soll.setMinimum(int(submsg['Min']))
|
||||
self.Slider_pwr_soll.setMaximum(int(submsg['Max']))
|
||||
|
||||
def on_stirrer_changed(self, msg):
|
||||
print("on_stirrer_changed {}".format(msg))
|
||||
@@ -151,14 +151,14 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
self.checkbox_stirrer_activate_initial_update = False
|
||||
elif "Speed" in key:
|
||||
if self.slider_speed_initial_update:
|
||||
self.Slider_speed_soll.setValue(msg['Speed'])
|
||||
self.Slider_speed_soll.setValue(int(round(msg['Speed'])))
|
||||
self.slider_speed_initial_update = False
|
||||
elif "Capabilities" in key:
|
||||
submsg = msg['Capabilities']
|
||||
if "Power" in submsg:
|
||||
submsg = submsg['Power']
|
||||
self.Slider_speed_soll.setLowerBound(submsg['Min'])
|
||||
self.Slider_speed_soll.setUpperBound(submsg['Max'])
|
||||
self.Slider_speed_soll.setMinimum(int(submsg['Min']))
|
||||
self.Slider_speed_soll.setMaximum(int(submsg['Max']))
|
||||
|
||||
def closeEvent(self, event):
|
||||
print("Exitting gracefully!")
|
||||
|
||||
+16
-21
@@ -2,9 +2,10 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'brewpi.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.14.1
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
from PyQt5.Qwt import *
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@@ -189,13 +190,11 @@ class Ui_MainWindow(object):
|
||||
self.groupBox_2.setSizePolicy(sizePolicy)
|
||||
self.groupBox_2.setMinimumSize(QtCore.QSize(0, 0))
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.Slider_temp_soll = QwtSlider(self.groupBox_2)
|
||||
self.Slider_temp_soll = QtWidgets.QSlider(self.groupBox_2)
|
||||
self.Slider_temp_soll.setGeometry(QtCore.QRect(20, 70, 63, 281))
|
||||
self.Slider_temp_soll.setLowerBound(0.0)
|
||||
self.Slider_temp_soll.setUpperBound(100.0)
|
||||
self.Slider_temp_soll.setScaleMaxMajor(7)
|
||||
self.Slider_temp_soll.setScaleMaxMinor(3)
|
||||
self.Slider_temp_soll.setScaleStepSize(0.0)
|
||||
self.Slider_temp_soll.setMinimum(0)
|
||||
self.Slider_temp_soll.setMaximum(100)
|
||||
self.Slider_temp_soll.setOrientation(QtCore.Qt.Vertical)
|
||||
self.Slider_temp_soll.setObjectName("Slider_temp_soll")
|
||||
self.label_6 = QtWidgets.QLabel(self.groupBox_2)
|
||||
self.label_6.setGeometry(QtCore.QRect(10, 370, 67, 31))
|
||||
@@ -214,13 +213,11 @@ class Ui_MainWindow(object):
|
||||
self.horizontalLayout.addWidget(self.groupBox_2)
|
||||
self.groupBox = QtWidgets.QGroupBox(self.horizontalTabWidgetPage1)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.Slider_pwr_soll = QwtSlider(self.groupBox)
|
||||
self.Slider_pwr_soll = QtWidgets.QSlider(self.groupBox)
|
||||
self.Slider_pwr_soll.setGeometry(QtCore.QRect(10, 70, 81, 281))
|
||||
self.Slider_pwr_soll.setLowerBound(0.0)
|
||||
self.Slider_pwr_soll.setUpperBound(100.0)
|
||||
self.Slider_pwr_soll.setScaleMaxMajor(7)
|
||||
self.Slider_pwr_soll.setScaleMaxMinor(3)
|
||||
self.Slider_pwr_soll.setScaleStepSize(0.0)
|
||||
self.Slider_pwr_soll.setMinimum(0)
|
||||
self.Slider_pwr_soll.setMaximum(100)
|
||||
self.Slider_pwr_soll.setOrientation(QtCore.Qt.Vertical)
|
||||
self.Slider_pwr_soll.setObjectName("Slider_pwr_soll")
|
||||
self.checkbox_heater_activate = QtWidgets.QCheckBox(self.groupBox)
|
||||
self.checkbox_heater_activate.setGeometry(QtCore.QRect(30, 370, 81, 31))
|
||||
@@ -235,13 +232,11 @@ class Ui_MainWindow(object):
|
||||
self.checkbox_stirrer_activate = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
self.checkbox_stirrer_activate.setGeometry(QtCore.QRect(40, 370, 81, 23))
|
||||
self.checkbox_stirrer_activate.setObjectName("checkbox_stirrer_activate")
|
||||
self.Slider_speed_soll = QwtSlider(self.groupBox_3)
|
||||
self.Slider_speed_soll = QtWidgets.QSlider(self.groupBox_3)
|
||||
self.Slider_speed_soll.setGeometry(QtCore.QRect(40, 70, 63, 281))
|
||||
self.Slider_speed_soll.setLowerBound(0.0)
|
||||
self.Slider_speed_soll.setUpperBound(100.0)
|
||||
self.Slider_speed_soll.setScaleMaxMajor(7)
|
||||
self.Slider_speed_soll.setScaleMaxMinor(3)
|
||||
self.Slider_speed_soll.setScaleStepSize(0.0)
|
||||
self.Slider_speed_soll.setMinimum(0)
|
||||
self.Slider_speed_soll.setMaximum(100)
|
||||
self.Slider_speed_soll.setOrientation(QtCore.Qt.Vertical)
|
||||
self.Slider_speed_soll.setObjectName("Slider_speed_soll")
|
||||
self.label_11 = QtWidgets.QLabel(self.groupBox_3)
|
||||
self.label_11.setGeometry(QtCore.QRect(0, 30, 141, 31))
|
||||
@@ -1277,7 +1272,7 @@ class Ui_MainWindow(object):
|
||||
self.label_5.setText(_translate("MainWindow", "Power [W]"))
|
||||
self.label_7.setText(_translate("MainWindow", "State"))
|
||||
self.label_state.setText(_translate("MainWindow", "State"))
|
||||
self.plainTextUri.setPlainText(_translate("MainWindow", "ws://localhost:8765"))
|
||||
self.plainTextUri.setPlainText(_translate("MainWindow", "ws://brewpi:8765"))
|
||||
self.label_8.setText(_translate("MainWindow", "Host"))
|
||||
self.menu_File.setTitle(_translate("MainWindow", "&File"))
|
||||
self.menu_Help.setTitle(_translate("MainWindow", "&Help"))
|
||||
|
||||
Reference in New Issue
Block a user