Страницы

Поиск по вопросам

вторник, 31 марта 2020 г.

Обновление виджета QLabel PyQt5

#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_())

Комментариев нет:

Отправить комментарий