暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

解决pyqt5 textbrowser控件超链接锚点问题

zayki 2025-04-27
253

引用stackoverflow的一篇文章,我解决了pyqt5 textbrowser控件超链接锚点问题,
文章链接:https://stackoverflow.com/questions/73584865/qtextbrowser-pyqt5-problem-after-click-on-anchor

主要解决方案:每次在textbrowser控件中使用append添加内容(包含超链接内容)之前,将游标移动到textbrowser控件的最下方,即可以解决问题。

'''This might be unintuitive for QTextBrowser, since it doesn't show the text cursor (the "caret"), but clicking on a QTextBrowser does change the cursor position, exactly like it would if you used setReadOnly(False) or by using a standard QTextEdit. The solution is to always move the text cursor to the end before calling append(). Remember that in order to make the actual text edit/browser cursor move, you must call setTextCursor() again after moving its position.''' def addtxt(self): # get the QTextCursor of the widget's document cursor = self.browser.textCursor() # move it to the end of the document cursor.movePosition(cursor.End) # *restore* the text cursor on the widget self.browser.setTextCursor(cursor) self.browser.append('sample text 1') self.browser.append('some text: <a href="http://link.com">textlink</a>') self.browser.append('sample text 2')

现象描述如下:
源代码:

import sys from PyQt5.QtWidgets import * class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.resize(500, 500) self.browser = QTextBrowser(self) self.browser.resize(500, 300) self.btn = QPushButton('get html print', self) self.btn.move(250, 400) self.btn.clicked.connect(self.gethtml) self.btn2 = QPushButton('add text', self) self.btn2.move(150, 400) self.btn2.clicked.connect(self.addtxt) self.browser.setOpenLinks(False) self.browser.anchorClicked.connect(self.anchor_clicked) def gethtml(self): print(self.browser.toHtml()) def addtxt(self): self.browser.append('sample text 1') self.browser.append('some text: <a href="http://link.com">textlink</a>') self.browser.append('sample text 2') def anchor_clicked(self): pass if __name__ == '__main__': app = QApplication(sys.argv) dlgMain = MainWindow() dlgMain.show() sys.exit(app.exec_())

点击界面上"add text"按钮后,显示结果如下图:
image.png

在textbrowser控件显示超链接文本内容之后,点击textlink链接锚点会打开对应的链接,
点击之后,再点击"add text"按钮后会变成如下效果, 没有设置超链接的文本也激活了超链接锚点,
image.png

贴出我的代码:

self.button2.clicked.connect(self.getaccounts) def getaccounts(self): # 启动进度条动画 self.progress_bar.setRange(0, 0) self.progress_timer.start(100) # 禁用按钮防止重复点击 self.button1.setEnabled(False) self.button2.setEnabled(False) self.scrolledtext1.setReadOnly(True) # 创建工作线程 self.worker = WorkerThread(self._do_getaccounts) self.worker.finished.connect(self.on_getaccounts_finished) self.worker.start() def on_getaccounts_finished(self, success, result): # 恢复按钮状态 self.button1.setEnabled(True) self.button2.setEnabled(True) # 停止进度条 self.progress_timer.stop() self.progress_bar.setRange(0, 1) self.progress_bar.setValue(0) self.scrolledtext1.clear() # 滚动到最后一行,这部分即是点睛之笔。 self.scrolledtext1.setFocus() cursor = self.scrolledtext1.textCursor() cursor.movePosition(cursor.End) self.scrolledtext1.setTextCursor(cursor) self.scrolledtext1.append(result) # 追加文本内容是在移动游标之后。 if not success: self.scrolledtext1.append(f"操作失败: {result}") def _do_getaccounts(self): try: from requests import session admin = self.entry1.text() passwd = self.entry2.text() account = self.entry3.text() cip_manageurl = self.entry4.text() login_url = jenkins_manageurl + "/j_acegi_security_check" payload = "j_username=" + admin + "&j_password=" + passwd + "&from=%2F&Submit=%E7%99%BB%E5%BD%95&remember_me=on" headers = { 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'accept-encoding': 'gzip, deflate', 'accept-language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'connection': 'keep-alive', 'content-length': '88', 'content-type': 'application/x-www-form-urlencoded', 'dnt': '1', 'host': jenkins_manageurl.split("//")[1], 'origin': jenkins_manageurl, 'referer': jenkins_manageurl + '/login?from=%2F', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0', } response = self.session.post(login_url, headers=headers, data=payload, timeout=2) if response.status_code != 200: return "用户名或者密码错误,请管理员重新输入!" else: self.save_config() # Save on successful login account_url = jenkins_manageurl + "/securityRealm/" response = self.session.get(account_url) html = etree.HTML(response.text) account_list = html.xpath("//tr//td[2]/a/text()") # self.scrolledtext1.append("—" * 12 + "\n") return "系统中存在%d个账号" % len(account_list) + ":\n" +"\n".join(account_list) except Exception as e: self.scrolledtext1.append("连接失败,请检查或者修改CIP管理地址.\n" + str(e)) finally: # Use QTimer.singleShot to stop timer in main thread QTimer.singleShot(0, lambda: ( self.progress_timer.stop(), self.progress_bar.setRange(0, 1), self.progress_bar.setValue(0) ))
最后修改时间:2025-04-27 17:17:18
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论