Как сделать двухсторонний чат в QT (PyQt)
Пытался сделать окно чата в Qt. Столкнулся с проблемой отображения сообщений. Само окно с сообщениями сделал с помощью QTextBrowser. Но весь текст отображается только с одной стороны окна чата. Есть какие-либо варианты (без хардкода в QML) чтобы реализовать подобное примеру ниже окно чата ? (на скриншоте сделал с помощью label, но каждое сообщение добавлять в box в виде отдельного объекта - разориться на ресурсах, поэтому ищу оптимальные варианты)
Пример
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Возможный вариант, обратите внимание:
QTextEditreadOnlyдолжно бытьTrue;- полосы прокрутки отключены;
- политика вертикального размера должна быть
Preferred; - как
MinimumSizeHint(), так иsizeHint()должны использовать внутреннийQTextDocumentдля возврата правильной высоты с минимальной шириной по умолчанию; - любое изменение размера или содержимого должно вызвать updateGeometry(), чтобы родительский макет знал, что подсказка изменилась, и геометрию можно было вычислить снова;
import sys
from random import randrange
from PyQt5 import QtWidgets, QtGui, QtCore, QtMultimedia
from PyQt5.Qt import *
class WrapLabel(QtWidgets.QTextEdit):
def __init__(self, text=''):
super().__init__(text)
self.setStyleSheet('''
WrapLabel {
border: 1px outset palette(dark);
border-radius: 8px;
background: palette(light);
}
''')
self.setReadOnly(True)
self.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Maximum)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.textChanged.connect(self.updateGeometry)
def minimumSizeHint(self):
doc = self.document().clone()
doc.setTextWidth(self.viewport().width())
height = doc.size().height()
height += self.frameWidth() * 2
return QtCore.QSize(150, height-100)
def sizeHint(self):
return self.minimumSizeHint()
def resizeEvent(self, event):
super().resizeEvent(event)
self.updateGeometry()
class ChatTest(QtWidgets.QScrollArea):
def __init__(self):
super().__init__()
container = QtWidgets.QWidget()
self.setMinimumSize(250, 250)
self.setWidget(container)
self.setWidgetResizable(True)
layout = QtWidgets.QVBoxLayout(container)
layout.addStretch()
self.resize(480, 360)
for i in range(1, 11):
QtCore.QTimer.singleShot(1000 * i, lambda i=i:
self.addMessage('1' * randrange(70, 350), i)
)
def addMessage(self, text, i):
wrapLabel = WrapLabel(text)
if i % 2:
wrapLabel.setStyleSheet('''
WrapLabel {
border: 1px outset palette(dark);
border-radius: 8px;
background: palette(light);
margin-left: 50px;
background: #FFFEB7;
}
''')
else:
wrapLabel.setStyleSheet('''
WrapLabel {
border: 1px outset palette(dark);
border-radius: 8px;
background: palette(light);
margin-right: 50px;
background: #C8E6F5;
color: #6D3939;
}
''')
self.widget().layout().addWidget(wrapLabel)
QtCore.QTimer.singleShot(0, self.scrollToBottom)
def scrollToBottom(self):
QtWidgets.QApplication.processEvents()
self.verticalScrollBar().setValue(
self.verticalScrollBar().maximum())
if __name__ == "__main__":
app = QApplication(sys.argv)
w = ChatTest()
w.show()
sys.exit(app.exec_())

