Qt如何自定義滑動(dòng)條
最近要用到滑動(dòng)條,Qt自帶的QSlider雖然能滿足需求,但是操作起來(lái)有很多不舒服的地方,于是在它的基礎(chǔ)上改了改,分享給大家使用。
先放效果圖
在QSlider的基礎(chǔ)上,改變了樣式,繪制了刻度,增加了取整功能,只需要微調(diào)就能適應(yīng)各種需求。
1、頭文件
需要包含下面的東西
#include <QSlider> #include <QtCore> #include <QStylePainter> #include <QStyleOptionSlider> #include <QMouseEvent>
2、聲明
需要繼承QSlider,并重寫兩個(gè)鼠標(biāo)事件mousePressEvent和mouseReleaseEvent,使用paintEvent用來(lái)繪制刻度線,使用信號(hào)發(fā)送選中的數(shù)值。
class MySlider : public QSlider { Q_OBJECT public: MySlider(QWidget *parent = nullptr); ~MySlider(); signals: void sliderValue(float); private: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void paintEvent(QPaintEvent *ev); };
3、構(gòu)造函數(shù)
首先在構(gòu)造函數(shù)中配置控件的相關(guān)屬性,在此宏定義的幾個(gè)數(shù)值:nMin和nMax代表取值范圍,nSingleStep代表步長(zhǎng),nTick代表刻度間隔,nWidth和nHeight控制控件的大小。
通過(guò)設(shè)置Orientation為Horizontal,使控件為橫向。
#include "myslider.h" int nMin = 0; int nMax = 100; int nSingleStep = 10; int nTick = 10; //修改刻度個(gè)數(shù)改此數(shù)值 int nWidth = 200; int nHeight = 50; MySlider::MySlider(QWidget *parent): QSlider (parent) { setOrientation(Qt::Horizontal); setFixedSize(nWidth,nHeight); setMinimum(nMin); setMaximum(nMax); setSingleStep(nSingleStep); setTickInterval(nTick); setTickPosition(QSlider::TicksAbove);
4、設(shè)置樣式表
QSlider::groove控制背景樣式,QSlider::handle控制滑塊樣式,QSlider::sub-page控制劃過(guò)區(qū)域的樣式。
需要注意的是,qss和QSlider自帶的刻度線并不兼容,使用qss就不能顯示自帶的刻度線了,但是后文我提供了解決方法。
setStyleSheet("QSlider::groove:horizontal{height:12px; left:0px; right:0px; border:0px; border-radius:6px; background:rgb(242,242,242);} \ QSlider::handle:horizontal{width:24px; background:#1644B0; border-radius:12px; margin:-6px 0px;} \ QSlider::sub-page:horizontal{background:#4C85FB; border:0px; border-radius:6px;}"); }
5、重寫鼠標(biāo)點(diǎn)擊事件
之所以要這么做,是因?yàn)镼Slider的點(diǎn)擊效果是一格一格地移動(dòng),我希望滑塊能直接跳到指定位置,所以需要用到setValue。
void MySlider::mousePressEvent(QMouseEvent * event) { int pointPos = ((double)event->pos().x()) / (this->width() * (nMax - nMin) + nMin); if(pointPos != 0){ if(abs(pointPos - this->value()) > nTick){ this->setValue(pointPos); } } else{ QSlider::mousePressEvent(event); } }
6、重寫鼠標(biāo)釋放事件
因?yàn)橄M≈悼梢匀讉€(gè)固定的值,此處限定只能取0, 0.1, 0.2… 1這些值,所以在釋放時(shí)對(duì)當(dāng)前值四舍五入,然后讓滑塊移動(dòng)到相應(yīng)的位置。最后發(fā)出信號(hào)傳遞數(shù)值。
void MySlider::mouseReleaseEvent(QMouseEvent *event) { //獲取當(dāng)前點(diǎn)擊位置 int currentX = event->pos().x(); //獲取當(dāng)前點(diǎn)擊的位置占整個(gè)Slider的百分比 float per = currentX *1.0 /this->width(); //限制邊界 if(per > 1) per = 1; else if(per < 0) per = 0; //按步長(zhǎng)取整 per = (float)(qRound(per * 100 / nTick) * nTick) / 100; //利用算得的百分比得到具體數(shù)字 int value = per*(this->maximum() - this->minimum()) + this->minimum(); //設(shè)定滑動(dòng)條位置 this->setValue(value); //滑動(dòng)條移動(dòng)事件等事件也用到了mousePressEvent,加這句話是為了不對(duì)其產(chǎn)生影響,是的Slider能正常相應(yīng)其他鼠標(biāo)事件 QSlider::mousePressEvent(event); emit sliderValue(per); }
7、繪制刻度
前文提到了qss和QSlider刻度的沖突,所以這里我們直接使用paintEvent畫線。
修改宏定義的參數(shù)值,刻度的數(shù)量也會(huì)隨之變動(dòng)。
void MySlider::paintEvent(QPaintEvent *) { QStylePainter p(this); QStyleOptionSlider opt; initStyleOption(&opt); // 獲取滑塊的大小 QRect handle = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); // draw tick marks // do this manually because they are very badly behaved with style sheets int interval = tickInterval(); if (interval == 0) { interval = pageStep(); } if (tickPosition() != NoTicks) { for (int i = minimum(); i <= maximum(); i += interval) { int x = round((double)((double)((double)(i - this->minimum()) / (double)(this->maximum() - this->minimum())) * (double)(this->width() - handle.width()) + (double)(handle.width() / 2.0))) - 1; int h = 4; p.setPen(QColor("#a5a294")); if (tickPosition() == TicksBothSides || tickPosition() == TicksAbove) { int y = this->rect().top(); p.drawLine(x, y, x, y + h); } if (tickPosition() == TicksBothSides || tickPosition() == TicksBelow) { int y = this->rect().bottom(); p.drawLine(x, y, x, y - h); } } } // draw the slider (this is basically copy/pasted from QSlider::paintEvent) opt.subControls = QStyle::SC_SliderGroove; p.drawComplexControl(QStyle::CC_Slider, opt); // draw the slider handle opt.subControls = QStyle::SC_SliderHandle; p.drawComplexControl(QStyle::CC_Slider, opt); }
8、實(shí)際使用
拖動(dòng)或點(diǎn)擊滑動(dòng)條都會(huì)發(fā)出信號(hào),傳遞滑塊對(duì)應(yīng)的值。
所以在要使用的地方建立信號(hào)槽,就可以接收對(duì)應(yīng)滑動(dòng)條傳來(lái)的值并加以處理。
FaceThreshSlider = new MySlider(this); connect(FaceThreshSlider, SIGNAL(sliderValue(float)), this, SLOT(setSlideThresh(float)));
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++通過(guò)TerminateProess結(jié)束進(jìn)程實(shí)例
這篇文章主要介紹了C++通過(guò)TerminateProess結(jié)束進(jìn)程實(shí)例,是Windows應(yīng)用程序設(shè)計(jì)中非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10C++中實(shí)現(xiàn)線程安全和延遲執(zhí)行詳解
這篇文章主要為大家詳細(xì)介紹了C++中實(shí)現(xiàn)線程安全和延遲執(zhí)行的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以了解下2024-01-01