Найти - Пользователи
Полная версия: PyQT4 | Следующий результат поиска в QTextEdit
Начало » GUI » PyQT4 | Следующий результат поиска в QTextEdit
1
Kyrym
Как находить следующие результаты поиска текста?
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox, QFileDialog)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
tx = '''Константин бежал по дорожке, а потом колол дрова.
Кондрат собирал корения. На улице стоял колотун.
Иван же лежал в гамаке и пил кофе с конфетами.
ваер  р
вп
фп пр
ко
афвп
ырап
авпопр
рпавап
фпре
ре р пар
ер екр
рвек'''
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(600, 250) # шир / выс окна
        self.setWindowTitle('Поиск текста') # Заголовок
        # ПЕРЕМЕННЫЕ КЛАССА
        self.find_index = 0
        # БЛОК РАЗМЕТКИ
        #grid_os = QGridLayout()
        vbox = QVBoxLayout()
        # ---
        self.pole_vivod = QTextEdit('')
        self.pole_vivod.setStyleSheet(sss_vivod)
        self.pole_vivod.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction) # QtCore.Qt.TextEditorInteraction
        vbox.addWidget(self.pole_vivod)
        # ---
        grid_UT = QGridLayout()
        vbox.addLayout(grid_UT)
        # --- --- поиск ---
        self.btn_find_clear = QtGui.QPushButton('X')
        self.btn_find_clear.clicked.connect(self.on_find_clear)
        grid_UT.addWidget(self.btn_find_clear, 1,0)
        # ---
        self.btn_find_backward = QtGui.QPushButton('◄')
        self.btn_find_backward.clicked.connect(self.on_find_backward)
        grid_UT.addWidget(self.btn_find_backward, 1,1)
        # ---
        self.btn_find_forward = QtGui.QPushButton('►')
        self.btn_find_forward.clicked.connect(self.on_find_forward)
        grid_UT.addWidget(self.btn_find_forward, 1,2)
        # ---
        self.pole_find = QLineEdit(self)
        self.pole_find.setToolTip('Поиск текста')
        self.pole_find.textChanged.connect(self.on_find_text)
        grid_UT.addWidget(self.pole_find, 1,3,1,10)
        # настройка:
        grid_UT.setColumnStretch(10, 1)
        for i in range(10):
            grid_UT.setColumnMinimumWidth(i, 10) # индекс / высота
        # --- --- end: поиск ---
        
        # ---
        self.setLayout(vbox)
        # --- ---
        Window.on_start(self)
    # ЛОГИКА
    
    def on_start(self):        
        self.pole_vivod.append(str(tx))
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
    # === >>> ПОИСК ТЕКСТА ===
    def on_find_text(self):
        # self.find_index # как-то использовать для списка найденных индексов
        text = self.pole_find.text()
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
        self.pole_vivod.find(text)
    def on_find_forward(self): # поиск вперёд
        self.find_index += 1
        self.on_find_text()
    def on_find_backward(self): # поиск назад
        self.find_index -= 1
        self.on_find_text()
    def on_find_clear(self): # очистить поиск
        self.find_index = 0
        self.pole_find.blockSignals(1) # блокировка сигналов
        self.pole_find.clear()
        self.pole_find.blockSignals(0) # отмена блокировки сигналов
        cursor = self.pole_vivod.textCursor()
        posit = cursor.position() # позиц курсора
        cursor.movePosition(posit) # происходит сброс выделения        
        self.pole_vivod.setTextCursor(cursor)
        
    # === >>> END: ПОИСК ТЕКСТА === 
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window()   
    window.show()
    sys.exit(app.exec_())
    
PEHDOM
Это потому что вы делаете self.pole_vivod.moveCursor(QtGui.QTextCursor.Start) тоесть каждый раз пр поиске вы возвращаете курсор на начало документа, вот оно вам и ищет каждый раз с начала. закаментите его для начала и увидите.
Для поиска в обратную сторону, нужно в find указать второй аргумент QTextDocument.FindBackward
http://doc.crossplatform.ru/qt/4.7.x/qtextedit.html#find
Kyrym
PEHDOM
Для поиска в обратную сторону, нужно в find указать второй аргумент QTextDocument.FindBackward
Такого вопроса не было )))
PEHDOM
Это потому что вы делаете self.pole_vivod.moveCursor(QtGui.QTextCursor.Start) то есть каждый раз пр поиске вы возвращаете курсор на начало документа, вот оно вам и ищет каждый раз с начала. закаментите его для начала и увидите.
self.pole_vivod.moveCursor(QtGui.QTextCursor.Start) - эта строчка написана не просто так, без неё поиск становится не правильным.
Попробуйте следующую задачу. Нам надо найти текст “кон”, результатом поиска должен стать “Константин” - это самое первое слово. Однако, когда мы введём “ко”, то будет выделено слово “колокол” - это второе вхождение “ко”, потом добавляем букву “н” и получаем слово “Кондрат” - это второе вхождение “кон”, а не первое. Напомню, что найтись должен был “Константин”.

Я вижу решение своей задачи через создание списка всех вхождений искомого текста, ну и работа с индексами этого списка. Однако, может есть какой-то стандартный простой метод?
Kyrym
Ладно. Пока сделал поиск так, но работает по нажатию на кнопки:
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox, QFileDialog, QTextDocument)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
tx = '''Константин бежал по дорожке, а потом колол дрова.
Кондрат собирал корения. На улице стоял колотун.
Иван же лежал в гамаке и пил кофе с конфетами.
ваер  р
вп
фп пр
ко
афвп
ырап
авпопр
рпавап
фпре
ре р пар
ер екр
рвек'''
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(600, 250) # шир / выс окна
        self.setWindowTitle('Поиск текста') # Заголовок
        # ПЕРЕМЕННЫЕ КЛАССА
        self.find_index = 0
        # БЛОК РАЗМЕТКИ
        #grid_os = QGridLayout()
        vbox = QVBoxLayout()
        # ---
        self.pole_vivod = QTextEdit('')
        self.pole_vivod.setStyleSheet(sss_vivod)
        self.pole_vivod.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction) # QtCore.Qt.TextEditorInteraction
        vbox.addWidget(self.pole_vivod)
        # ---
        grid_UT = QGridLayout()
        vbox.addLayout(grid_UT)
        # --- --- поиск ---
        self.btn_find_clear = QtGui.QPushButton('X')
        self.btn_find_clear.clicked.connect(self.on_find_clear)
        grid_UT.addWidget(self.btn_find_clear, 1,0)
        # ---
        self.btn_find_backward = QtGui.QPushButton('◄')
        self.btn_find_backward.clicked.connect(self.on_find_backward)
        grid_UT.addWidget(self.btn_find_backward, 1,1)
        # ---
        self.btn_find_forward = QtGui.QPushButton('►')
        self.btn_find_forward.clicked.connect(self.on_find_forward)
        grid_UT.addWidget(self.btn_find_forward, 1,2)
        # ---
        self.pole_find = QLineEdit(self)
        self.pole_find.setToolTip('Поиск текста')
        grid_UT.addWidget(self.pole_find, 1,3,1,10)
        # ---        
        self.check_find_r = QtGui.QCheckBox("Р")
        self.check_find_r.setToolTip('Учёт регистра')
        grid_UT.addWidget(self.check_find_r, 1,14)
        # настройка:
        grid_UT.setColumnStretch(10, 1)
        for i in range(10):
            grid_UT.setColumnMinimumWidth(i, 10) # индекс / высота
        # --- --- end: поиск ---
        
        # ---
        self.setLayout(vbox)
        # --- ---
        Window.on_start(self)
    # ЛОГИКА
    
    def on_start(self):        
        self.pole_vivod.append(str(tx))
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
    # === >>> ПОИСК ТЕКСТА ===
    def on_find_forward(self): # поиск вперёд
        text = self.pole_find.text()
        check_find_r = self.check_find_r.isChecked()
        if check_find_r == 0: # без регистра
            self.pole_vivod.find(text)
        else:
            self.pole_vivod.find(text, QTextDocument.FindCaseSensitively)
    def on_find_backward(self): # поиск назад
        text = self.pole_find.text()
        check_find_r = self.check_find_r.isChecked()
        if check_find_r == 0: # без регистра
            self.pole_vivod.find(text, QTextDocument.FindBackward)
        else:
            self.pole_vivod.find(text, QTextDocument.FindBackward | QTextDocument.FindCaseSensitively)
    def on_find_clear(self): # очистить поиск
        self.pole_find.clear()
        cursor = self.pole_vivod.textCursor()
        posit = cursor.position() # позиц курсора
        cursor.movePosition(posit) # происходит сброс выделения        
        self.pole_vivod.setTextCursor(cursor)
        
    # === >>> END: ПОИСК ТЕКСТА === 
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window()   
    window.show()
    sys.exit(app.exec_())
    
PEHDOM
Kyrym
эта строчка написана не просто так, без неё поиск становится не правильным.
нету “неправильного” поиска, есть логика вашей программы, которую вы пока не смогли ясно описать. Вы спросили как сделать чтобы оно искало следующее входжение, я ответил, что пока вы в начале каждого поска делаете moveCursor(QtGui.QTextCursor.Start) оно всегда будет искать первое вхождение. как вы это реализуете в вашем случае, зависит только от вас.Вам нужно или писать три метода для поиска: поиск сначала, поиск следующего и поиск предыдущего, или в on_find_text добавить аргумент и в зависимости от него делать поиск или сначала или с тек-позиции.
типа такого:
 ....
    # === >>> ПОИСК ТЕКСТА ===
    def on_find_text(self, text, opt=0):
        '''
        opt:
            0 искать с начала текста
            1 искать вперед с тек. позиции
            2 искать назад с тек позиции
        '''
        if opt == 0:
            self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
            self.pole_vivod.find(text)
        elif opt == 1:
            self.pole_vivod.find(text)
        elif opt == 2:
            self.pole_vivod.find(text, QTextDocument.FindBackward)
    def on_find_forward(self): # поиск вперёд
        text = self.pole_find.text()
        self.on_find_text(text, 1)
    def on_find_backward(self): # поиск назад
        text = self.pole_find.text()
        self.on_find_text(text, 2)
...
Kyrym
Да, меня тут осенило, если совместить мой первый код и второй, то получится то, что нужно. Ну собственно, уже слепил, работает.
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox, QFileDialog, QTextDocument)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
tx = '''Константин бежал по дорожке, а потом колол дрова.
Кондрат собирал корения. На улице стоял колотун.
Иван же лежал в гамаке и пил кофе с конфетами.
ваер  р
вп
фп пр
ко
афвп
ырап
авпопр
рпавап
фпре
ре р пар
ер екр
рвек'''
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(600, 250) # шир / выс окна
        self.setWindowTitle('Поиск текста') # Заголовок
        # БЛОК РАЗМЕТКИ
        #grid_os = QGridLayout()
        vbox = QVBoxLayout()
        # ---
        self.pole_vivod = QTextEdit('')
        self.pole_vivod.setStyleSheet(sss_vivod)
        self.pole_vivod.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction) # QtCore.Qt.TextEditorInteraction
        vbox.addWidget(self.pole_vivod)
        # ---
        grid_UT = QGridLayout()
        vbox.addLayout(grid_UT)
        # --- --- поиск ---
        self.btn_find_clear = QtGui.QPushButton('X')
        self.btn_find_clear.clicked.connect(self.on_find_clear)
        grid_UT.addWidget(self.btn_find_clear, 1,0)
        # ---
        self.btn_find_backward = QtGui.QPushButton('◄')
        self.btn_find_backward.clicked.connect(self.on_find_backward)
        grid_UT.addWidget(self.btn_find_backward, 1,1)
        # ---
        self.btn_find_forward = QtGui.QPushButton('►')
        self.btn_find_forward.clicked.connect(self.on_find_forward)
        grid_UT.addWidget(self.btn_find_forward, 1,2)
        # ---
        self.pole_find = QLineEdit(self)
        self.pole_find.setToolTip('Поиск текста')
        self.pole_find.textChanged.connect(self.on_find_text)
        grid_UT.addWidget(self.pole_find, 1,3,1,10)
        # ---        
        self.check_find_r = QtGui.QCheckBox("Р")
        self.check_find_r.setToolTip('Учёт регистра')
        grid_UT.addWidget(self.check_find_r, 1,14)
        # настройка:
        grid_UT.setColumnStretch(10, 1)
        for i in range(10):
            grid_UT.setColumnMinimumWidth(i, 10) # индекс / высота
        # --- --- end: поиск ---
        
        # ---
        self.setLayout(vbox)
        # --- ---
        Window.on_start(self)
    # ЛОГИКА
    
    def on_start(self):        
        self.pole_vivod.append(str(tx))
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
    # === >>> ПОИСК ТЕКСТА ===
    def on_find_text(self, text, opt=0):
        check_find_r = self.check_find_r.isChecked()
        if opt == 0:
            self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
        if check_find_r == 0: # без регистра
            if opt == 0 or opt == 1:
                self.pole_vivod.find(text)
            else:
                self.pole_vivod.find(text, QTextDocument.FindBackward)
        else: # с регистром
            if opt == 0 or opt == 1:
                self.pole_vivod.find(text, QTextDocument.FindCaseSensitively)            
            else:
                self.pole_vivod.find(text, QTextDocument.FindBackward | QTextDocument.FindCaseSensitively)
            
        
    def on_find_forward(self): # поиск вперёд
        text = self.pole_find.text()
        self.on_find_text(text, 1)
    def on_find_backward(self): # поиск назад
        text = self.pole_find.text()
        self.on_find_text(text, 2)
    def on_find_clear(self): # очистить поиск
        self.pole_find.blockSignals(1) # блокировка сигналов
        self.pole_find.clear()
        self.pole_find.blockSignals(0) # отмена блокировки сигналов
        cursor = self.pole_vivod.textCursor()
        posit = cursor.position() # позиц курсора
        cursor.movePosition(posit) # происходит сброс выделения        
        self.pole_vivod.setTextCursor(cursor)
        
    # === >>> END: ПОИСК ТЕКСТА === 
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window()   
    window.show()
    sys.exit(app.exec_())
    
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB