简体   繁体   中英

Highlighting the words with find function and moving the cursor with coloured cursor movement and displaying the number of found words

I am trying to implement find function to display the words found and moving the cursor over the found words with coloured cursor and highlight the words found and count the number of words found.

I tried highlighter and cursor movement but my highlighter works after the movement of cursor. mainWindow.py

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import os
import sys
#import Find_Problem
import Dock_Find
class MainWindow(Find_Problem.Ui_MainWindow, QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.actionNew.triggered.connect(self.newFile)
        self.actionOpen.triggered.connect(self.openFile)
        self.actionSave.triggered.connect(self.saveFile)
        self.actionExit.triggered.connect(self.exitFile)
        self.actionFind.triggered.connect(self.new_find)
        self.actionWord_Count.triggered.connect(self.countWord)
        self.show()
        self.showMaximized()

    def newFile(self):
        self.textEdit.clear()

    def openFile(self):
        filename = QFileDialog.getOpenFileName(self, 'Open File', ".","(*.txt)")
        if filename[0]:
            f = open(filename[0], 'rt')
            with f:
                data = f.read()
                self.textEdit.setText(data)

    def saveFile(self):
        filename = QFileDialog.getSaveFileName(self, 'Save File', ".", "(*.txt)")
        if filename[0]:
            f = open(filename[0], 'wt')
            with f:
                text = self.textEdit.toPlainText()
                f.write(text)
                QMessageBox.about(self, "Save File", "File Saved Successfully")

    def exitFile(self):
        choice = QMessageBox.question(self, 'Close', "Do you want to close?", QMessageBox.Yes | QMessageBox.No)
        if choice == QMessageBox.Yes:
            self.saveFile()
            self.close()
        else:
            pass

    def new_find(self):
        txt = Dock_Find()
        txt.show()

        def handleFind():
            text = txt.findLine.text()

            if self.find(text):
                linenumber = self.textCursor().blockNumber() + 1
                fmt = QTextCharFormat()
                fmt.setForeground(Qt.blue)
                return
            else:

                #self.statusBar().showMessage("<b>'" + txt.findLine.text() + "'</b> not found")
                self.moveCursor(QTextCursor.Start)
                if self.find(text):
                    fmt = QTextCharFormat()
                    fmt.setBackground(Qt.yellow)
                    self.mergeFormatOnWordsOrSelection(fmt)
                    linenumber = self.textCursor().blockNumber() + 1
                    return

            QMessageBox.about(self, "No Match", "No Words Found")
            txt.hide()
        def handleFindPrevious():
            text = txt.findLine.text()
            long = len(text)
            cursor = QTextCursor()
            pos = cursor.position()

            if self.find(text):
                linenumber = self.textCursor().blockNumber() +1
                fmt = QTextCharFormat()
                fmt.setForeground(Qt.red)
                self.mergeFormatOnWordsOrSelection(fmt)
                return
            else:
                self.moveCursor(QTextCursor.PreviousWord)
                if self.find(text):
                    fmt = QTextCharFormat()
                    fmt.setBackground(Qt.yellow)
                    self.mergeFormatOnWordsOrSelection(fmt)
                    linenumber = self.textCursor().blockNumber() +1
                    return
        txt.findButton.clicked.connect(handleFind)
        txt.previousButton.clicked.connect(handleFindPrevious)


    def mergeFormatOnWordsSelection(self, format):
        cursor = self.textEdit.textCursor()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.mergeCharFormat(format)
        self.textEdit.mergeCurrentCharFormat(format)

    def countWord(self):
        text = self.textEdit.textCursor().selectedText()
        words = str(len(text.split()))
        symbols = str(len(text))
        self.currenWords.setText(words)
        self.currentSymbols.setText(symbols)
        text = self.textEdit.toPlainText()
        words = str(len(text.split()))
        symbols = str(len(text))
        self.totalWords.setText(words)
        self.totalSymbols.setText(symbols)


class Dock_Find(Dock_Find.Ui_Dock_Find, QtWidgets.QDockWidget):
    def __init__(self, parent=None):
        super(Dock_Find, self).__init__(parent)
        self.setupUi(self)
        self.findLine.setPlaceholderText("Type Here")


if __name__== '__main__':
    app = QtWidgets.QApplication(sys.argv)
    qt_app = MainWindow()
    qt_app.show()
    sys.exit(app.exec_())

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setObjectName("textEdit")
        self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        self.menuSearch = QtWidgets.QMenu(self.menubar)
        self.menuSearch.setObjectName("menuSearch")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionOpen = QtWidgets.QAction(MainWindow)
        self.actionOpen.setObjectName("actionOpen")
        self.actionSave = QtWidgets.QAction(MainWindow)
        self.actionSave.setObjectName("actionSave")
        self.actionExit = QtWidgets.QAction(MainWindow)
        self.actionExit.setObjectName("actionExit")
        self.actionFind = QtWidgets.QAction(MainWindow)
        self.actionFind.setObjectName("actionFind")
        self.actionWord_Count = QtWidgets.QAction(MainWindow)
        self.actionWord_Count.setObjectName("actionWord_Count")
        self.actionNew = QtWidgets.QAction(MainWindow)
        self.actionNew.setObjectName("actionNew")
        self.menuFile.addAction(self.actionNew)
        self.menuFile.addAction(self.actionOpen)
        self.menuFile.addAction(self.actionSave)
        self.menuFile.addAction(self.actionExit)
        self.menuSearch.addAction(self.actionFind)
        self.menuSearch.addAction(self.actionWord_Count)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuSearch.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuFile.setTitle(_translate("MainWindow", "File"))
        self.menuSearch.setTitle(_translate("MainWindow", "Search"))
        self.actionOpen.setText(_translate("MainWindow", "Open"))
        self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
        self.actionSave.setText(_translate("MainWindow", "Save"))
        self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
        self.actionExit.setText(_translate("MainWindow", "Exit"))
        self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q"))
        self.actionFind.setText(_translate("MainWindow", "Find"))
        self.actionFind.setShortcut(_translate("MainWindow", "Ctrl+F"))
        self.actionWord_Count.setText(_translate("MainWindow", "Word Count"))
        self.actionNew.setText(_translate("MainWindow", "New"))
        self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N"))
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dock_Find(object):
    def setupUi(self, Dock_Find):
        Dock_Find.setObjectName("Dock_Find")
        Dock_Find.resize(401, 62)
        Dock_Find.setMinimumSize(QtCore.QSize(320, 60))
        font = QtGui.QFont()
        font.setPointSize(10)
        Dock_Find.setFont(font)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/image/graphy_100px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        Dock_Find.setWindowIcon(icon)
        self.dockWidgetContents = QtWidgets.QWidget()
        self.dockWidgetContents.setObjectName("dockWidgetContents")
        self.serachLabel = QtWidgets.QLabel(self.dockWidgetContents)
        self.serachLabel.setGeometry(QtCore.QRect(10, 10, 71, 16))
        self.serachLabel.setObjectName("serachLabel")
        self.findLine = QtWidgets.QLineEdit(self.dockWidgetContents)
        self.findLine.setGeometry(QtCore.QRect(80, 10, 151, 20))
        self.findLine.setObjectName("findLine")
        self.findButton = QtWidgets.QPushButton(self.dockWidgetContents)
        self.findButton.setGeometry(QtCore.QRect(320, 10, 75, 23))
        self.findButton.setObjectName("findButton")
        self.previousButton = QtWidgets.QPushButton(self.dockWidgetContents)
        self.previousButton.setGeometry(QtCore.QRect(240, 10, 75, 23))
        self.previousButton.setObjectName("previousButton")
        Dock_Find.setWidget(self.dockWidgetContents)

        self.retranslateUi(Dock_Find)
        QtCore.QMetaObject.connectSlotsByName(Dock_Find)

    def retranslateUi(self, Dock_Find):
        _translate = QtCore.QCoreApplication.translate
        Dock_Find.setWindowTitle(_translate("Dock_Find", "Find"))
        self.serachLabel.setText(_translate("Dock_Find", "Search For:"))
        self.findButton.setText(_translate("Dock_Find", "Find Next"))
        self.previousButton.setText(_translate("Dock_Find", "Previous"))

import resource_rc

My cursor is highlighted in default and I can not see it properly and I want to highlight it and also looking for creating a function to count the number of words found. I am a learning to develop a text editor and a new programmer and using PyQt5 for GUI.

Try it:

#import os
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui     import *
from PyQt5.QtCore    import *

#import Find_Problem
#import Dock_Find


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setObjectName("textEdit")
        self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        self.menuSearch = QtWidgets.QMenu(self.menubar)
        self.menuSearch.setObjectName("menuSearch")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionOpen = QtWidgets.QAction(MainWindow)
        self.actionOpen.setObjectName("actionOpen")
        self.actionSave = QtWidgets.QAction(MainWindow)
        self.actionSave.setObjectName("actionSave")
        self.actionExit = QtWidgets.QAction(MainWindow)
        self.actionExit.setObjectName("actionExit")
        self.actionFind = QtWidgets.QAction(MainWindow)
        self.actionFind.setObjectName("actionFind")
        self.actionWord_Count = QtWidgets.QAction(MainWindow)
        self.actionWord_Count.setObjectName("actionWord_Count")
        self.actionNew = QtWidgets.QAction(MainWindow)
        self.actionNew.setObjectName("actionNew")
        self.menuFile.addAction(self.actionNew)
        self.menuFile.addAction(self.actionOpen)
        self.menuFile.addAction(self.actionSave)
        self.menuFile.addAction(self.actionExit)
        self.menuSearch.addAction(self.actionFind)
        self.menuSearch.addAction(self.actionWord_Count)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuSearch.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuFile.setTitle(_translate("MainWindow", "File"))
        self.menuSearch.setTitle(_translate("MainWindow", "Search"))
        self.actionOpen.setText(_translate("MainWindow", "Open"))
        self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
        self.actionSave.setText(_translate("MainWindow", "Save"))
        self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
        self.actionExit.setText(_translate("MainWindow", "Exit"))
        self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q"))
        self.actionFind.setText(_translate("MainWindow", "Find"))
        self.actionFind.setShortcut(_translate("MainWindow", "Ctrl+F"))
        self.actionWord_Count.setText(_translate("MainWindow", "Word Count"))
        self.actionNew.setText(_translate("MainWindow", "New"))
        self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N"))


class Ui_Dock_Find(object):
    def setupUi(self, Dock_Find):
        Dock_Find.setObjectName("Dock_Find")
        Dock_Find.resize(320, 65)
        Dock_Find.setMinimumSize(QtCore.QSize(320, 65))
        font = QtGui.QFont()
        font.setPointSize(10)
        Dock_Find.setFont(font)
        icon = QtGui.QIcon()

#        icon.addPixmap(QtGui.QPixmap(":/image/graphy_100px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        icon.addPixmap(QtGui.QPixmap("Ok.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)

        Dock_Find.setWindowIcon(icon)
        self.dockWidgetContents = QtWidgets.QWidget()
        self.dockWidgetContents.setObjectName("dockWidgetContents")
        self.serachLabel = QtWidgets.QLabel(self.dockWidgetContents)
        self.serachLabel.setGeometry(QtCore.QRect(10, 10, 71, 16))
        self.serachLabel.setObjectName("serachLabel")
        self.findLine = QtWidgets.QLineEdit(self.dockWidgetContents)
        self.findLine.setGeometry(QtCore.QRect(80, 10, 151, 20))
        self.findLine.setObjectName("findLine")
        self.findButton = QtWidgets.QPushButton(self.dockWidgetContents)
        self.findButton.setGeometry(QtCore.QRect(240, 10, 75, 23))
        self.findButton.setObjectName("findButton")
        Dock_Find.setWidget(self.dockWidgetContents)

        self.retranslateUi(Dock_Find)
        QtCore.QMetaObject.connectSlotsByName(Dock_Find)

    def retranslateUi(self, Dock_Find):
        _translate = QtCore.QCoreApplication.translate
        Dock_Find.setWindowTitle(_translate("Dock_Find", "Find"))
        self.serachLabel.setText(_translate("Dock_Find", "Search For:"))
        self.findButton.setText(_translate("Dock_Find", "Find"))

#import resource_rc        


#class MainWindow(Find_Problem.Ui_MainWindow, QtWidgets.QMainWindow):
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.actionNew.triggered.connect(self.newFile)
        self.actionOpen.triggered.connect(self.openFile)
        self.actionSave.triggered.connect(self.saveFile)
        self.actionExit.triggered.connect(self.exitFile)
        self.actionFind.triggered.connect(self.findWord)
        self.actionWord_Count.triggered.connect(self.countWord)
        self.show()
        self.showMaximized()

        self.textEdit.setFont(QFont('Decorative', 12))                      # +
        self.countWords = 0                                                 # +++

    def newFile(self):
        self.textEdit.clear()

    def openFile(self):
        filename = QFileDialog.getOpenFileName(self, 'Open File', ".","(*.txt *.py)")   # + *.py
        if filename[0]:
            fmt = QTextCharFormat()
            fmt.setForeground(QColor(0, 0, 0))
            fmt.setFontPointSize(12)
            self.textEdit.mergeCurrentCharFormat(fmt)

            f = open(filename[0], 'rt')
            with f:
                data = f.read()
                self.textEdit.setText(data)

    def saveFile(self):
        filename = QFileDialog.getSaveFileName(self, 'Save File', ".", "(*.txt)")
        if filename[0]:
            f = open(filename[0], 'wt')
            with f:
                text = self.textEdit.toPlainText()
                f.write(text)
                QMessageBox.about(self, "Save File", "File Saved Successfully")

    def exitFile(self):
        choice = QMessageBox.question(self, 'Close', "Do you want to close?", QMessageBox.Yes | QMessageBox.No)
        if choice == QMessageBox.Yes:
            self.saveFile()
            self.close()
        else:
            pass

    def findWord(self):

        self.dock = Dock_Find()
        self.addDockWidget(Qt.TopDockWidgetArea, self.dock)
        self.dock.show()
        self.dock.findButton.clicked.connect(self.handleFind)

### +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

    def mergeFormatOnWordOrSelection(self, format):
        cursor = self.textEdit.textCursor()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.mergeCharFormat(format)
        self.textEdit.mergeCurrentCharFormat(format)

    def handleFind(self):
        text = self.dock.findLine.text()
        if not text:
            return
        col = QColorDialog.getColor(self.textEdit.textColor(), self)
        if not col.isValid():
            return
        fmt = QTextCharFormat()
        fmt.setForeground(col)
        print("\nfmt.setForeground(col)", col)
        fmt.setFontPointSize(14)     

        self.textEdit.moveCursor(QTextCursor.Start)

        self.countWords = 0
        while self.textEdit.find(text, QTextDocument.FindWholeWords):      # Find whole words
            self.mergeFormatOnWordOrSelection(fmt)
            self.countWords += 1

        QMessageBox.information(self, 
            "Information", 
#            f"word->`{text}` found in the text `{self.countWords}` times."
             "word->`{text}` found in the text `{countWords}` times.".format(text=text, countWords=self.countWords)
        )

### +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    

    """ ---
        self.dock = Dock_Find()
        self.addDockWidget(Qt.TopDockWidgetArea, self.dock)
        self.dock.show()

        def handleFind():
            text = self.dock.findLine.text()
            if self.textEdit.find(text):
                return
            else:
                fmt = QTextCharFormat()
                fmt.setBackground(Qt.yellow)
                self.textEdit.moveCursor(QTextCursor.Start)
                while self.textEdit.find(text, QTextDocument.FindWholeWords):
                    self.mergeFormatOnWordsSelection(fmt)
                if self.textEdit.find(text):
                    while self.textEdit.moveCursor(QTextCursor.EndOfWord):
                        QMessageBox.about(self, "End of Line", "No Further More Words")
                    return
            QMessageBox.about(self, "No Match", "No Words Found")
        self.dock.findButton.clicked.connect(handleFind)

    def mergeFormatOnWordsSelection(self, format):
        cursor = self.textEdit.textCursor()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.mergeCharFormat(format)
        self.textEdit.mergeCurrentCharFormat(format)
    """ 

    def countWord(self):
        textWord    = self.textEdit.textCursor().selectedText()
        words   = str(len(textWord.split()))
        symbols = str(len(textWord))

#?        self.currenWords.setText(words)
#?        self.currentSymbols.setText(symbols)

        text = self.textEdit.toPlainText()
        words = str(len(text.split()))
        symbols = str(len(text))

#?        self.totalWords.setText(words)
#?        self.totalSymbols.setText(symbols)

#        print(f"word->`{self.dock.findLine.text()}` found in the text `{self.countWords}` times.") # +
        print("word->`{text}` found in the text `{countWords}` times."
              "".format(text=self.dock.findLine.text(), countWords=self.countWords)) # +

        QMessageBox.information(self, 
            "Information", 
#            f"word->`{textWord}` found in the text `{self.countWords}` times."
            "word->`{textWord}` found in the text `{countWords}` times."
            "".format(textWord=textWord, countWords=self.countWords)
        )


#class Dock_Find(Dock_Find.Ui_Dock_Find, QtWidgets.QDockWidget):
class Dock_Find(QtWidgets.QDockWidget, Ui_Dock_Find):
    def __init__(self, parent=None):
        super(Dock_Find, self).__init__(parent)
        self.setupUi(self)
        self.findLine.setPlaceholderText("Type Here")


if __name__== '__main__':
    app = QtWidgets.QApplication(sys.argv)
    qt_app = MainWindow()
    qt_app.show()
    sys.exit(app.exec_())

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM