如何在 PyQt5 标签中创建光标



我有一个 PyQt5 窗口,里面有一个带有文本的标签。

那里显示的文本来自 python 字符串变量。字符串由用户单击屏幕上的按钮构建,然后将字符串输出到该标签中的窗口。

到目前为止,我有一个退格键,可以删除字符串中的最后一个字符,但我也希望用户能够单击标签中字符前面的位置,然后能够删除该字符。

所以,我想知道如何做两件事。

  1. 如何根据用户单击获取字符串中的字符位置
  2. 我已经看到了一些这方面的示例,但是一旦用户单击该位置,我还想在该位置显示光标。

我想使用标签小部件来执行此操作 - 而不是使用文本输入字段。

有人有什么想法吗?

让 QLabel 像这样工作是很困难的(QLabel 比看起来更复杂).
单击后可以显示光标,这是通过设置textInteractionFlags属性来实现的:

self.label.setTextInteractionFlags(
QtCore.Qt.TextSelectableByMouse | QtCore.Qt.TextSelectableByKeyboard)

第一个标志是允许处理鼠标事件,而第二个标志允许在标签获得焦点后立即显示光标(例如,单击它后).
不幸的是,这不允许你获取光标位置(也不允许用户更改它);有一些方法(使用 QFontMetrics 和 QTextDocument),但你需要一个复杂的实现才能使其真正可靠。

解决方案是使用 QLineEdit 并覆盖keyPressEvent,这是每当按键发生时总是在小部件上调用的函数(并且它具有输入焦点)。考虑到数字输入似乎仍然需要,只需确保event.key()对应于数字的Qt.Key枚举,在这种情况下,调用基本实现.
您甚至可以通过正确设置其样式表来使其看起来与 QLabel 完全相同。

class CommandLineEdit(QtWidgets.QLineEdit):
allowedKeys = (
QtCore.Qt.Key_0, 
QtCore.Qt.Key_1, 
QtCore.Qt.Key_2, 
QtCore.Qt.Key_3, 
QtCore.Qt.Key_4, 
QtCore.Qt.Key_5, 
QtCore.Qt.Key_6, 
QtCore.Qt.Key_7, 
QtCore.Qt.Key_8, 
QtCore.Qt.Key_9, 
)
def __init__(self):
super().__init__()
self.setStyleSheet('''
CommandLineEdit {
border: none;
background: transparent;
}
''')
def keyPressEvent(self, event):
if event.key() in self.allowedKeys:
super().keyPressEvent(event)

然后,如果要以编程方式设置文本(也基于光标),下面是一个基本用法:

from functools import partial
class CommandTest(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.commandLineEdit = CommandLineEdit()
layout.addWidget(self.commandLineEdit)
keys = (
'QWERTYUIOP', 
'ASDFGHJKL', 
'ZXCVBNM'
)
backspaceButton = QtWidgets.QToolButton(text='<-')
enterButton = QtWidgets.QToolButton(text='Enter')
self.shiftButton = QtWidgets.QToolButton(text='Shift', checkable=True)
for row, letters in enumerate(keys):
rowLayout = QtWidgets.QHBoxLayout()
rowLayout.addStretch()
layout.addLayout(rowLayout)
for letter in letters:
btn = QtWidgets.QToolButton(text=letter)
rowLayout.addWidget(btn)
btn.clicked.connect(partial(self.typeLetter, letter))
rowLayout.addStretch()
if row == 0:
rowLayout.addWidget(backspaceButton)
elif row == 1:
rowLayout.addWidget(enterButton)
else:
rowLayout.addWidget(self.shiftButton)
spaceLayout = QtWidgets.QHBoxLayout()
layout.addLayout(spaceLayout)
spaceLayout.addStretch()
spaceButton = QtWidgets.QToolButton(minimumWidth=200)
spaceLayout.addWidget(spaceButton)
spaceLayout.addStretch()
backspaceButton.clicked.connect(self.commandLineEdit.backspace)
spaceButton.clicked.connect(lambda: self.typeLetter(' '))
def typeLetter(self, letter):
text = self.commandLineEdit.text()
pos = self.commandLineEdit.cursorPosition()
if not self.shiftButton.isChecked():
letter = letter.lower()
self.commandLineEdit.setText(text[:pos] + letter + text[pos:])
import sys
app = QtWidgets.QApplication(sys.argv)
w = CommandTest()
w.show()
sys.exit(app.exec_())

如您所见,您可以调用backspace()以清除最后一个字符(或选择),并且在typeLetter函数中,您需要的所有剩余功能:获取/设置文本和光标位置.
对于其他任何内容,只需研究完整的文档。

最新更新