首頁 > 軟體

Qt介面中滑動條的實現方式

2022-11-11 14:00:14

Qt介面實現滑動條

功能

在表單內放置一個滑動條slider、一個spin box增減小控制元件,一個設定中間值的按鈕,一個將當前值通過qQebug列印到編譯器上。使用彈簧和佈局使介面更美觀。

效果

Widget.h檔案:

#pragma once

#include <QtWidgets/QWidget>
#include<QSlider>		//滑動條標頭檔案
#include<QSpinBox>		//增減控制元件標頭檔案
#include<QBoxLayout>	//介面佈局標頭檔案,包含了水平佈局<QHBoxLayout>和垂直佈局<QVBoxLayout>
#include<QSpacerItem>	//彈簧標頭檔案
#include<QPushButton>	//按鈕標頭檔案
#include<QDebug>		//qDebug輸出標頭檔案
#include "ui_Widget.h"	//ui介面

class Widget : public QWidget
{
	Q_OBJECT

public:
	Widget(QWidget *parent = Q_NULLPTR);
	QSlider *slider;		//定義一個滑動條,在cpp檔案的構建函數中設定屬性,下列控制元件同
	QSpinBox *box;			//定義一個增減控制元件

	QSpacerItem *spacer;	//彈簧1
	QSpacerItem *spacer2;	//彈簧2

	QPushButton *btn_setMedi;		//設定中間值的按鈕
	QPushButton *btn_getValue;		//列印當前值的按鈕

private:
	Ui::WidgetClass ui;
};

Widget.cpp:

#include "Widget.h"

Widget::Widget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	QSpinBox *box = new QSpinBox(this);	
	QSlider *slider = new QSlider(Qt::Horizontal,this);	//Qt::Horizontal設定為水平的滑動條
	
	QSpacerItem *spacer = new QSpacerItem(20, 20);  //彈簧的w和h為20,20
	QSpacerItem *spacer2 = new QSpacerItem(20, 20);
	QSpacerItem *spacer3 = new QSpacerItem(20, 20);
	QSpacerItem *spacer4 = new QSpacerItem(20, 20);
	
	QPushButton *btn_setMedi = new QPushButton("set median", this);	//按鈕文字為「set median」
	QPushButton *btn_getValue = new QPushButton("get value", this);

	QHBoxLayout *loyout = new QHBoxLayout;//相當於this->setLayout(loyout);定義一個水平佈局
	loyout->addItem(spacer);			//新增彈簧用addItem
	loyout->addWidget(box);				//新增控制元件和按鈕用addWidget
	loyout->addWidget(slider);
	loyout->addItem(spacer2);

	QHBoxLayout *btnLayout = new QHBoxLayout;
	btnLayout->addItem(spacer3);
	btnLayout->addWidget(btn_setMedi);
	btnLayout->addWidget(btn_getValue);
	btnLayout->addItem(spacer4);
	
	//垂直佈局設定了this,讓佈局依賴在widget上
	//前面的兩個水平佈局不用設定,因為水平佈局依賴在了垂直佈局上,只需最外層設定依賴
	QVBoxLayout *vloyout = new QVBoxLayout(this);	//新增垂直佈局,把前面的兩個水平佈局放進來
	vloyout->addLayout(loyout);
	vloyout->addLayout(btnLayout);
	
	this->setFixedSize(400, 300);	//把表單大小固定

	//數值改變,滑動條跟著改變
	//函數QSpinBox::valueChanged出現了函數過載(int或char),需要定義一個函數指標排除二義性
	void (QSpinBox:: *box_signal ) (int) = &QSpinBox::valueChanged;
	connect(box ,box_signal , slider, &QSlider::setValue);

	//滑動條改變,數值跟著改變
	connect(slider, &QSlider::valueChanged, box, &QSpinBox::setValue);

	//設定中間值
	//使用了Lambda表示式[](){}
	connect(btn_setMedi, &QPushButton::clicked, [=]() {
		slider->setValue(50);
	});

	//列印當前值
	connect(btn_getValue, &QPushButton::clicked, [=]() {
		qDebug() << box->value();
	});
}

main.cpp:

#include "Widget.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	Widget w;
	w.show();
	return a.exec();
}

Qt滑動條解決點選和拖動問題

QSlider 在點選非滾軸部分時,不會直接到點選位置,而是一步一步執行,在專案中使用時會感覺不流暢。可以通過改變QSlider的滑鼠點選事件(mousePressEvent)和滑鼠移動事件(mouseMoveEvent)解決。

使用原QSlider

如UI中使用verticalSlider,MySliderUI.h 標頭檔案:

class MySliderUI : public QWidget
{
    Q_OBJECT
public:
    explicit MySliderUI(QWidget *parent = 0);
    ~MySliderUI();
protected:
    bool eventFilter(QObject *obj, QEvent *event);

private:
    Ui::EpsSliderUI *ui;
};

MySliderUI.cpp

MySliderUI::MySliderUI(QWidget *parent) :
    QWidget(parent)
{
    ui->slider->installEventFilter(this);
}

新增事件過濾,對QSlider的事件重新處理。

bool MySliderUI::eventFilter(QObject *obj, QEvent *event)
{
    if( obj == ui->slider)
    {
        if (event->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
            if (mouseEvent->button() == Qt::LeftButton)
            {
                ui->slider->event(event);
                double pos = mouseEvent->pos().y() / (double)ui->slider->height();
                int value =  pos * (ui->slider->maximum() - ui->slider->minimum()) 
                                  + ui->slider->minimum()+0.5;
                ui->slider->setValue(value);
                return true;
            }
        }
        else if (event->type() == QEvent::MouseButtonDblClick)
        {
            return true;
        }
        else if (event->type() == QEvent::MouseMove)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
            ui->slider->event(event);
            double pos = mouseEvent->pos().y() / (double)ui->slider->height();
            int value =  pos * (ui->slider->maximum() - ui->slider->minimum()) 
                                + ui->slider->minimum()+0.5;
            ui->slider->setValue(value);
            return true;
        }
    }
    return QObject::eventFilter(obj,event);
}

繼承QSlider,重寫事件函數

標頭檔案

class MySlider : public QSlider
{
    Q_OBJECT
public:
    MySlider(QWidget *parent = nullptr);
    ~MySlider();

protected:
    void mousePressEvent(QMouseEvent *event);  //單擊
    void mouseMoveEvent(QMouseEvent *event);
};

實現檔案

#include "myslider.h"
#include <QMouseEvent>

MySlider::MySlider(QWidget *parent)
    :QSlider (parent)
{
}

MySlider::~MySlider()
{
}

void MySlider::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)    //判斷左鍵
    {
        //注意應先呼叫父類別的滑鼠點選處理事件,這樣可以不影響拖動的情況
        QSlider::mousePressEvent(event);
        double pos = ((double)height() - event->pos().y()) / (double)height();
        int value = pos * (maximum() - minimum()) + minimum();
        setValue(value);
    }
}
void MySlider::mouseMoveEvent(QMouseEvent *event)
{
    //注意應先呼叫父類別的滑鼠點選處理事件,這樣可以不影響拖動的情況
    QSlider::mouseMoveEvent(event);
    double pos =  ((double)height() - event->pos().y()) / (double)height();
    int value = pos * (maximum() - minimum()) + minimum();
    setValue(value);
}

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com