Страницы

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

среда, 26 февраля 2020 г.

Почему не обновляется виджет с чатом QListWidget?

#python #python_3x #pyqt5 #pyqt


Есть такой код, для простоты лишнее не привожу. После авторизации срабатывает метод
getChat и выводится виджет с сообщениями, которые берутся из базы. В другом потоке
отправляются запросы на сервер каждую секунду и в консоли вижу, что нужный словарь
с данными при отправке нового сообщения как и нужно обновляется и возвращается в переменной
rs. Далее пытаюсь перерисовать виджет с сообщениями, наверное это нужно делать в методе
on_request, но не получается. Прошу подсказать, ума не приложу, как это реализовать. 

from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import QThread
import requests
import json
import time

colors = ['#1f3a93', '#26a65b']

class ThreadClass(QThread):
    about_response = QtCore.pyqtSignal(object)

    def __init__(self, url: str):
        super().__init__()
        self.url = url

    def run(self):
        while True:
            try:
                rs = requests.post(self.url)
                self.about_response.emit(rs)

            except Exception as e:
                print('Error:', e)

            finally:
                time.sleep(3)

class MyWindow(QtWidgets.QWidget):

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        self.url_base = 'http://127.0.0.1:5000/'
        self.main_id = 0
        self.res_usr = {}
        self.chat_obj = QtWidgets.QListWidget


        url = self.url_base + 'blog/chat'

        self.thread_class = ThreadClass(url)
        self.thread_class.about_response.connect(self.on_response)
        self.thread_class.start()

        self.title = QtWidgets.QLabel('Авторизация')
        self.title.setAlignment(QtCore.Qt.AlignHCenter)

        self.username = QtWidgets.QLineEdit()
        self.username.setPlaceholderText('Введите логин:')
        self.password = QtWidgets.QLineEdit()
        self.password.setPlaceholderText('Введите пароль:'),
        self.password.setEchoMode(QtWidgets.QLineEdit.Password)
        self.btnLogin = QtWidgets.QPushButton("&OK")

        self.lnkReg = QtWidgets.QPushButton('&Регистрация')

        self.vbox = QtWidgets.QVBoxLayout()
        self.vbox.addWidget(self.title)
        self.vbox.addWidget(self.username)
        self.vbox.addWidget(self.password)
        self.vbox.addWidget(self.btnLogin)
        self.vbox.addWidget(self.lnkReg)

        self.setLayout(self.vbox)
        self.btnLogin.clicked.connect(self.authorisation)
        self.lnkReg.clicked.connect(self.switchToRegistration)

    def on_response(self, rs):
        res_u = rs.text
        res_pst = json.loads(res_u)
        print(res_pst)
        self.chat_obj = QtWidgets.QListWidget(self)
        for key, value in res_pst.items():
            item = QtWidgets.QListWidgetItem(self.chat_obj)
            item.setText(value[0] + ': ' + value[1])
            if value[2] == self.main_id:
                item.setTextAlignment(QtCore.Qt.AlignRight)
                item.setForeground(QtGui.QColor(colors[0]))
            else:
                item.setTextAlignment(QtCore.Qt.AlignLeft)
                item.setForeground(QtGui.QColor(colors[1]))
            self.chat_obj.addItem(value[0] + ': ' + value[1])
        self.chat_obj.repaint()



    def switchToRegistration(self):
        """
        Переключение на регистрацию
        """
        window.resize(300, 200)
        self.clearLayout(self.vbox)

        self.title = QtWidgets.QLabel('Регистрация')
        self.title.setAlignment(QtCore.Qt.AlignHCenter)

        self.username = QtWidgets.QLineEdit()
        self.username.setPlaceholderText('Введите логин:')
        self.password = QtWidgets.QLineEdit()
        self.password.setPlaceholderText('Введите пароль:'),
        self.password.setEchoMode(QtWidgets.QLineEdit.Password)
        self.btnReg = QtWidgets.QPushButton("&OK")

        self.lnkAutor = QtWidgets.QPushButton('&Авторизация')

        self.vbox.addWidget(self.title)
        self.vbox.addWidget(self.username)
        self.vbox.addWidget(self.password)
        self.vbox.addWidget(self.btnReg)
        self.vbox.addWidget(self.lnkAutor)

        self.setLayout(self.vbox)
        self.btnReg.clicked.connect(self.registration)
        self.lnkAutor.clicked.connect(self.switchToAuthorisation)


    def switchToAuthorisation(self):
        """
        Переключение на авторизацию
        """
        window.resize(300, 200)
        self.clearLayout(self.vbox)

        self.title = QtWidgets.QLabel('Авторизация')
        self.title.setAlignment(QtCore.Qt.AlignHCenter)

        self.username = QtWidgets.QLineEdit()
        self.username.setPlaceholderText('Введите логин:')
        self.password = QtWidgets.QLineEdit()
        self.password.setPlaceholderText('Введите пароль:'),
        self.password.setEchoMode(QtWidgets.QLineEdit.Password)
        self.btnAutor = QtWidgets.QPushButton("&OK")

        self.lnkReg = QtWidgets.QPushButton('&Регистрация')

        self.vbox.addWidget(self.title)
        self.vbox.addWidget(self.username)
        self.vbox.addWidget(self.password)
        self.vbox.addWidget(self.btnLogin)
        self.vbox.addWidget(self.lnkReg)

        self.setLayout(self.vbox)
        self.btnAutor.clicked.connect(self.authorisation)
        self.lnkReg.clicked.connect(self.switchToRegistration)


    def authorisation(self):
        """
        Авторизация
        """
        url = self.url_base + 'auth/login'
        data = {'username': self.username.text(), 'password': self.password.text()}
        r = requests.post(url, json=data)

        res_u = r.text
        #print(res_u)
        res_usr = json.loads(res_u)
        #print(res_usr['status'])
        if res_usr['status'] == 'ok':
            self.main_id = res_usr['id']
            #print(self.main_id)
            self.getChat()
        elif res_usr['status'] == 'no':
            self.showError(res_usr)


    def registration(self):
        """
        Регистрация
        """
        url = self.url_base + 'auth/register'
        data = {'username': self.username.text(), 'password': self.password.text()}
        r = requests.post(url, json=data)

        res_u = r.text
        #print(res_u)
        res_usr = json.loads(res_u)
        if res_usr['status'] == 'ok':
            self.switchToAuthorisation()
        elif res_usr['status'] == 'no':
            self.showError(res_usr)


    def clearLayout(self, layout):
        """
        Очистка окошка
        """
        for i in reversed(range(layout.count())):
            layout.itemAt(i).widget().setParent(None)


    def showError(self, res_usr):
        """
        Показать ошибки
        """
        self.label = QtWidgets.QLabel(res_usr['error'])
        self.label.setAlignment(QtCore.Qt.AlignHCenter)
        self.vbox.addWidget(self.label)

    def showSuccess(self, res_usr):
        """
        Показать успех
        """
        self.label = QtWidgets.QLabel(res_usr['success_msg'])
        self.label.setAlignment(QtCore.Qt.AlignHCenter)
        self.vbox.addWidget(self.label)

    def getChat(self):
        window.resize(300, 400)
        self.clearLayout(self.vbox)

        self.label = QtWidgets.QLabel('Чат')
        self.label.setAlignment(QtCore.Qt.AlignHCenter)
        self.vbox.addWidget(self.label)

        url = self.url_base + 'blog/chat'
        r = requests.post(url)
        print(r.status_code, r.reason)
        print(r.request.headers)

        res_u = r.text
        res_pst = json.loads(res_u)
        #print(res_pst)

        self.chat_obj = QtWidgets.QListWidget(self)
        for key, value in res_pst.items():
            item = QtWidgets.QListWidgetItem(self.chat_obj)
            item.setText(value[0] + ': ' + value[1])
            if value[2] == self.main_id:
                item.setTextAlignment(QtCore.Qt.AlignRight)
                item.setForeground(QtGui.QColor(colors[0]))
            else:
                item.setTextAlignment(QtCore.Qt.AlignLeft)
                item.setForeground(QtGui.QColor(colors[1]))
        #self.chat_obj.addItem(value[0] + ': ' + value[1])

        self.vbox.addWidget(self.chat_obj)

        self.message = QtWidgets.QLineEdit()
        self.message.setPlaceholderText('Введите сообщение')
        self.vbox.addWidget(self.message)

        self.btnSend = QtWidgets.QPushButton("&Отправить")
        self.vbox.addWidget(self.btnSend)
        self.btnSend.clicked.connect(self.sendmessage)


    def sendmessage(self):
        """
        Отправка сообщения
        """
        print(self.main_id)
        url = self.url_base + 'blog/create/{}'.format(self.main_id)
        data = {'message': self.message.text()}
        #print(data)
        r = requests.post(url, json=data)

        #print(r.status_code, r.reason)
        #print(r.request.headers)

        res_m = r.text
        #print(res_m)
        res_usr = json.loads(res_m)
        if res_usr['status'] == 'ok':
            self.showSuccess(res_usr)
        elif res_usr['status'] == 'no':
            self.showError(res_usr)

        self.message.clear()


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle("Простой Мессенжер")
    window.resize(300, 200)
    window.show()
    sys.exit(app.exec_())


Вот код серверной части, тот, который отвечает за формирование чата:

from flask import (
Blueprint, flash, g, redirect, render_template, request, url_for
)
from werkzeug.exceptions import abort

from flaskr.auth import login_required
from flaskr.db import get_db
import json

bp = Blueprint('blog', __name__, url_prefix='/blog')


@bp.route('/chat', methods=('GET', 'POST'))
def chat():

    db = get_db()
    posts = db.execute(
        'SELECT p.id, author_id, msg, created, u.username'
        ' FROM post p JOIN user u'
        ' ON u.id = p.author_id'
        ' ORDER BY p.created DESC',
    ).fetchall()
    pst = {}
    for i in posts:
        pst[i['id']] = [i['username'], i['msg'], i['author_id']]
    dc = pst
    dc = json.dumps(dc)
    return dc


@bp.route('/create/', methods=('GET', 'POST'))
def create(main_id):
    if request.method == 'POST':
        msg = request.get_json().get('message')
        error = None

        if not msg:
            error = 'Message is required.'

        if error is not None:
            dc = {'error': error, 'status': 'not'}
            dc = json.dumps(dc)
            return dc
        else:
            db = get_db()
            author_id = main_id
            db.execute(
                'INSERT INTO post (msg, author_id)'
                ' VALUES (?, ?)',
                (msg, author_id)
            )
            db.commit()

            dc = {'success_msg': 'The message successfully sent', 'status': 'ok'}
            dc = json.dumps(dc)
            return dc

    return dc

    


Ответы

Ответ 1



Мои изменения рядом с # TODO:. Главное что сделал -- убрал пересоздание виджета-списка и манипуляции с layout (это можно потом сделать, сейчас это будет мешать) class MyWindow(QtWidgets.QWidget): def __init__(self, parent=None): super().__init__(parent) self.url_base = 'http://127.0.0.1:5000/' self.main_id = 0 self.res_usr = dict() # TODO: # self.chat_obj = QtWidgets.QListWidget url = self.url_base + 'blog/chat' self.thread_class = ThreadClass(url) self.thread_class.about_response.connect(self.on_response) self.thread_class.start() self.title = QtWidgets.QLabel('Авторизация') self.title.setAlignment(QtCore.Qt.AlignHCenter) self.username = QtWidgets.QLineEdit() self.username.setPlaceholderText('Введите логин:') self.password = QtWidgets.QLineEdit() self.password.setPlaceholderText('Введите пароль:'), self.password.setEchoMode(QtWidgets.QLineEdit.Password) self.btnLogin = QtWidgets.QPushButton("&OK") self.lnkReg = QtWidgets.QPushButton('&Регистрация') self.chat_obj = QtWidgets.QListWidget() self.vbox = QtWidgets.QVBoxLayout() self.vbox.addWidget(self.title) self.vbox.addWidget(self.username) self.vbox.addWidget(self.password) self.vbox.addWidget(self.btnLogin) self.vbox.addWidget(self.lnkReg) # TODO: # Пусть пока будет self.vbox.addWidget(self.chat_obj) self.setLayout(self.vbox) self.btnLogin.clicked.connect(self.authorisation) self.lnkReg.clicked.connect(self.switchToRegistration) def on_response(self, rs): # TODO: res_pst = rs.json() # res_u = rs.text # res_pst = json.loads(res_u) print(res_pst) for key, value in res_pst.items(): item = QtWidgets.QListWidgetItem(self.chat_obj) item.setText(value[0] + ': ' + value[1]) if value[2] == self.main_id: item.setTextAlignment(QtCore.Qt.AlignRight) item.setForeground(QtGui.QColor(colors[0])) else: item.setTextAlignment(QtCore.Qt.AlignLeft) item.setForeground(QtGui.QColor(colors[1])) self.chat_obj.addItem(value[0] + ': ' + value[1]) def switchToRegistration(self): """ Переключение на регистрацию """ # TODO: self.resize(300, 200) # self.clearLayout(self.vbox) self.title = QtWidgets.QLabel('Регистрация') self.title.setAlignment(QtCore.Qt.AlignHCenter) self.username = QtWidgets.QLineEdit() self.username.setPlaceholderText('Введите логин:') self.password = QtWidgets.QLineEdit() self.password.setPlaceholderText('Введите пароль:'), self.password.setEchoMode(QtWidgets.QLineEdit.Password) self.btnReg = QtWidgets.QPushButton("&OK") self.lnkAutor = QtWidgets.QPushButton('&Авторизация') self.vbox.addWidget(self.title) self.vbox.addWidget(self.username) self.vbox.addWidget(self.password) self.vbox.addWidget(self.btnReg) self.vbox.addWidget(self.lnkAutor) self.setLayout(self.vbox) self.btnReg.clicked.connect(self.registration) self.lnkAutor.clicked.connect(self.switchToAuthorisation) def switchToAuthorisation(self): """ Переключение на авторизацию """ # TODO: self.resize(300, 200) # self.clearLayout(self.vbox) self.title = QtWidgets.QLabel('Авторизация') self.title.setAlignment(QtCore.Qt.AlignHCenter) self.username = QtWidgets.QLineEdit() self.username.setPlaceholderText('Введите логин:') self.password = QtWidgets.QLineEdit() self.password.setPlaceholderText('Введите пароль:'), self.password.setEchoMode(QtWidgets.QLineEdit.Password) self.btnAutor = QtWidgets.QPushButton("&OK") self.lnkReg = QtWidgets.QPushButton('&Регистрация') self.vbox.addWidget(self.title) self.vbox.addWidget(self.username) self.vbox.addWidget(self.password) self.vbox.addWidget(self.btnLogin) self.vbox.addWidget(self.lnkReg) self.setLayout(self.vbox) self.btnAutor.clicked.connect(self.authorisation) self.lnkReg.clicked.connect(self.switchToRegistration) def authorisation(self): """ Авторизация """ url = self.url_base + 'auth/login' data = {'username': self.username.text(), 'password': self.password.text()} r = requests.post(url, json=data) # TODO: res_usr = r.json() # res_u = r.text # #print(res_u) # res_usr = json.loads(res_u) #print(res_usr['status']) if res_usr['status'] == 'ok': self.main_id = res_usr['id'] #print(self.main_id) self.getChat() elif res_usr['status'] == 'no': self.showError(res_usr) def registration(self): """ Регистрация """ url = self.url_base + 'auth/register' data = {'username': self.username.text(), 'password': self.password.text()} r = requests.post(url, json=data) res_usr = r.json() # TODO: # res_u = r.text # #print(res_u) # res_usr = json.loads(res_u) if res_usr['status'] == 'ok': self.switchToAuthorisation() elif res_usr['status'] == 'no': self.showError(res_usr) # TODO: # def clearLayout(self, layout): # """ # Очистка окошка # """ # for i in reversed(range(layout.count())): # layout.itemAt(i).widget().setParent(None) def showError(self, res_usr): """ Показать ошибки """ self.label = QtWidgets.QLabel(res_usr['error']) self.label.setAlignment(QtCore.Qt.AlignHCenter) self.vbox.addWidget(self.label) def showSuccess(self, res_usr): """ Показать успех """ self.label = QtWidgets.QLabel(res_usr['success_msg']) self.label.setAlignment(QtCore.Qt.AlignHCenter) self.vbox.addWidget(self.label) def getChat(self): window.resize(300, 400) # self.clearLayout(self.vbox) self.label = QtWidgets.QLabel('Чат') self.label.setAlignment(QtCore.Qt.AlignHCenter) self.vbox.addWidget(self.label) url = self.url_base + 'blog/chat' r = requests.post(url) print(r.status_code, r.reason) print(r.request.headers) # TODO: res_pst = r.json() # res_u = r.text # res_pst = json.loads(res_u) #print(res_pst) # self.chat_obj = QtWidgets.QListWidget(self) for key, value in res_pst.items(): item = QtWidgets.QListWidgetItem(self.chat_obj) item.setText(value[0] + ': ' + value[1]) if value[2] == self.main_id: item.setTextAlignment(QtCore.Qt.AlignRight) item.setForeground(QtGui.QColor(colors[0])) else: item.setTextAlignment(QtCore.Qt.AlignLeft) item.setForeground(QtGui.QColor(colors[1])) #self.chat_obj.addItem(value[0] + ': ' + value[1]) # TODO: в конструкторе добавлено на форму # self.vbox.addWidget(self.chat_obj) self.message = QtWidgets.QLineEdit() self.message.setPlaceholderText('Введите сообщение') self.vbox.addWidget(self.message) self.btnSend = QtWidgets.QPushButton("&Отправить") self.vbox.addWidget(self.btnSend) self.btnSend.clicked.connect(self.sendmessage) def sendmessage(self): """ Отправка сообщения """ print(self.main_id) url = self.url_base + 'blog/create/{}'.format(self.main_id) data = {'message': self.message.text()} #print(data) r = requests.post(url, json=data) #print(r.status_code, r.reason) #print(r.request.headers) # TODO: res_usr = r.json() # res_m = r.text # #print(res_m) # res_usr = json.loads(res_m) if res_usr['status'] == 'ok': self.showSuccess(res_usr) elif res_usr['status'] == 'no': self.showError(res_usr) self.message.clear() Код с self.label = явно костыльный, но его не трогал, т.к. проблема с QListWidget, а не с этим

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

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