Я понял то, что вы сказали следующим образом:
- Вы хотите нарисовать треугольник наконечника по краю в любом месте RoundRect.
- Но наконечник находится вне прямоугольникакак есть, и затем, если вы попытаетесь избежать этого, если вы увеличите размер метки для просмотра кончика, тексты на прямоугольнике будут выходить из прямоугольника наоборот.Вы хотите избежать этих явлений. То есть вы хотите включать тексты в RoundRect все время и показывать треугольник наконечника одновременно.
- В соответствии с этим пониманием я попытался написать код.
- Пожалуйста, не стесняйтесь спрашивать меня, если у вас остались какие-то проблемы.
Пояснение
Вы не можете показать кончик треугольника итексты одновременно, потому что размер круглого прямоугольника (я назову это «пузырем») почти равен размеру этикетки. Поэтому я попытался изменить его.
Чтобы изменить это, я рассчитал размерпузыря из каждого текста.Я сделал эту функцию:
calc_textswidth(self, text, minimumwidth)
Это вычисляет ширину текста каждого символа.и вернуть длину.если длина больше, чем ширина пузырька (ширина метки - длина строки пути), я вставил «\ n» для переноса.
Если вы установите setWrap(True)
, он станет грязным.Потому что это означает, что тексты будут переноситься, если тексты достигают конца метки. Поэтому я удаляю метод.
text = self.text()
text = text.replace("\n", "")
Для пересчета положения текстов при каждом изменении размера важно объединить все текстыкак одна строка. И мы вычисляем всю длину строки, мы делим тексты каждый раз, когда длина становится больше, чем ширина пузырька.
Мы делаем это снова и снова.
КакПо объяснению я разделил размер этикетки и пузыря.Ширина пузырьков определяется исходя из длины текстов.
PS
Расчет очень многословен.Возможно, он станет компактным, если вы будете использовать списки и т. Д. ...
Надеюсь, этот расчет не является чем-то вроде бутылочного горлышка этого приложения ...
Если он останетсячто-то, пожалуйста, не стесняйтесь спрашивать меня.
Обновление
Как вы говорите, мой код является ловушкой линии.Я перемещаю край линии к центральной точке.
Я думаю, что это лучшее место для верхнего края.
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class chatLabel(QLabel):
def __init__(self, text):
super(chatLabel, self).__init__(text)
self.setContentsMargins(6,6,6,6)
sizePolicy = QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding )
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
self.setSizePolicy(sizePolicy)
#I changed this color because I can't see the text good.
self.color = QColor("#333C43")
self.tip_length = 15
self.coodinate_point = 10
self.setText(text)
self.initial_minimumwidth = 128
self.setMinimumWidth(self.initial_minimumwidth)
self.initial_maximumwidth = 128
self.setMaximumWidth(self.initial_maximumwidth)
def paintEvent(self, e):
p = QPainter(self)
p.setRenderHint(QPainter.Antialiasing, False)
#I changed this width from - 1 to - 16 because I can't see the result good.
rect = QRectF(0,0,self.width()- self.tip_length,self.height()-1)
p.setPen(Qt.NoPen)
path = QPainterPath()
path.setFillRule(Qt.WindingFill )
path.addRoundedRect(rect, 15.0, 15.0)
#I deleted this object
#path.addRect(self.width()-13, 0, 13, 13)
linePath = QPainterPath()
linePath.moveTo(rect.right() + 15 , rect.top())
center = rect.center()
linePath.lineTo(center.x() , rect.bottom())
linePath.lineTo(rect.right() , rect.top() - rect.height())
path = path.united(linePath)
p.fillPath(path, self.color)
super(chatLabel, self).paintEvent(e)
def checktextsinside(self, text):
font = self.font()
fontmetrics = QFontMetricsF(font)
fontwidth = fontmetrics.width(text)
return fontwidth
def checkeachcharinside(self, text, minimumwidth):
font = self.font()
fontmetrics = QFontMetricsF(font)
t_sum = 0
t_join = ""
chat_data = []
for num, t in enumerate(text):
cw = fontmetrics.widthChar(t)
t_sum += cw
t_join += t
if t_sum > minimumwidth - self.tip_length :
chat_data.append(t_join+"\n")
t_sum = 0
t_join = ""
#append the final extra t_join
chat_data.append(t_join)
return t_sum, chat_data
def resizeEvent(self, e): #Due to a bug in Qt, we need this. ref:https://bugreports.qt.io/browse/QTBUG-37673
#heightForWidth rely on minimumSize to evaulate, so reset it before
if self.width()>256:
self.setMinimumWidth(128)
text = self.text()
text = text.replace("\n", "")
n_width, chat_data = self.checkeachcharinside(text, self.initial_minimumwidth - (self.tip_length + self.coodinate_point))
joint_text = ""
for joint in chat_data:
joint_text += joint
self.setText(joint_text)
self.setMinimumSize(QSize(n_width + self.tip_length, self.heightForWidth( self.width())))
super(chatLabel, self).resizeEvent(e)
def main():
try:
app=QApplication([])
except Exception as e:
print(e)
widget = chatLabel("This is the result typing!Please Don't wrap!Yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
widget.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()