#python #pyqt5
Здравствуйте. Подскажите как обновить виджет с фотографией - QLabel, библиотеки PyQt5 в python 3.6. Смысл заключается в том, что сокет получает bytes фотографии и нужно при каждом получении обновлять фотографию в окне gui. Код gui: import io from PIL import Image from PIL.ImageQt import ImageQt from PyQt5.QtGui import * from PyQt5 import QtWidgets, QtGui import sys class Window(QtWidgets.QWidget): def __init__(self, ): super().__init__() self.resize(800, 600) self.wiget_photo() def wiget_photo(self): self.img = Image.open(io.BytesIO(photo)) #открытие bytes фото (библиотека PIL) self.qimage = ImageQt(self.img) self.pixmap = QPixmap.fromImage(self.qimage) #формотирование bytes фото в pixmap для setPixmap self.lbl = QtWidgets.QLabel(self) self.pix = QtGui.QPixmap(self.pixmap) self.lbl.setPixmap(self.pix) self.lbl.resize(500, 500) #размер виджета self.lbl.move(50, 50) #расположение виджета self.show() if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) GUI = Window() sys.exit(app.exec_())
Ответы
Ответ 1
Чтобы показывать картинки, полученные через сокет, можно принимать картинки в фоновом потоке, используя простой сокет сервер (в общем случае, Qt позволяет сервер в цикле событий запустить в том же потоке) и получив картинку послать сигнал, чтобы отобразить картинку в GUI: #!/usr/bin/env python3 import socket import sys from PyQt5.QtCore import QObject, QThread, pyqtSignal from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import QApplication, QLabel def server(signal_obj, host='localhost', port=29044): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # reuse sockets in TIME_WAIT state sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind((host, port)) sock.listen() signal_obj.server_started.emit(host, port) while True: conn, addr = sock.accept() # XXX add error handling with conn, conn.makefile('rb') as file: # one client at a time signal_obj.got_image.emit(addr, file.read()) # image received class SignalObject(QObject): server_started = pyqtSignal(str, int) # host, port got_image = pyqtSignal(tuple, bytes) # addr, image data def receive_images(self): server(self) class ImageViewer(QLabel): def on_server_start(self, host, port): self.setText(f'Waiting for images on {host}:{port}') self.adjustSize() def on_received_image(self, addr, image_data): self.setWindowTitle('Image from {}:{}'.format(*addr)) pixmap = QPixmap() pixmap.loadFromData(image_data) self.setPixmap(pixmap) self.resize(pixmap.width(), pixmap.height()) app = QApplication(sys.argv) # run server in a background thread thread = QThread() signal_obj = SignalObject() # communicate with GUI using signals signal_obj.moveToThread(thread) thread.started.connect(signal_obj.receive_images) image_viewer = ImageViewer() image_viewer.setWindowTitle('Show Images from socket') signal_obj.server_started.connect(image_viewer.on_server_start) signal_obj.got_image.connect(image_viewer.on_received_image) image_viewer.show() thread.start() # start server sys.exit(app.exec()) Чтобы послать картинку при запущенном приложении: $ nc localhost 29044 < /path/to/image.png В коде две основных части: server() ожидает по указанному адресу (host, port) новые соединения. Когда клиент подключается, сервер читает данные и публикует их как got_image сигнал: signal_obj.got_image.emit(addr, file.read()) GUI, которое подписано на этот сигнал: signal_obj.got_image.connect(image_viewer.on_received_image) показывает новую картинку, используя Pixmap.loadFromData метод. Отображение картинок на экран PyQt5 доступных как bytes. В Qt у каждого объекта, есть свой поток (thread affinity), чтобы SignalObject.receive_images слот выполнялся в фоновом потоке, используется signal_obj.moveToThread(thread) вызов. Background thread with QThread in PyQt. Не обязательно QThread использовать, посылка сигналов является thread-safe, можно из обычного Питон-потока сигналы посылать, пример кода.Ответ 2
Пример обновлении QLabel при помощи функции setText() раз в секунду. В вашем случае обновление будет при получении фотографии. import sys from PyQt5 import QtWidgets, QtCore class Main(QtWidgets.QWidget): def __init__(self): super().__init__() self.setFixedSize(200, 200) self.setWindowTitle('Test') self.i = 0 self.label = QtWidgets.QLabel() lay = QtWidgets.QVBoxLayout() lay.addWidget(self.label) self.setLayout(lay) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.tick) self.timer.start(1000) def tick(self): self.i += 1 self.label.setText("Значение равно {}".format(self.i)) if self.i == 10: self.label.setText("Подсчет окончен") self.timer.stop() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) main = Main() main.show() sys.exit(app.exec_())
Комментариев нет:
Отправить комментарий