#c #qt #qslider
Вопрос:
Комментарии:
1. В чем проблема с тем, чтобы ручка была просто такой полой?
2. @hyde привет, если он прямо настроен на полый, вы увидите канавку ниже.
3. Итак, вы хотите, чтобы полая часть «просвечивала» канавку. Если это сложное требование, вам, возможно , придется реализовать свой собственный рисунок, сублиссировав
QAbstractScrollbar
или простоQScrollBar
(или, если это пользовательский интерфейс QML, просто создайте пользовательский компонент полосы прокрутки в QML, не очень сложно и хорошее упражнение в QML).4. @Parisa.H.R QSlider принадлежит QtWidgets
5. @Parisa.H.R Я хочу реализовать это на c .
Ответ №1:
Ознакомившись с документацией QStyle
, я решил использовать QStyle
для перерисовки QSlider
, чтобы добиться желаемого эффекта. Вот код реализации.
# coding:utf-8
from PyQt5.QtCore import QSize, Qt, pyqtSignal, QPoint, QRectF
from PyQt5.QtGui import QColor, QMouseEvent, QPainter, QPainterPath
from PyQt5.QtWidgets import (QProxyStyle, QSlider, QStyle, QStyleOptionSlider,
QWidget)
class HollowHandleStyle(QProxyStyle):
""" 滑块中空样式 """
def __init__(self, config: dict = None):
"""
Parameters
----------
config: dict
样式配置
"""
super().__init__()
self.config = {
"groove.height": 3,
"sub-page.color": QColor(255, 255, 255),
"add-page.color": QColor(255, 255, 255, 64),
"handle.color": QColor(255, 255, 255),
"handle.ring-width": 4,
"handle.hollow-radius": 6,
"handle.margin": 4
}
config = config if config else {}
self.config.update(config)
# 计算 handle 的大小
w = self.config["handle.margin"] self.config["handle.ring-width"]
self.config["handle.hollow-radius"]
self.config["handle.size"] = QSize(2*w, 2*w)
def subControlRect(self, cc: QStyle.ComplexControl, opt: QStyleOptionSlider, sc: QStyle.SubControl, widget: QWidget):
""" 返回子控件所占的矩形区域 """
if cc != self.CC_Slider or opt.orientation != Qt.Horizontal or sc == self.SC_SliderTickmarks:
return super().subControlRect(cc, opt, sc, widget)
rect = opt.rect
if sc == self.SC_SliderGroove:
h = self.config["groove.height"]
grooveRect = QRectF(0, (rect.height()-h)//2, rect.width(), h)
return grooveRect.toRect()
elif sc == self.SC_SliderHandle:
size = self.config["handle.size"]
x = self.sliderPositionFromValue(
opt.minimum, opt.maximum, opt.sliderPosition, rect.width())
# 解决滑块跑出滑动条的情况
x *= (rect.width()-size.width())/rect.width()
sliderRect = QRectF(x, 0, size.width(), size.height())
return sliderRect.toRect()
def drawComplexControl(self, cc: QStyle.ComplexControl, opt: QStyleOptionSlider, painter: QPainter, widget: QWidget):
""" 绘制子控件 """
if cc != self.CC_Slider or opt.orientation != Qt.Horizontal:
return super().drawComplexControl(cc, opt, painter, widget)
grooveRect = self.subControlRect(cc, opt, self.SC_SliderGroove, widget)
handleRect = self.subControlRect(cc, opt, self.SC_SliderHandle, widget)
painter.setRenderHints(QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
# 绘制滑槽
painter.save()
painter.translate(grooveRect.topLeft())
# 绘制划过的部分
w = handleRect.x()-grooveRect.x()
h = self.config['groove.height']
painter.setBrush(self.config["sub-page.color"])
painter.drawRect(0, 0, w, h)
# 绘制未划过的部分
x = w self.config['handle.size'].width()
painter.setBrush(self.config["add-page.color"])
painter.drawRect(x, 0, grooveRect.width()-w, h)
painter.restore()
# 绘制滑块
ringWidth = self.config["handle.ring-width"]
hollowRadius = self.config["handle.hollow-radius"]
radius = ringWidth hollowRadius
path = QPainterPath()
path.moveTo(0, 0)
center = handleRect.center() QPoint(1, 1)
path.addEllipse(center, radius, radius)
path.addEllipse(center, hollowRadius, hollowRadius)
handleColor = self.config["handle.color"] # type:QColor
handleColor.setAlpha(255 if opt.activeSubControls !=
self.SC_SliderHandle else 153)
painter.setBrush(handleColor)
painter.drawPath(path)
# 滑块按下
if widget.isSliderDown():
handleColor.setAlpha(255)
painter.setBrush(handleColor)
painter.drawEllipse(handleRect)
Вот пример того, как использовать HollowHandleStyle
:
# coding:utf-8
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QApplication, QWidget, QSlider
class Demo(QWidget):
def __init__(self):
super().__init__()
self.resize(300, 200)
self.setStyleSheet("Demo{background: rgb(34, 180, 127)}")
style = {
"sub-page.color": QColor(70, 23, 180),
"handle.ring-width": 4,
"handle.hollow-radius": 6,
"handle.margin": 4
}
self.slider = QSlider(Qt.Horizontal, self)
self.slider.setStyle(HollowHandleStyle(style))
self.slider.resize(200, 28)
self.slider.move(50, 100)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Demo()
w.show()
sys.exit(app.exec_())
На следующем рисунке показан конечный эффект:
Ответ №2:
вы можете сделать фон Генделя прозрачным и установить для него границу по таблице стилей, но таким образом вы увидите линию слайдера, если вы выберете цвет фона слайдера таким же, как и его бэкэнд, вы можете исправить его с помощью таблицы стилей, иначе вам следует написать его краской и создать свой собственный слайдер.
QSlider::groove:horizontal {
border-radius: 1px;
height: 2px;
margin: 20px;
background-color: rgb(52, 59, 72);
}
QSlider::groove:horizontal:hover {
background-color: rgb(55, 62, 76);
}
QSlider::handle:horizontal {
background-color: transparent;
border: 4px solid black;
height: 22px;
width: 22px;
margin: -14px 0;
border-radius: 14px;
padding: -14px 0px;
}
код пользовательского интерфейса :
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>561</width>
<height>238</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSlider" name="horizontalSlider">
<property name="minimumSize">
<size>
<width>0</width>
<height>70</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QSlider::groove:horizontal {
border-radius: 1px;
height: 2px;
margin: 20px;
background-color: rgb(52, 59, 72);
}
QSlider::groove:horizontal:hover {
background-color: rgb(55, 62, 76);
}
QSlider::handle:horizontal {
background-color: white;
border: 4px solid black;
height: 22px;
width: 22px;
margin: -14px 0;
border-radius: 14px;
padding: -14px 0px;
}
</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>561</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>