在 PyQt 中将鼠标悬停在 link 上时更改文本颜色
Change Text color when hovered over a link in PyQt
我试图在 QLabel 中将鼠标悬停在 link 上时更改文本的颜色。我无法使用PyQt提供的标签来实现,所以我尝试通过继承QLabel来创建自定义标签。
这是我试过的代码,但这不能正常工作:
from PyQt5 import QtGui, QtCore, QtWidgets
import sys
class LinkLabel(QtWidgets.QLabel):
def __init__(self, link=""):
super(LinkLabel, self).__init__()
self.setText('<a href="http://whosebug.com/" style="color: black; font: 14px; text-decoration: None;">'
'Whosebug</a>')
self.setFixedSize(100, 50)
# self.linkHovered.connect(lambda : print("Hovered"))
self.linkActivated.connect(self.reDirect)
#self.setMouseTracking(True)
def reDirect(self, linkStr):
QtGui.QDesktopServices.openUrl(QtCore.QUrl(linkStr))
def mouseMoveEvent(self, event):
print(self.fontMetrics().boundingRect("Whosebug"), event.pos())
if self.fontMetrics().boundingRect("Whosebug").contains(event.pos()):
print("Hovered")
self.setText('<a href="http://whosebug.com/" style="color: blue; font: 14px; text-decoration: None;">'
'Whosebug</a>')
else:
self.setText('<a href="http://whosebug.com/" style="color: black; font: 14px; text-decoration: None;">'
'Whosebug</a>')
super(LinkLabel, self).mouseMoveEvent(event)
# def enterEvent(self, event):
# print("YES", self.fontMetrics().boundingRect(self.text()))
# if self.fontMetrics().boundingRect(self.text()).contains(event.pos()):
# print("Hovered")
# self.setText('<a href="http://whosebug.com/" style="color: blue; font: 14px;">'
# 'SignUp</a>')
# # self.fontMetrics().tightBoundingRect()
# super(LinkLabel, self).enterEvent(event)
#
# def leaveEvent(self, event):
# if not self.fontMetrics().boundingRect(self.text()).contains():
# self.setText('<a href="http://whosebug.com/" style="color: black; font: 14px;">'
# 'SignUp</a>')
#
# super(LinkLabel, self).leaveEvent(event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.layout().addWidget(LinkLabel())
def main():
app = QtWidgets.QApplication(sys.argv)
win =MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我试过 QLabel.linkHovered.connect()
但问题是一旦悬停它就会改变颜色并且不会重置回原来的颜色。评论部分都是我试过的。
它不能正常工作,因为标签居中,而你对 boundingRect()
的调用显然不是:
Returns the rectangle that is covered by ink if character ch were to be drawn at the origin of the coordinate system.
此外,您正在使用更大的字体,而 fontMetrics 对此一无所知,因为它基于小部件的 font()
。
解决方案是使用正确的 boundingRect() 实现,并根据您要使用的字体构造字体指标:
def checkHover(self, pos=None):
if pos is None:
pos = self.mapFromGlobal(QtGui.QCursor.pos())
font = self.font()
font.setPixelSize(14)
fm = QtGui.QFontMetrics(font)
textRect = fm.boundingRect(self.rect(), self.alignment(), "Whosebug")
self.setText('''
<a href="{link}" style="color: {color}; font: 14px; text-decoration: None;">
{alias}</a>'''.format(
link='https://whosebug.com',
alias='Whosebug',
color='blue' if pos in textRect else 'black',
))
def enterEvent(self, event):
self.checkHover()
super(LinkLabel, self).enterEvent(event)
def mouseMoveEvent(self, event):
self.checkHover(event.pos())
super(LinkLabel, self).mouseMoveEvent(event)
def leaveEvent(self, event):
self.checkHover()
super(LinkLabel, self).leaveEvent(event)
请注意,我使用 setPixelSize()
是因为您以像素为单位设置字体大小,而您最好使用点代替,因为它们与设备无关(这是字体渲染的首选做法)。
我试图在 QLabel 中将鼠标悬停在 link 上时更改文本的颜色。我无法使用PyQt提供的标签来实现,所以我尝试通过继承QLabel来创建自定义标签。
这是我试过的代码,但这不能正常工作:
from PyQt5 import QtGui, QtCore, QtWidgets
import sys
class LinkLabel(QtWidgets.QLabel):
def __init__(self, link=""):
super(LinkLabel, self).__init__()
self.setText('<a href="http://whosebug.com/" style="color: black; font: 14px; text-decoration: None;">'
'Whosebug</a>')
self.setFixedSize(100, 50)
# self.linkHovered.connect(lambda : print("Hovered"))
self.linkActivated.connect(self.reDirect)
#self.setMouseTracking(True)
def reDirect(self, linkStr):
QtGui.QDesktopServices.openUrl(QtCore.QUrl(linkStr))
def mouseMoveEvent(self, event):
print(self.fontMetrics().boundingRect("Whosebug"), event.pos())
if self.fontMetrics().boundingRect("Whosebug").contains(event.pos()):
print("Hovered")
self.setText('<a href="http://whosebug.com/" style="color: blue; font: 14px; text-decoration: None;">'
'Whosebug</a>')
else:
self.setText('<a href="http://whosebug.com/" style="color: black; font: 14px; text-decoration: None;">'
'Whosebug</a>')
super(LinkLabel, self).mouseMoveEvent(event)
# def enterEvent(self, event):
# print("YES", self.fontMetrics().boundingRect(self.text()))
# if self.fontMetrics().boundingRect(self.text()).contains(event.pos()):
# print("Hovered")
# self.setText('<a href="http://whosebug.com/" style="color: blue; font: 14px;">'
# 'SignUp</a>')
# # self.fontMetrics().tightBoundingRect()
# super(LinkLabel, self).enterEvent(event)
#
# def leaveEvent(self, event):
# if not self.fontMetrics().boundingRect(self.text()).contains():
# self.setText('<a href="http://whosebug.com/" style="color: black; font: 14px;">'
# 'SignUp</a>')
#
# super(LinkLabel, self).leaveEvent(event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.layout().addWidget(LinkLabel())
def main():
app = QtWidgets.QApplication(sys.argv)
win =MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我试过 QLabel.linkHovered.connect()
但问题是一旦悬停它就会改变颜色并且不会重置回原来的颜色。评论部分都是我试过的。
它不能正常工作,因为标签居中,而你对 boundingRect()
的调用显然不是:
Returns the rectangle that is covered by ink if character ch were to be drawn at the origin of the coordinate system.
此外,您正在使用更大的字体,而 fontMetrics 对此一无所知,因为它基于小部件的 font()
。
解决方案是使用正确的 boundingRect() 实现,并根据您要使用的字体构造字体指标:
def checkHover(self, pos=None):
if pos is None:
pos = self.mapFromGlobal(QtGui.QCursor.pos())
font = self.font()
font.setPixelSize(14)
fm = QtGui.QFontMetrics(font)
textRect = fm.boundingRect(self.rect(), self.alignment(), "Whosebug")
self.setText('''
<a href="{link}" style="color: {color}; font: 14px; text-decoration: None;">
{alias}</a>'''.format(
link='https://whosebug.com',
alias='Whosebug',
color='blue' if pos in textRect else 'black',
))
def enterEvent(self, event):
self.checkHover()
super(LinkLabel, self).enterEvent(event)
def mouseMoveEvent(self, event):
self.checkHover(event.pos())
super(LinkLabel, self).mouseMoveEvent(event)
def leaveEvent(self, event):
self.checkHover()
super(LinkLabel, self).leaveEvent(event)
请注意,我使用 setPixelSize()
是因为您以像素为单位设置字体大小,而您最好使用点代替,因为它们与设备无关(这是字体渲染的首选做法)。