【问题标题】:How to make text in QTextBrowser selectable? [closed]如何使 QTextBrowser 中的文本可选择? [关闭]
【发布时间】:2019-10-14 23:14:39
【问题描述】:

我希望能够以非自定义方式选择一段文本,就像您点击文本中间的网站链接一样(“你好,我的名字是 www.google.com”,www.当您按下 google.com 时,它不会突出显示。当您按下它时,它会将您带到与我的文本相同的网站。我想让它像“你好,我的名字是 Jeff,我住在伦敦,我每天都吃土豆”我希望用户能够单独选择每个句子(“你好,我的名字是 Jeff”)单独,(“我住在伦敦”)单独,所以当用户移动鼠标光标在句子上突出显示(就像准备好被选中),然后我想给它添加一些功能。

这是一个类似的项目,检查上面的文本,而不是下面的文本以及它对鼠标的反应。

http://quran.ksu.edu.sa/tafseer/tabary/sura10-aya18.html

【问题讨论】:

  • 我听不懂你,你是不是想让你点击一个单词时必须选中它?
  • 对不起,如果我的解释不好....我希望能够选择一个单词(或一系列单词)而不是突出显示它们....并以您单击的方式单击它们在外部链接 ..... www.google.com .... 并能够将其链接到某些功能(例如:pushbutton.clicked.connect(function))....整个程序就像一本书,我希望能够对一个句子做出进一步的解释......所以当人们点击它时......我想要一个新的功能发生(例如一个新的文本似乎将那个句子翻译成另一种语言)
  • 好的,1) 突出显示是选择操作的一部分 2) 据你所知,我首先了解你想选择某些文本,然后如果你点击一个选定的元素,就会触发一个信号,你可以连接到接收所选文本的功能。我是对的?
  • 另一方面,如果您发现您的出版物中的解释不清楚,我邀请您对其进行编辑和改进
  • 是的,一旦我意识到这甚至是一个好问题,我就会编辑我的问题……也许我的问题不在 qt 中,所以我可以删除它。非常感谢您回复我

标签: python pyqt pyqt5 qtextbrowser


【解决方案1】:

这是一个开始。在下面的代码中,文本中的可点击短语被翻译成文本光标的有序列表。当鼠标移动时(即发生mouseMove 事件时),鼠标指针下的文本位置将与此文本光标列表进行比较。如果此位置在列表中的光标范围内,则通过设置浏览器的额外选择来突出显示相应的短语。当单击鼠标按钮并且鼠标悬停在可单击的短语上时,会发出一个信号,其中包含与文本中所选短语相对应的文本光标。然后可以将此信号连接到另一个小部件的插槽以进行进一步操作(例如打开消息框,如下例所示)。

from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import QTextBrowser, QApplication, QMessageBox
from PyQt5.QtGui import QFont, QSyntaxHighlighter, QTextCharFormat, QTextCursor

import bisect, re


class MyHighlighter(QSyntaxHighlighter):
    def __init__(self, keywords, parent):
        super().__init__(parent)
        self.keywords = keywords

    def highlightBlock(self, block):
        if not self.keywords:
            return
        charFormat = QTextCharFormat()
        charFormat.setFontWeight(QFont.Bold)
        charFormat.setForeground(Qt.darkMagenta)
        regex = re.compile('|'.join(self.keywords), re.IGNORECASE)
        result = regex.search(block, 0)
        while result:
            self.setFormat(result.start(),result.end()-result.start(), charFormat)
            result = regex.search(block, result.end())


class MyBrowser(QTextBrowser):
    text_clicked = pyqtSignal("QTextCursor")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMouseTracking(True)
        self.setTextInteractionFlags(Qt.NoTextInteraction)

        # self.phrases contains all phrases that should be clickable.
        self.phrases = set()
        self.cursors = []

        # ExtraSelection object for highlighting phrases under the mouse cursor
        self.selection = QTextBrowser.ExtraSelection()
        self.selection.format.setBackground(Qt.blue)
        self.selection.format.setForeground(Qt.white)
        self.selected_cursor = None

        # custom highlighter for highlighting all phrases
        self.highlighter = MyHighlighter(self.phrases, self)
        self.document().contentsChange.connect(self.text_has_changed)

    @property
    def selected_cursor(self):
        return None if self.selection.cursor == QTextCursor() else self.selection.cursor

    @selected_cursor.setter
    def selected_cursor(self, cursor):
        if cursor is None:
            cursor = QTextCursor()
        if self.selection.cursor != cursor:
            self.selection.cursor = cursor
            self.setExtraSelections([self.selection])

    def mouseMoveEvent(self, event):
        ''' Update currently selected cursor '''
        cursor = self.cursorForPosition(event.pos())
        self.selected_cursor = self.find_selected_cursor(cursor)

    def mouseReleaseEvent(self, event):
        ''' Emit self.selected_cursor signal when currently hovering over selectable phrase'''
        if self.selected_cursor:
            self.text_clicked.emit(self.selected_cursor)
            self.selected_cursor = None

    def add_phrase(self, phrase):
        ''' Add phrase to set of phrases and update list of text cursors'''
        if phrase not in self.phrases:
            self.phrases.add(phrase)
            self.find_cursors(phrase)
            self.highlighter.rehighlight()

    def find_cursors(self, phrase):
        ''' Find all occurrences of phrase in the current document and add corresponding text cursor
        to self.cursors '''
        if not phrase:
            return
        self.moveCursor(self.textCursor().Start)
        while self.find(phrase):
            cursor = self.textCursor()
            bisect.insort(self.cursors, cursor)
        self.moveCursor(self.textCursor().Start)

    def find_selected_cursor(self, cursor):
        ''' return text cursor corresponding to current mouse position or None if mouse not currently
        over selectable phrase'''
        position = cursor.position()
        index = bisect.bisect(self.cursors, cursor)
        if index < len(self.cursors) and self.cursors[index].anchor() <= position:
            return self.cursors[index]
        return None

    def text_has_changed(self):
        self.cursors.clear()
        self.selected_cursor = None
        for phrase in self.phrases:
            self.find_cursors(phrase)
            self.highlighter.rehighlight()


def text_message(widget):
    def inner(cursor):
        text = cursor.selectedText()
        pos = cursor.selectionStart()
        QMessageBox.information(widget, 'Information',
                f'You have clicked on the phrase <b>{text}</b><br>'
                f'which starts at position {pos} in the text')
    return inner


if __name__=="__main__":
    app = QApplication([])
    window = MyBrowser()
    window.resize(400,300)
    information = text_message(window)

    text = '''
    <h1>Title</h1>
    <p>This is a random text with. The following words are highlighted</p>
    <ul>
    <li>keyword1</li>
    <li>keyword2</li>
    </ul>
    <p>Click on either keyword1 or keyword2 to get more info. 
    '''

    window.add_phrase('keyword1')
    window.add_phrase('keyword2')
    window.setText(text)
    window.text_clicked.connect(information)
    window.show()
    app.exec()

【讨论】:

  • 你是那个男人......非常感谢......这正是我想要的。如果我能用 1k 给你投票,我会这样做......但不幸的是,我不能做可见的投票,因为我的声誉低于 15(我是这个网站的新手)......再次感谢你拯救了我的天。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 2016-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多