I use the pyqt5.I connect the pushbutton signal to the dididi(). It is supported when I clicked the button it will print the message, but when I click the button, it does not print the message. Why? What can I do to solve it?
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'bank1.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QBasicTimer
from PyQt5.QtGui import QColor, QFontMetrics, QPainter, QPalette
from PyQt5.QtWidgets import (QApplication, QDialog, QLineEdit, QVBoxLayout,
QWidget)
from PyQt5.QtCore import QCoreApplication
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(80, 200, 71, 21))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(Form)
self.pushButton_2.setGeometry(QtCore.QRect(230, 200, 72, 23))
self.pushButton_2.setObjectName("pushButton_2")
self.textEdit = QtWidgets.QTextEdit(Form)
self.textEdit.setGeometry(QtCore.QRect(140, 90, 104, 31))
self.textEdit.setObjectName("textEdit")
self.pushButton.clicked.connect(self.dididi)
self.pushButton_2.clicked.connect(self.dididi)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "RCT"))
self.pushButton.setText(_translate("Form", "连接"))
self.pushButton_2.setText(_translate("Form", "发送"))
def dididi(self):
print("hello world")
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
widget = QWidget(None)
Ui_Form().setupUi(widget)
widget.show()
sys.exit(app.exec_())
pass
Just put #staticmethod above your "dididi()" method.
See explanation about #staticmethod #classmethod and normal methods.
#staticmethod
def dididi():
print("hello world")
If you don't want to loose the context (the self) then you could do it this way:
Instead of directly connecting the clicked event to your method, in tour setupUi you create an internal function and you connect the clicked event to it. This would do the trick as you still have access to the self object at this context:
def clicked():
self.dididi()
self.pushButton.clicked.connect(clicked)
This way, you can still define your dididi function as a normal method and use local variables of your class via the self argument.
Related
Good afternoon. I'm trying to run an application in a thread that will run a long process, but so that I have control over this process so that I can interrupt the application on a button and then continue. Simulation of the application while just reading the save file (left for example), however, the application crashes in the same version of its writing.
Here is my appearance file:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'StartForm.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# 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
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 643)
MainWindow.setMinimumSize(QtCore.QSize(400, 500))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton_Update_BFO = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_Update_BFO.setMinimumSize(QtCore.QSize(0, 30))
self.pushButton_Update_BFO.setCheckable(True)
self.pushButton_Update_BFO.setObjectName("pushButton_Update_BFO")
self.verticalLayout.addWidget(self.pushButton_Update_BFO)
self.plainTextEditLogger = QtWidgets.QPlainTextEdit(self.centralwidget)
self.plainTextEditLogger.setStyleSheet("QPlainTextEdit\n"
"{\n"
" background-color: palette(base);\n"
" border-style:solid;\n"
" border-width: 1px;\n"
" border-radius: 3px;\n"
" border-color: #D0D0D0;\n"
"}")
self.plainTextEditLogger.setObjectName("plainTextEditLogger")
self.verticalLayout.addWidget(self.plainTextEditLogger)
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.verticalLayout.addWidget(self.progressBar)
MainWindow.setCentralWidget(self.centralwidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 22))
self.menuBar.setObjectName("menuBar")
self.menu = QtWidgets.QMenu(self.menuBar)
self.menu.setObjectName("menu")
MainWindow.setMenuBar(self.menuBar)
self.menuBar.addAction(self.menu.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_Update_BFO.setText(_translate("MainWindow", "Обновить список ссылок на bfo.nalog.ru"))
self.menu.setTitle(_translate("MainWindow", "Настройки"))
Here is my main file:
import sys
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QCoreApplication
import StartForm
import FormClasses
import need_Classes
def main():
app = QtWidgets.QApplication(sys.argv)
window = FormClasses.ExampleApp()
window.show()
app.exec_()
if __name__ == '__main__':
main()
And here is the problematic part:
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QCoreApplication
import StartForm
import main
import sys
import time
import threading
from threading import Lock
import datetime
from dateutil.parser import parse
from datetime import date#, datetime
import urllib3.contrib.pyopenssl
import main
import need_Classes
class ExampleApp(QtWidgets.QMainWindow, StartForm.Ui_MainWindow):
def __init__(self):
super().__init__()
self.count=0
self.setupUi(self)
self.pushButton_Update_BFO.clicked.connect(self.start_update_Update_BFO)
self.progressBar.setMinimum(1)
self.progressBar.setValue(1)
def main_update_Update_BFO(self):
#urllib3.contrib.pyopenssl.inject_into_urllib3()
self.plainTextEditLogger.clear()
self.progressBar.setValue(1)
try:
with open('save_update_Update_BFO.json', 'w', encoding="utf-8") as save_f:
self.save =need_Classes.save_update_Update_BFO(save_f)
save_f.close()
print("Retrieve recent saves\nSave successfully received")
except Exception as exc:
self.print("Retrieving saves:\nError reading saves!" + str(exc))
return
print("Hi!")
def ticker(self, event):
while event.is_set():
self.main_update_Update_BFO()
time.sleep(1)
def start_update_Update_BFO(self):
if self.pushButton_Update_BFO.isChecked():
self.event = threading.Event()
self.event.set()
self.t1 = threading.Thread(target=self.ticker, args=(self.event,),)# daemon=True)
self.t1.start()
#self.t1.join()
else:
self.event.clear()
# t1.join()
Accidentally found that the problematic line is: #urllib3.contrib.pyopenssl.inject_into_urllib3()
If this line is uncommented, the program will crash.
The second question is that I can't figure out if it's necessary to use daemon=True in threads, and also, after starting the thread, if self.t1.join() should be performed
If I type these things back into when, I lose control of the form and the button.
I am trying to use keyPressEvent in a mainwindow I generated with QtDesigner but no key press is detected by my program. Here is my code
The QtDesigner generated class is MainWindowUI.
class MainWindow(QMainWindow,MainWindowUI.Ui_MainWindow):
def __init__(self, translator,parent=None):
QMainWindow.__init__(self, parent=parent)
#super(MainWindow,self).__init__(parent)
self.setupUi(self)
self.translator=translator
self.completeGUI()
def completeGUI(self):
self.setConnections()
self.set_line_edit_validators()
self.category_combo.insertSeparator(4)
self.category_combo.insertSeparator(8)
self.type_conjug_combo.insertSeparator(3)
self.type_conjug_combo.insertSeparator(6)
#self.type_conjug_combo.setItemData( 0, QtGui.QColor('red'), QtCore.Qt.ForegroundRole )
self.save_button.clicked.connect(self.fileSave)
self.category_label.hide()
self.category_combo.hide()
self.type_conjug_label.hide()
self.type_conjug_combo.hide()
self.grammar_combo.setStyleSheet("color:red")
self.category_combo.setStyleSheet("color:red;")
self.type_conjug_combo.setStyleSheet("color:red;")
self.palat_combo.setStyleSheet("color:red;")
self.accent_combo.setStyleSheet("color:red;")
self.terme_edit.setStyleSheet("border: 2px solid red;")
print("completeGUI is over")
def keyPressEvent(self, e):
print(e.key())
I had a look at various answers to analog question on this forum but I could not manage to have it working.
Thank you for help.
HERE IS A MINIMAL EXAMPLE THAT REPRODUCES THE TROUBLE
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication
import sys
from view.NewMainWindow import NewMainWindow
if __name__=='__main__':
app = QApplication(sys.argv)
translator = QtCore.QTranslator()
app.installTranslator(translator)
mainWindow = NewMainWindow(translator)
NewMainWindow.show(mainWindow)
#sys.exit(app.exec_())
current_exit_code=app.exec_()
app=None
AND THE NEWMAINWINDOW
from PyQt5.QtWidgets import QMainWindow
from gen import NewMainWindowUI
class NewMainWindow(QMainWindow,NewMainWindowUI.Ui_MainWindow):
def __init__(self,translator, parent=None):
super(NewMainWindow,self).__init__(parent)
self.setupUi(self)
print('init completed')
def keyPressEvent(self, e):
print('event detected')
print(e.key())
THE GENERATED INTERFACE
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'src/designer/newmainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.13.1
#
# WARNING! 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(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(130, 110, 113, 36))
self.lineEdit.setObjectName("lineEdit")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 29))
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_())
I usually avoid calling a keyPressEvent from both the central widget and the main window, because, as #musicamante said, one could be "consuming" the other. Especially if you plan on switching between multiple central widgets.
You should instead create a slot on a QMainWindow object connected to the central widget's keyPressEvent (but name it something else, like onKeyPressEvent or something) and then you emit the event from inside the MainWindow's keyPressEvent, something like this:
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtGui import QKeyEvent
class MainWindow(QMainWindow):
key_pressed = pyqtSignal(QKeyEvent)
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
central_widget = NewWindow()
self.key_pressed.connect(central_widget.onKeyPressEvent)
self.setCentralWidget(central_widget)
...
def keyPressEvent(self, event: QKeyEvent) -> None:
self.key_pressed.emit(event)
return super().keyPressEvent(event)
class NewWindow(QWidget):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
...
#pyqtSlot(QKeyEvent)
def onKeyPressEvent(self, event: QKeyEvent) -> None:
print(event.key())
return
Im trying to build a temperature monitor using pyqt5 on a raspberry pi 3 with ds18b20 sensors attached. I am pretty new to python and pyqt5.
The Gui file (frameless.py) was developed with QT 4 designer. The Gui should serve as a basic example for a more enviromental sensors (e.g pH EC etc.) to be implemented. The actual code (runframeless.py) is shown below.
I am well aware that is is best to use threads (or Multithreading) if more senosor data are to be read at the same time, but currently I am stuck in a pretty simple problem.
Problem:
The temperature is shown in the textlabel, but the temperature value in def read_temp(self) is not updated.
Question:
Can anyone explain why it is not updated and help me getting the code right so that the temperature value shown in the gui is changed when the temperature acually changes?
runframeless.py
# -*- coding: utf-8 -*-
# file: runframeless.py)
#-create a skeleton class(es) for Raspberry Pi GUI-
# need this
import sys
import time
import datetime
import os
import glob
#----This gets the Qt stuff------------------------
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLabel
# Import QtCreator/qtdesigner file
import frameless
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '10*')[0]
device_file = device_folder + '/w1_slave'
#-------------------------------------------------
#----class(es) for our Raspberry Pi GUI-----------
#-------------------------------------------------
class MainWindow(QMainWindow, frameless.Ui_MainWindow):
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self) # gets defined in the UI file
self.label.setText(str(self.read_temp()))
self.timer = QtCore.QTimer(self)
self.timer.setInterval(1000)
self.timer.timeout.connect(self.read_temp)
self.timer.start()
def read_temp(self):
f = open(device_file, 'r')
lines = f.readlines()
f.close()
time.sleep(.1)
while lines[0].strip()[-3:] != 'YES':
time.sleep(.1)
#lines = self.read_temp()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
return temp_c
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
file: frameless.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'frameless.ui'
#
# Created: Tue Feb 27 17:31:49 2018
# by: PyQt5 UI code generator 5.3.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.setWindowFlags(Qt.FramelessWindowHint) # frameless
MainWindow.resize(800, 480)
MainWindow.setStyleSheet("background:rgb(0, 0, 0);")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setStyleSheet("")
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(660, 430, 101, 31))
self.pushButton.setStyleSheet("background: rgb(255, 255, 255) ")
self.pushButton.setObjectName("pushButton")
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(10, 170, 751, 41))
self.widget.setObjectName("widget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_2 = QtWidgets.QLabel(self.widget)
self.label_2.setStyleSheet("background: rgb(255, 255, 255) ")
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
self.label = QtWidgets.QLabel(self.widget)
self.label.setStyleSheet("background: rgb(255, 255, 255) ")
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.pushButton.clicked.connect(MainWindow.close)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "exit"))
self.label_2.setText(_translate("MainWindow", "Ds18B20-sensor"))
self.label.setText(_translate("MainWindow", "TextLabel"))
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_())
When debugging code, it pays to logically step through how the program works.
Firstly, this line self.label.setText(str(self.read_temp())) runs once as it is in the __init__ method. This calls the self.read_temp() method which returns the temperature and places it in the text box.
Next, you create a QTimer in the __init__ method, which calls self.read_temp() every second. So when the timer triggers every second, self.read_temp is run, the temperature is read out, and returned to whatever internal code the QTimer uses to call your method.
At this point the QTimer throws away the return value because it doesn't want it, can't use it, etc.
As you can probably now see, the reason why it doesn't update is because you have never told it to update.
I would suggest adding the line self.label.setText(str(temp_c)) prior to the return temp_c line in order to update the label from the code that runs every second.
I made a repository in github that contain a code in python and PyQt5 for temperature control (monitoring) whith raspberry Pi and ds18b20 sensor
You can use that by following link
https://github.com/salarshekari/ds18b20-raspberry-pyqt5
please do not forget star if you like that
when I converted the .ui file from Qt to .py, I try to run it but it does not show the gui I created with Qt. I have tried adding
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
screen = Ui_Form()
screen.show()
sys.exit(app.exec_())
at the end of my code but it returns an error:
Traceback (most recent call last): File "C:\Path***.py", line 12,
in
class Ui_Form(object): File "C:\Path****.py", line 355, in Ui_Form
screen = Ui_Form() NameError: name 'Ui_Form' is not defined
This is my code
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(490, 264)
*insert some more generated codes here*
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.Load_4.setText(_translate("Form", "Load"))
self.Load_5.setText(_translate("Form", "Load"))
*insert some more generated codes here*
You should not add more code to the file generated by the pyuic tool. Instead, subclass the Ui class that is in the file. By doing this you can change the gui and use the pyuic tool again without losing all of the code you wrote. It would look like this:
(in another file)
from pyuic_generated_file import UiForm
class MainWindow(QtWidgets.QMainWindow, Ui_Form):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setupUi(self)
# code here
Then in your main method:
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
I created a GUI with the hepl of QtCreator-->QtDesigner. The file is called mainwindow.ui. With the help of pyuic5 I created mainwindow.py
pyuic5 mainwindow.ui > mainwindow.py
and this is how it looks like:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.frame = QtWidgets.QFrame(self.centralWidget)
self.frame.setGeometry(QtCore.QRect(30, 20, 341, 191))
self.frame.setFrameShape(QtWidgets.QFrame.Panel)
self.frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.frame.setObjectName("frame")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 23))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
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"))
and wanted to import that in my main script main.py:
#!/usr/bin/env python3
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from mainwindow import *
import sys
def main():
app = QApplication(sys.argv)
instance = Ui_MainWindow()
#instance.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
...but nothing happens when I run it. How should my main.py look like to use that gui module?
Ok, I figured it myself. To use a GUI file in Python, created in QtCreator called mainwindow.py, my main.py should look something like this:
#!/usr/bin/env python3
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from mainwindow import *
import sys
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.show()
def main():
app = QApplication(sys.argv)
instance = Main()
#instance.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
My class Main(QMainWindow) must have a parent QMainWindow and not QWidget because QWidget doesn't have setCentralWidget method which is needed in mainwindow.py.