在 PyQt5 中获取滚动条缩略图的 size/width?
Getting the size/width of a scrollbar thumb in PyQt5?
比如说,你有一个 PyQt5 滚动条:
我想以编程方式找到滚动条的宽度 "thumb"(编辑:在 http://pyqt.sourceforge.net/Docs/PyQt4/qscrollbar.html 中称为 "slider"),以及它的位置;我猜一开始像素是 "natural" 单位。
从上图中,我猜想 start
始终为 0 - 但我能否获取 left
、right
、width
(虽然,如果我们有 left
和 right
,width
是平凡的 right-left
); end
以像素为单位?
我知道存在 QScrollBar
的 .value()
、pageStep()
和 singleStep()
,但我无法确定它们是否与上述尺寸(以像素为单位)相关.
(如果滚动条需要 PyQt5 示例,请参见我在 Have tabs keep focus on mousewheel over them in a PyQt5 scrollarea? 中发布的代码)
在这种情况下,您必须使用QStyle() 的subControlRect() 方法来获取您可以从中获取所需信息的矩形。
在下面的示例中,我创建了 QScrollBar 的自定义 class,每当滑块的位置发生变化或 QScrollBar 的大小时,它都会通过信号发出该信息。
from PyQt5 import QtCore, QtGui, QtWidgets
class Scrollbar(QtWidgets.QScrollBar):
geometryChanged = QtCore.pyqtSignal(int, int, int, int, int)
def __init__(self, parent=None):
super(Scrollbar, self).__init__(parent)
self.sliderMoved.connect(self.calculate_geometry)
def resizeEvent(self, event):
self.calculate_geometry()
super(Scrollbar, self).resizeEvent(event)
def calculate_geometry(self):
opt = QtWidgets.QStyleOptionSlider()
self.initStyleOption(opt)
gr = self.style().subControlRect(QtWidgets.QStyle.CC_ScrollBar, opt,
QtWidgets.QStyle.SC_ScrollBarGroove, self)
sr = self.style().subControlRect(QtWidgets.QStyle.CC_ScrollBar, opt,
QtWidgets.QStyle.SC_ScrollBarSlider, self)
start = gr.left() if self.orientation() == QtCore.Qt.Horizontal else gr.top()
left = sr.left() if self.orientation() == QtCore.Qt.Horizontal else sr.top()
right = sr.right() if self.orientation() == QtCore.Qt.Horizontal else sr.bottom()
width = sr.width() if self.orientation() == QtCore.Qt.Horizontal else sr.height()
end = gr.right() if self.orientation() == QtCore.Qt.Horizontal else gr.bottom()
self.geometryChanged.emit(start, left, width, right, end)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
hlayv = QtWidgets.QHBoxLayout()
hlayv.addWidget(QtWidgets.QLabel("start: "))
self._start_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._start_label_v)
hlayv.addWidget(QtWidgets.QLabel("left: "))
self._left_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._left_label_v)
hlayv.addWidget(QtWidgets.QLabel("width: "))
self._width_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._width_label_v)
hlayv.addWidget(QtWidgets.QLabel("right: "))
self._right_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._right_label_v)
hlayv.addWidget(QtWidgets.QLabel("end: "))
self._end_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._end_label_v)
hlayh = QtWidgets.QHBoxLayout()
hlayh.addWidget(QtWidgets.QLabel("start: "))
self._start_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._start_label_h)
hlayh.addWidget(QtWidgets.QLabel("left: "))
self._left_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._left_label_h)
hlayh.addWidget(QtWidgets.QLabel("width: "))
self._width_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._width_label_h)
hlayh.addWidget(QtWidgets.QLabel("right: "))
self._right_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._right_label_h)
hlayh.addWidget(QtWidgets.QLabel("end: "))
self._end_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._end_label_h)
self.scrollarea = QtWidgets.QScrollArea()
content_widget = QtWidgets.QLabel()
content_widget.setStyleSheet('''background-color : red;''')
content_widget.setFixedSize(1000, 1000)
self.scrollarea.setWidget(content_widget)
hscrollbar = Scrollbar()
hscrollbar.geometryChanged.connect(self.on_vertical_geometryChanged)
self.scrollarea.setHorizontalScrollBar(hscrollbar)
self.scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
vscrollbar =Scrollbar()
self.scrollarea.setVerticalScrollBar(vscrollbar)
vscrollbar.geometryChanged.connect(self.on_horizontal_geometryChanged)
self.scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
vlay = QtWidgets.QVBoxLayout(self)
vlay.addWidget(QtWidgets.QLabel("<b>Vertical: </b>"))
vlay.addLayout(hlayv)
vlay.addWidget(QtWidgets.QLabel("<b>Horizontal: </b>"))
vlay.addLayout(hlayh)
vlay.addWidget(self.scrollarea)
@QtCore.pyqtSlot(int, int, int, int, int)
def on_vertical_geometryChanged(self, start, left, width, right, end):
self._start_label_v.setNum(start)
self._left_label_v.setNum(left)
self._width_label_v.setNum(width)
self._right_label_v.setNum(right)
self._end_label_v.setNum(end)
QtCore.pyqtSlot(int, int, int, int, int)
def on_horizontal_geometryChanged(self, start, left, width, right, end):
self._start_label_h.setNum(start)
self._left_label_h.setNum(left)
self._width_label_h.setNum(width)
self._right_label_h.setNum(right)
self._end_label_h.setNum(end)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
比如说,你有一个 PyQt5 滚动条:
我想以编程方式找到滚动条的宽度 "thumb"(编辑:在 http://pyqt.sourceforge.net/Docs/PyQt4/qscrollbar.html 中称为 "slider"),以及它的位置;我猜一开始像素是 "natural" 单位。
从上图中,我猜想 start
始终为 0 - 但我能否获取 left
、right
、width
(虽然,如果我们有 left
和 right
,width
是平凡的 right-left
); end
以像素为单位?
我知道存在 QScrollBar
的 .value()
、pageStep()
和 singleStep()
,但我无法确定它们是否与上述尺寸(以像素为单位)相关.
(如果滚动条需要 PyQt5 示例,请参见我在 Have tabs keep focus on mousewheel over them in a PyQt5 scrollarea? 中发布的代码)
在这种情况下,您必须使用QStyle() 的subControlRect() 方法来获取您可以从中获取所需信息的矩形。
在下面的示例中,我创建了 QScrollBar 的自定义 class,每当滑块的位置发生变化或 QScrollBar 的大小时,它都会通过信号发出该信息。
from PyQt5 import QtCore, QtGui, QtWidgets
class Scrollbar(QtWidgets.QScrollBar):
geometryChanged = QtCore.pyqtSignal(int, int, int, int, int)
def __init__(self, parent=None):
super(Scrollbar, self).__init__(parent)
self.sliderMoved.connect(self.calculate_geometry)
def resizeEvent(self, event):
self.calculate_geometry()
super(Scrollbar, self).resizeEvent(event)
def calculate_geometry(self):
opt = QtWidgets.QStyleOptionSlider()
self.initStyleOption(opt)
gr = self.style().subControlRect(QtWidgets.QStyle.CC_ScrollBar, opt,
QtWidgets.QStyle.SC_ScrollBarGroove, self)
sr = self.style().subControlRect(QtWidgets.QStyle.CC_ScrollBar, opt,
QtWidgets.QStyle.SC_ScrollBarSlider, self)
start = gr.left() if self.orientation() == QtCore.Qt.Horizontal else gr.top()
left = sr.left() if self.orientation() == QtCore.Qt.Horizontal else sr.top()
right = sr.right() if self.orientation() == QtCore.Qt.Horizontal else sr.bottom()
width = sr.width() if self.orientation() == QtCore.Qt.Horizontal else sr.height()
end = gr.right() if self.orientation() == QtCore.Qt.Horizontal else gr.bottom()
self.geometryChanged.emit(start, left, width, right, end)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
hlayv = QtWidgets.QHBoxLayout()
hlayv.addWidget(QtWidgets.QLabel("start: "))
self._start_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._start_label_v)
hlayv.addWidget(QtWidgets.QLabel("left: "))
self._left_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._left_label_v)
hlayv.addWidget(QtWidgets.QLabel("width: "))
self._width_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._width_label_v)
hlayv.addWidget(QtWidgets.QLabel("right: "))
self._right_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._right_label_v)
hlayv.addWidget(QtWidgets.QLabel("end: "))
self._end_label_v = QtWidgets.QLabel()
hlayv.addWidget(self._end_label_v)
hlayh = QtWidgets.QHBoxLayout()
hlayh.addWidget(QtWidgets.QLabel("start: "))
self._start_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._start_label_h)
hlayh.addWidget(QtWidgets.QLabel("left: "))
self._left_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._left_label_h)
hlayh.addWidget(QtWidgets.QLabel("width: "))
self._width_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._width_label_h)
hlayh.addWidget(QtWidgets.QLabel("right: "))
self._right_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._right_label_h)
hlayh.addWidget(QtWidgets.QLabel("end: "))
self._end_label_h = QtWidgets.QLabel()
hlayh.addWidget(self._end_label_h)
self.scrollarea = QtWidgets.QScrollArea()
content_widget = QtWidgets.QLabel()
content_widget.setStyleSheet('''background-color : red;''')
content_widget.setFixedSize(1000, 1000)
self.scrollarea.setWidget(content_widget)
hscrollbar = Scrollbar()
hscrollbar.geometryChanged.connect(self.on_vertical_geometryChanged)
self.scrollarea.setHorizontalScrollBar(hscrollbar)
self.scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
vscrollbar =Scrollbar()
self.scrollarea.setVerticalScrollBar(vscrollbar)
vscrollbar.geometryChanged.connect(self.on_horizontal_geometryChanged)
self.scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
vlay = QtWidgets.QVBoxLayout(self)
vlay.addWidget(QtWidgets.QLabel("<b>Vertical: </b>"))
vlay.addLayout(hlayv)
vlay.addWidget(QtWidgets.QLabel("<b>Horizontal: </b>"))
vlay.addLayout(hlayh)
vlay.addWidget(self.scrollarea)
@QtCore.pyqtSlot(int, int, int, int, int)
def on_vertical_geometryChanged(self, start, left, width, right, end):
self._start_label_v.setNum(start)
self._left_label_v.setNum(left)
self._width_label_v.setNum(width)
self._right_label_v.setNum(right)
self._end_label_v.setNum(end)
QtCore.pyqtSlot(int, int, int, int, int)
def on_horizontal_geometryChanged(self, start, left, width, right, end):
self._start_label_h.setNum(start)
self._left_label_h.setNum(left)
self._width_label_h.setNum(width)
self._right_label_h.setNum(right)
self._end_label_h.setNum(end)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())