Debounced Completer автоматически выбирает выделенную опцию, когда я прекращаю пролистывать результаты?Python

Программы на Python
Ответить
Anonymous
 Debounced Completer автоматически выбирает выделенную опцию, когда я прекращаю пролистывать результаты?

Сообщение Anonymous »

Я пытаюсь создать обновленный виджет Typeahead, который заполняется данными из моей базы данных. Когда я пытаюсь пролистать результаты запроса со стрелкой вниз, выделенный результат выбирается автоматически, когда я перестаю нажимать клавишу со стрелкой вниз.
Я просмотрел документацию по QCompleter и типу возвращаемого всплывающего окна, QAbstractItemView. QAbstractItemView, говорит Ctrl+клавиши со стрелками: «Изменяет текущий элемент, но не выбирает его». Однако когда я пытаюсь перемещаться, удерживая клавишу Ctrl, поведение не отличается.
Код моего виджета приведен ниже:
# Typeahead.h
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QCompleter
from utk_apis.sql_engine import SQLEngine
from PyQt5.QtCore import QStringListModel

from PyQt5.QtCore import QTimer, QStringListModel
from PyQt5.QtWidgets import QLineEdit, QCompleter, QAbstractItemView

class Typeahead(QLineEdit):
def __init__(self, parent=None):
super(Typeahead, self).__init__(parent)
self.results = []
self.selected_result = None
self.engine = None
self.current_index = -1
self.ignore_text_change = False
self.completer = QCompleter(self)

self.completer.setWidget(self)
self.completer.setCompletionMode(QCompleter.PopupCompletion)
self.completer.popup().setSelectionMode(
QAbstractItemView.SingleSelection
) # Single item selection in popup

self.setCompleter(self.completer)
self.completer.popup().setAlternatingRowColors(True)

# Create a timer for debouncing
self.debounce_timer = QTimer(self)
self.debounce_timer.setSingleShot(True) # Only trigger once after interval
self.debounce_timer.setInterval(300) # 300 ms debounce interval

# Connect the timeout of the timer to the emit_text_changed method
self.debounce_timer.timeout.connect(self.emit_text_changed)

# Connect the textChanged signal to start the debounce timer
self.textChanged.connect(self.start_debounce)

# Connect the completer's activated signal to set the selected item only when Enter is pressed
self.completer.activated.connect(self.on_completer_activated)

def start_debounce(self):
"""Start the debounce timer when the text changes."""
self.debounce_timer.start() # This starts or restarts the debounce timer

def emit_text_changed(self):
"""Fetch results and update completer when text changes."""
print(f'Emitting text changed event: {self.text()} Ignore text change: {self.ignore_text_change}')

if self.ignore_text_change is True:
self.ignore_text_change = False
return
if self.engine is None:
self.engine = SQLEngine(env=self.property("env"))

# Run the query to fetch data from the database
data = self.engine.run_query(self._build_query(), results_as_dict=True)

# Convert data to the list of results. Store for sharing with other Typeahead instances
self.results = [
{
"text": f"{row['primary_key_1']} ({row['primary_key_2']}, {row['primary_key_3']})",
"primary_key_1": row["primary_key_1"],
"primary_key_2": row["primary_key_2"],
"primary_key_3": row["primary_key_3"],
}
for row in data
]

# Update the completer with the new results
self.update_completer()

def update_completer(self):
"""Update the QCompleter with the new results."""
completer_model = QStringListModel([result["text"] for result in self.results])

#self.completer.model().setStringList(completer_model)
self.completer.setModel(completer_model)

# Set the width of the popup based on the longest string to avoid truncation
longest_string = max(
[len(result["text"]) for result in self.results], default=0
)

self.completer.popup().setMinimumWidth(
longest_string * 15
) # Adjust 7 to fit font size

# Manually open the completer dropdown
if self.results:
self.completer.complete() # Force the dropdown to show up again

def on_completer_activated(self, text):
"""Handle what happens when an item in the dropdown is selected."""
# Only set the text when the user selects an item by pressing Enter
selected_item = next(
(result for result in self.results if result["text"] == text), None
)
if selected_item:
self.setText(selected_item["text"])

def _build_query(self):
"""Build the SQL query for fetching suggestions."""
query = f"SELECT {','.join(self.property('primary_keys'))} FROM {self.property('targetTable')} WHERE {self.property('targetField')} LIKE '%{self.text()}%'"
return query



Подробнее здесь: https://stackoverflow.com/questions/791 ... ng-through
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»