python - 如果我只按任何字母(AZ,az)或数字(0 - 9),如何将焦点从 QListWidget 更改为 QLineEdit?
问题描述
面临将焦点从 QListWidget 更改为 QLineEdit 的问题。
如果我们从 QLineEdit 按down_arrow或up_arrow,焦点从 QLineEdit 变为 Qlistwidget,然后从 QListWidget 按left_arrow或back_space,焦点从 QListwidget 变为 QLineEdit。
假设焦点在 QListWidget,现在我按任何字母或数字( A -z 或 a -z 或 0 - 9),如何将焦点从 QListwidget 更改为 QLineEdit并在 QLineEdit 框中显示按下的键值。(例如,如果我从 QListWidget 按“H”,焦点从 QListWidget 更改为 QLineEdit,字符“H”出现在最后(第 n 个)位置)
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
item = ["Python", "Python 2.7", "Python 2.9", "Python 3.5", "Python 3.7", "National", "Zebra",
"Apple", "X Ray", "Boat", "Tiger", "Item001", "Item002", "Item003", "Item004", "Item005",
"001Item", "002Item", "003Item", "004Item", "005Item", "Ball", "Cat", "Dog", "Fish",
"Gold Fish", "Star Fish", "2821", "2822", "2823", "2811", "2812", "2813"]
flag = 2
class Event_Handler(QWidget):
def __init__(self):
super().__init__()
self.setMinimumSize(350, 600)
self.textbox = QLineEdit()
self.textbox.installEventFilter(self)
self.textbox.textChanged.connect(self.func_textbox_textchanged)
self.listbox_dummy = QListWidget()
self.listbox_dummy.addItems(item)
self.listbox = QListWidget()
self.listbox.installEventFilter(self)
self.listbox.addItems(item)
self.label_1 = QLabel("Item Starts With (Alt+S)")
self.label_2 = QLabel("Item Contains (Alt+C)")
self.label_3 = QLabel("Item Ends With (Alt+E)")
vbox1 = QVBoxLayout()
vbox1.addWidget(self.textbox)
vbox1.addWidget(self.listbox)
vbox1.addWidget(self.label_1)
vbox1.addWidget(self.label_2)
vbox1.addWidget(self.label_3)
self.setLayout(vbox1)
def func_textbox_textchanged(self):
global search_text, search_text_lenth, total_listbox_items, startitem_rowno, enditem_rowno, \
startitem_count, containitem_count, enditem_count, item_normal, item_startswith, item_contains, \
item_endswith, flag
search_text = self.textbox.text()
search_text_length = len(search_text)
item_normal = self.listbox_dummy.findItems("*", Qt.MatchWildcard)
item_startswith = self.listbox_dummy.findItems(search_text, Qt.MatchStartsWith)
item_contains = self.listbox_dummy.findItems(search_text, Qt.MatchContains)
item_endswith = self.listbox_dummy.findItems(search_text, Qt.MatchEndsWith)
k = 0
dummy_list = []
for i in item_contains:
if ((i.text().lower())[0:search_text_length]) == (search_text.lower()):
dummy_list.append(k)
startitem_rowno = (dummy_list[0])
enditem_rowno = (dummy_list[-1])
k = k + 1
startitem_count = len(item_startswith)
containitem_count = len(item_contains)
enditem_count = len(item_endswith)
if search_text_length == 1:
flag = 1
self.listbox.clear()
if flag == 1:
self.func_item_startswith()
elif flag == 2:
self.func_item_contains()
elif flag == 3:
self.func_item_endswith()
elif flag == 0:
self.func_item_contains()
else:
self.func_item_normal()
if startitem_count == 0:
flag = 2
self.func_item_contains()
def func_item_startswith(self):
global flag
flag = 1
self.listbox.clear()
if startitem_count > 0:
for item in item_startswith:
self.listbox.addItem(item.text())
else:
print("No Matching from start item")
def func_item_contains(self):
global flag
flag = 2
self.listbox.clear()
if containitem_count > 0:
for item in item_contains:
self.listbox.addItem(item.text())
else:
print("No Matching from contains item")
def func_item_endswith(self):
global flag
flag = 3
self.listbox.clear()
if enditem_count > 0:
for item in item_endswith:
self.listbox.addItem(item.text())
else:
print("No Matching from end item")
def func_item_normal(self, normal_count=None):
global falg
flag = 0
self.listbox.clear()
if normal_count > 0:
for item in item_normal:
self.listbox.addItem(item.text())
def eventFilter(self, source, event):
global startitem_rowno, enditem_rowno
if event.type() == QEvent.KeyPress and source is self.textbox:
if event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_S:
self.func_item_startswith()
return True
if event.key() == Qt.Key_C and event.modifiers() == Qt.AltModifier:
self.func_item_contains()
return True
if event.key() == Qt.Key_E and event.modifiers() == Qt.AltModifier:
self.func_item_endswith()
return True
if event.key() == Qt.Key_Down:
startitem_rowno = 0
if flag != 2:
startitem_rowno = 0
self.listbox.setFocus()
self.listbox.setCurrentRow(startitem_rowno)
if event.key() == Qt.Key_Up:
enditem_rowno = len(self.listbox) - 1
if flag != 2:
enditem_rowno = len(self.listbox) - 1
self.listbox.setFocus()
self.listbox.setCurrentRow(enditem_rowno)
if event.key() == Qt.Key_Return:
if len(self.listbox) == 1:
self.listbox.setCurrentRow(0)
self.textbox.setText(self.listbox.currentItem().text())
prin = self.listbox.currentItem().text()
if event.type() == QKeyEvent.KeyPress and source is self.listbox:
if event.key() == Qt.Key_Left or event.key() == Qt.Key_Backspace:
self.textbox.setFocus()
if event.key() == Qt.Key_Return:
self.textbox.setText(self.listbox.currentItem().text())
self.textbox.setFocus()
return super(Event_Handler, self).eventFilter(source, event)
if __name__ == '__main__':
myapp = QApplication(sys.argv)
mywin = Event_Handler()
mywin.show()
sys.exit(myapp.exec_())
解决方案
凭借我的 Python 和 Pyqt5 知识,我得到了一些解决方案,但我敢肯定,这不是 Pythonic 的方式。所以专家会指导我得到一个正确的pythonic方法。
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
flag = 1
search_text_length = 0
startitem_rowno = None
enditem_rowno = None
item = ["Python", "Python 2.7", "Python 2.9", "Python 3.5", "Python 3.7", "National", "Zebra",
"Apple", "X Ray", "Boat", "Tiger", "Item001", "Item002", "Item003", "Item004", "Item005",
"001Item", "002Item", "003Item", "004Item", "005Item", "Ball", "Cat", "Dog", "Fish",
"Gold Fish", "Star Fish", "2821", "2822", "2823", "2811", "2812", "2813"]
class TitleValidator(QValidator):
def validate(self, text, pos):
return QValidator.Acceptable, text.title(), pos
class Listbox_008(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("List Box Example")
self.func_mydesign()
self.func_layout()
self.func_load_data()
# ----------------------------------------------------------------------------------
def func_mydesign(self):
self.textbox_search = QLineEdit()
self.listbox_search = QListWidget()
self.listbox_dummy = QListWidget()
self.label_listbox_head = QLabel(" Available Items :")
self.label_listbox_head.setAlignment(Qt.AlignCenter)
self.label_noraml = QLabel("Available Items (Alt+A) :")
self.label_starts = QLabel("Items &Starts With (Alt+S) : ")
self.label_contains = QLabel("Items &Contains anywhere (Alt+C) : ")
self.label_ends = QLabel("Items &Ends With (Alt+E) : ")
self.label_noraml_count = QLabel("600")
self.label_starts_count = QLabel()
self.label_contains_count = QLabel()
self.label_ends_count = QLabel()
self.label_selected_item = QLabel("Selected Item")
self.label_listbox_head.setFont(QFont("Caliber", 10, QFont.Bold))
self.label_listbox_head.setAlignment(Qt.AlignCenter)
self.label_listbox_head.setStyleSheet("background-color:blue;border-radius:4px;padding:2px;color:white")
self.textbox_search.setFont(QFont("Caliber", 12, QFont.Bold))
self.textbox_search.setFixedHeight(50)
self.textbox_search.installEventFilter(self)
self.textbox_search.textChanged.connect(self.func_textbox_textchanged)
self.textbox_search.setStyleSheet(self.func_foucs_stylesheet_001())
validator = TitleValidator(self.textbox_search)
self.textbox_search.setValidator(validator)
self.listbox_search.installEventFilter(self)
self.listbox_search.setStyleSheet(self.func_foucs_stylesheet_001())
self.listbox_search.itemClicked.connect(self.listbox_clicked)
self.listbox_search.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.listbox_search.setFont(QFont("Arial", 10, QFont.Bold))
self.label_noraml.setStyleSheet(self.func_qlabel_stylesheet_001())
self.label_starts.setStyleSheet(self.func_qlabel_stylesheet_001())
self.label_contains.setStyleSheet(self.func_qlabel_stylesheet_001())
self.label_ends.setStyleSheet(self.func_qlabel_stylesheet_001())
self.label_noraml_count.setStyleSheet(self.func_qlabel_stylesheet_002())
self.label_starts_count.setStyleSheet(self.func_qlabel_stylesheet_002())
self.label_contains_count.setStyleSheet(self.func_qlabel_stylesheet_002())
self.label_ends_count.setStyleSheet(self.func_qlabel_stylesheet_002())
self.label_selected_item.setFont(QFont("Caliber", 8, QFont.Bold))
def func_layout(self):
layout_top = QVBoxLayout()
layout_top_1 = QHBoxLayout()
layout_top_2 = QHBoxLayout()
layout_top_3 = QVBoxLayout()
layout_top_1.addWidget(self.textbox_search)
layout_top_3.addWidget(self.label_listbox_head)
layout_top_2.addWidget(self.listbox_search)
layout_top.addLayout(layout_top_1)
layout_top.addLayout(layout_top_3)
layout_top.addLayout(layout_top_2)
layout_bot = QVBoxLayout()
layout_bot_1 = QFormLayout()
layout_bot_1.setVerticalSpacing(5)
layout_bot_1.setHorizontalSpacing(3)
layout_bot_1.addRow(self.label_noraml, self.label_noraml_count)
layout_bot_1.addRow(self.label_starts, self.label_starts_count)
layout_bot_1.addRow(self.label_contains, self.label_contains_count)
layout_bot_1.addRow(self.label_ends, self.label_ends_count)
layout_bot_2 = QHBoxLayout()
layout_bot_2.addStretch()
layout_bot_2.addWidget(self.label_selected_item)
layout_bot_2.addStretch()
layout_bot.addLayout(layout_bot_1)
layout_bot.addSpacing(10)
layout_bot.addLayout(layout_bot_2)
frame_top = QFrame()
frame_top.setObjectName("frame_top")
frame_top.setLayout(layout_top)
frame_bot = QFrame()
frame_bot.setObjectName("frame_bot")
frame_bot.setLayout(layout_bot)
layout_tot = QVBoxLayout()
layout_tot.addWidget(frame_top)
layout_tot.addWidget(frame_bot)
frame_tot = QFrame()
frame_tot.setObjectName("frame_tot")
# frame_tot.setFixedSize(500,700)
frame_tot.setStyleSheet(self.func_Qframe_stylesheet_001())
frame_tot.setLayout(layout_tot)
frame_tot.setFrameShape(QFrame.Box)
frame_tot.setFrameShadow(QFrame.Plain)
layout_main = QHBoxLayout()
layout_main.addWidget(frame_tot)
self.setLayout(layout_main)
def func_load_data(self):
global flag,startitem_rowno,enditem_rowno
self.listbox_dummy.addItems(item)
self.listbox_search.addItems(item)
self.label_noraml_count.setText("{}".format(len(self.listbox_search)))
startitem_rowno = 0
enditem_rowno = len(self.listbox_search)-1
def func_qlabel_stylesheet_001(self):
return """
QLabel{
font-family: Caliber; font-style: bold; font-size:10pt; font-weight:normal;
color:black; background-color:'Orange'; min-width:280px; qproperty-alignment:'AlignRight';
}
"""
def func_qlabel_stylesheet_002(self):
return """
QLabel{
font-family: Caliber; font-style: bold; font-size:10pt; font-weight:normal;
color:black; background-color:'Orange';min-width:100px; qproperty-alignment:'AlignLeft';
}
"""
def func_Qframe_stylesheet_001(self):
return """
QFrame#frame_bot {background-color:"orange"}
QFrame#frame_top {background-color:#fff}
QFrame#frame_tot {background-color:"light green"}
"""
def func_foucs_stylesheet_001(self):
return """
QLineEdit:focus {border:4px solid red; ;}
QListWidget:focus {border:20px solid red; border-style:;}
"""
def eventFilter(self, source, event):
global cursor_position,textbox_value
if event.type() == QEvent.KeyPress and source is self.textbox_search:
if event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_S:
flag = 1
self.func_item_startswith()
return True
if event.key() == Qt.Key_C and event.modifiers() == Qt.AltModifier:
flag = 2
self.func_item_contains()
return True
if event.key() == Qt.Key_E and event.modifiers() == Qt.AltModifier:
flag = 3
self.func_item_endswith()
return True
if event.key() == Qt.Key_Down:
self.listbox_search.setFocus()
self.listbox_search.setCurrentRow(startitem_rowno)
cursor_position = self.textbox_search.cursorPosition()
textbox_value = self.textbox_search.text()
if event.key() == Qt.Key_Up:
self.listbox_search.setCurrentRow(enditem_rowno)
self.listbox_search.setFocus()
cursor_position = self.textbox_search.cursorPosition()
textbox_value = self.textbox_search.text()
if event.key() == Qt.Key_Return:
if len(self.listbox_search) == 1:
self.listbox_search.setCurrentRow(0)
self.textbox_search.setText(self.listbox_search.currentItem().text())
prin = self.listbox_search.currentItem().text()
self.label_selected_item.setText("Selected Item : " + prin)
self.label_selected_item.adjustSize()
else:
self.label_selected_item.setText("Select One Item........")
self.label_selected_item.adjustSize()
if event.type() == QKeyEvent.KeyPress and source is self.listbox_search:
if event.key() == Qt.Key_Left or event.key() == Qt.Key_Backspace:
self.listbox_search.clearFocus()
self.textbox_search.setFocus()
elif event.key() == Qt.Key_Return:
prin = self.listbox_search.currentItem().text()
self.textbox_search.setText(self.listbox_search.currentItem().text())
self.label_selected_item.setText("Selected Item : " + prin)
self.label_selected_item.adjustSize()
self.textbox_search.setFocus()
else:
self.textbox_search.setFocus()
keyvalue = event.text()
self.textbox_search.setText(textbox_value+keyvalue)
self.textbox_search.setCursorPosition(cursor_position+1)
return super(Listbox_008, self).eventFilter(source, event)
def func_item_startswith(self):
global flag,startitem_rowno,enditem_rowno
flag = 1
startitem_rowno = 0
enditem_rowno = startitem_count - 1
self.listbox_search.clear()
self.label_listbox_head.setText("Item Start With")
if startitem_count > 0:
for item in item_startswith:
self.listbox_search.addItem(item.text())
else:
print("No Matching from start item")
def func_item_contains(self):
global flag,startitem_rowno,enditem_rowno
flag = 2
self.listbox_search.clear()
self.label_listbox_head.setText("Item Contains With")
if containitem_count > 0:
for item in item_contains:
self.listbox_search.addItem(item.text())
else:
print("No Matching from contains item")
dummy_list = []
k = 0
for i in item_contains:
if i.text().lower()[0:search_text_length] == search_text.lower():
dummy_list.append(k)
startitem_rowno = dummy_list[0]
enditem_rowno = dummy_list[-1]
k +=1
if len(dummy_list) == 0 :
startitem_rowno = 0
enditem_rowno = containitem_count-1
def func_item_endswith(self):
global flag, startitem_rowno, enditem_rowno
flag = 3
startitem_rowno = 0
enditem_rowno = enditem_count - 1
self.listbox_search.clear()
self.label_listbox_head.setText("Item Ends With")
if enditem_count > 0:
for item in item_endswith:
self.listbox_search.addItem(item.text())
else:
print("No Matching from end item")
def func_item_normal(self):
global falg,startitem_rowno,enditem_rowno
flag = 0
startitem_rowno = 0
enditem_rowno = normal_count - 1
self.listbox_search.clear()
self.label_listbox_head.setText("Available Items")
if normal_count > 0:
for item in item_normal:
self.listbox_search.addItem(item.text())
def func_textbox_textchanged(self, txt):
global search_text, search_text_length, total_listbox_item, availableitem_count, normal_count, startitem_count, \
containitem_count, enditem_count, item_normal, item_startswith, item_contains, item_endswith, flag,\
startitem_rowno, enditem_rowno
search_text = self.textbox_search.text()
search_text_length = len(search_text)
total_listbox_item = len(self.listbox_search)
item_normal = self.listbox_dummy.findItems("*", Qt.MatchWildcard)
item_startswith = self.listbox_dummy.findItems(search_text, Qt.MatchStartsWith)
item_contains = self.listbox_dummy.findItems(search_text, Qt.MatchContains)
item_endswith = self.listbox_dummy.findItems(search_text, Qt.MatchEndsWith)
normal_count = len(item_normal)
startitem_count = len(item_startswith)
containitem_count = len(item_contains)
enditem_count = len(item_endswith)
self.func_item_normal()
self.label_noraml_count.setText("{}".format(normal_count))
if search_text_length >= 1:
self.label_starts_count.setText("{}".format(startitem_count))
self.label_contains_count.setText("{}".format(containitem_count))
self.label_ends_count.setText("{}".format(enditem_count))
else:
flag = 1
self.label_starts_count.clear()
self.label_contains_count.clear()
self.label_ends_count.clear()
self.listbox_search.clear()
if flag == 1:
self.func_item_startswith()
elif flag == 2:
self.func_item_contains()
elif flag == 3:
self.func_item_endswith()
elif flag == 0:
self.func_item_contains()
else:
self.func_item_normal()
if search_text_length == 0:
self.label_listbox_head.setText("Available Items :")
self.label_listbox_head.adjustSize()
if startitem_count == 0:
flag = 2
self.func_item_contains()
def listbox_clicked(self, item):
self.textbox_search.setText(item.text())
self.textbox_search.setFocus()
# -----------------------------------------------------------------------------------
def main():
myapp = QApplication(sys.argv)
mywindow = Listbox_008()
width = mywindow.frameGeometry().width()
height = mywindow.frameGeometry().height()
# print("screensize",width)
# print("screensize",height)
# screenShape = QDesktopWidget().screenGeometry()
# mywindow.resize(screenShape.width(), screenShape.height())
# print("resolution",screenShape.width())
# print("resolution",screenShape.height())
mywindow.show()
sys.exit(myapp.exec_())
if __name__ == "__main__":
main()