Issue
I have a weird question, I am creating a GUI for a chatbot and I've chosen PyQt5 Designer to do so. Everything has been working perfectly but now I've implemented some hyperlinks and realized that when I click a line with different font in QTextBrowser, all the chatbot responses change to that font. So for example, if I click a link, every single answer after that will be hyperlinked.
Code snippets:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
mainWindow.resize(812, 577)
self.centralwidget = QtWidgets.QWidget(mainWindow)
self.centralwidget.setObjectName("centralwidget")
#Browse Button
self.browseButton = QtWidgets.QPushButton(self.centralwidget)
self.browseButton.setGeometry(QtCore.QRect(690, 480, 101, 61))
self.browseButton.setObjectName("browseButton")
#TextBrowser (big window)
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setGeometry(QtCore.QRect(20, 20, 581, 471))
self.textBrowser.setObjectName("textBrowser")
self.textBrowser.setFontFamily("monospace")
self.textBrowser.setFont(QtGui.QFont("monospace",11))
self.textBrowser.setOpenExternalLinks(True)
#Line Edit - small line for user input
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(20, 500, 581, 41))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit.returnPressed.connect(self.run)
self.lineEdit.setPlaceholderText("Ask me anything...")
#Anton's Avatar
self.avatarLabel = QtWidgets.QLabel(self.centralwidget)
self.avatarLabel.setGeometry(QtCore.QRect(610, 20, 191, 251))
self.avatarLabel.setFrameShape(QtWidgets.QFrame.Box)
self.avatarLabel.setText("")
self.avatarLabel.setPixmap(QtGui.QPixmap("Anton.jpg"))
self.avatarLabel.setObjectName("avatarLabel")
#Send button and Yes/No Dialog
self.buttonBox = QtWidgets.QDialogButtonBox(self.centralwidget)
self.buttonBox.setGeometry(QtCore.QRect(400, 440, 193, 28))
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.sendButton = QtWidgets.QPushButton(self.centralwidget)
self.sendButton.setGeometry(QtCore.QRect(610, 480, 71, 61))
self.sendButton.setObjectName("sendButton")
self.sendButton.clicked.connect(self.run)
self.sendButton.clicked.connect(self.lineEdit.clear)
self.buttonBox.raise_()
self.browseButton.raise_()
self.textBrowser.raise_()
self.lineEdit.raise_()
self.avatarLabel.raise_()
self.sendButton.raise_()
mainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(mainWindow)
self.statusbar.setObjectName("statusbar")
mainWindow.setStatusBar(self.statusbar)
self.retranslateUi(mainWindow)
self.lineEdit.returnPressed.connect(self.lineEdit.clear)
self.sendButton.clicked.connect(self.lineEdit.copy)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "Chatbot"))
self.textBrowser.setHtml(_translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:7.8pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
self.sendButton.setText(_translate("mainWindow", "Send"))
def gettext(self): # Get text from user input text line
text = self.lineEdit.text()
return text
def answerr(self,text): # Print result to text browser
self.textBrowser.append(str(text))
def run(self):
#get user input
try:
userInput = self.gettext()
user = '<span style=\" color: #ff0000;\">%s</span>' % userInput
self.answerr("> "+user)
except (KeyboardInterrupt, EOFError) as e:
answerr("Bye!")
rec_video="https://www.youtube.com/watch?v=Z6MqOw2y744"
self.textBrowser.append("\nYou can find a video with the instructions on the link below.")
self.textBrowser.append(str("<a href=\""+rec_video+"\">'Youtube Link'</a>"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mainWindow = QtWidgets.QMainWindow()
ui = Ui_mainWindow()
ui.setupUi(mainWindow)
mainWindow.show()
sys.exit(app.exec_())
Any help would be greatly appreciated. P.S. If I would click the user input (red font) it would make all the upcoming chatbot responses red too. The only half-solution I have found was using QTextCursor.Start but that would scroll up after each question.
Solution
The problem is that when you click on the link that format is set as the current format so adding text will use that format, a possible solution is to reset the format to the value it had before the link is pressed (I have taken the time to improve your example using layout).
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.textbrowser = QtWidgets.QTextBrowser(openExternalLinks=True)
self.lineedit = QtWidgets.QLineEdit(
placeholderText=self.tr("Ask me anything...")
)
self.sendbutton = QtWidgets.QPushButton(self.tr("Send"))
self.browsebutton = QtWidgets.QPushButton()
self.avatarlabel = QtWidgets.QLabel(
frameShape=QtWidgets.QFrame.Box, pixmap=QtGui.QPixmap("Anton.jpg")
)
self.lineedit.setFixedHeight(40)
self.avatarlabel.setFixedSize(190, 250)
self.sendbutton.setFixedHeight(60)
self.browsebutton.setFixedHeight(60)
vlay_left = QtWidgets.QVBoxLayout()
vlay_right = QtWidgets.QVBoxLayout()
central_widget = QtWidgets.QWidget()
central_widget.setContentsMargins(10, 10, 10, 10)
self.setCentralWidget(central_widget)
hlay = QtWidgets.QHBoxLayout(central_widget)
hlay.addLayout(vlay_left)
hlay.addLayout(vlay_right)
vlay_left.addWidget(self.textbrowser)
vlay_left.addWidget(self.lineedit)
bottom_hlay = QtWidgets.QHBoxLayout()
bottom_hlay.addWidget(self.sendbutton)
bottom_hlay.addWidget(self.browsebutton)
vlay_right.addWidget(self.avatarlabel)
vlay_right.addStretch()
vlay_right.addLayout(bottom_hlay)
self.resize(640, 480)
self._text_format = self.textbrowser.currentCharFormat()
self.lineedit.returnPressed.connect(self.execute)
self.sendbutton.clicked.connect(self.lineedit.copy)
self.sendbutton.clicked.connect(self.execute)
self.textbrowser.setFontFamily("monospace")
self.textbrowser.setFont(QtGui.QFont("monospace", 11))
@property
def text_format(self):
return self._text_format
@text_format.setter
def text_format(self, fmt):
self._text_format = fmt
self.reset_format()
def reset_format(self):
self.textbrowser.setCurrentCharFormat(self.text_format)
@QtCore.pyqtSlot()
def execute(self):
self.reset_format()
text = self.lineedit.text()
user = '<span style=" color: #ff0000;">%s</span>' % text
self.answer("> " + user)
rec_video = "https://www.youtube.com/watch?v=Z6MqOw2y744"
self.textbrowser.append(
"\nYou can find a video with the instructions on the link below."
)
self.textbrowser.append('<a href="' + rec_video + "\">'Youtube Link'</a>")
self.lineedit.clear()
def answer(self, text):
self.textbrowser.append(text)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.