├── snap ├── btn1.png ├── btn2.png ├── btn3.png ├── avatar1.png ├── card1.png ├── msgbox2.png ├── msgbox3.png ├── slider1.png ├── checkbox1.png ├── inputnum1.png ├── radiobtn1.png ├── switchbtn1.png ├── lineprogress1.png └── circleprogress1.png ├── example ├── avatar.png ├── resource.qrc ├── widget.h ├── widget.ui ├── main.cpp ├── example.pro └── widget.cpp ├── qelement ├── images │ ├── arrow-up.png │ └── arrow-down.png ├── qelement.qrc ├── el_tooltip.cpp ├── el_global.h ├── el_select.h ├── el_tooltip.h ├── el_awesome.h ├── el_input.h ├── el_card.h ├── el_inputnumber.h ├── el_radio.h ├── el_checkbox.h ├── el_lineprogress.h ├── el_circleprogress.h ├── el_imageprovider.h ├── el_link.h ├── el_lineprogress.cpp ├── qelement.pri ├── el_avatar.h ├── el_select.cpp ├── el_circleprogress.cpp ├── el_style.h ├── el_switch.h ├── el_button.h ├── el_input.cpp ├── el_messagebox.h ├── el_link.cpp ├── el_imageprovider.cpp ├── el_radio.cpp ├── el_checkbox.cpp ├── el_card.cpp ├── el_inputnumber.cpp ├── el_slider.h ├── el_avatar.cpp ├── el_button.cpp ├── el_messagebox.cpp ├── el_switch.cpp └── el_slider.cpp ├── .gitmodules ├── LICENSE └── README.md /snap/btn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/btn1.png -------------------------------------------------------------------------------- /snap/btn2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/btn2.png -------------------------------------------------------------------------------- /snap/btn3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/btn3.png -------------------------------------------------------------------------------- /snap/avatar1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/avatar1.png -------------------------------------------------------------------------------- /snap/card1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/card1.png -------------------------------------------------------------------------------- /snap/msgbox2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/msgbox2.png -------------------------------------------------------------------------------- /snap/msgbox3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/msgbox3.png -------------------------------------------------------------------------------- /snap/slider1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/slider1.png -------------------------------------------------------------------------------- /example/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/example/avatar.png -------------------------------------------------------------------------------- /snap/checkbox1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/checkbox1.png -------------------------------------------------------------------------------- /snap/inputnum1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/inputnum1.png -------------------------------------------------------------------------------- /snap/radiobtn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/radiobtn1.png -------------------------------------------------------------------------------- /snap/switchbtn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/switchbtn1.png -------------------------------------------------------------------------------- /snap/lineprogress1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/lineprogress1.png -------------------------------------------------------------------------------- /snap/circleprogress1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/circleprogress1.png -------------------------------------------------------------------------------- /qelement/images/arrow-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/qelement/images/arrow-up.png -------------------------------------------------------------------------------- /qelement/images/arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devcxx/qelement/HEAD/qelement/images/arrow-down.png -------------------------------------------------------------------------------- /example/resource.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | avatar.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /qelement/qelement.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/arrow-down.png 4 | images/arrow-up.png 5 | 6 | 7 | -------------------------------------------------------------------------------- /qelement/el_tooltip.cpp: -------------------------------------------------------------------------------- 1 | #include "el_tooltip.h" 2 | 3 | EL_BEGIN_NAMESPACE 4 | 5 | Tooltip::Tooltip(Effect effect, QWidget* parent) 6 | : QToolTip (parent) 7 | { 8 | } 9 | 10 | EL_END_NAMESPACE 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "QtAwesome"] 2 | path = QtAwesome 3 | url = https://github.com/gamecreature/QtAwesome 4 | branch = main 5 | [submodule "FramelessWindow"] 6 | path = FramelessWindow 7 | url = https://github.com/winsoft666/Qt-FramelessWindow.git 8 | branch = master 9 | -------------------------------------------------------------------------------- /qelement/el_global.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_GLOBAL_H 2 | #define EL_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(EL_LIBRARY) 7 | #define EL_EXPORT Q_DECL_EXPORT 8 | #else 9 | #define EL_EXPORT 10 | #endif 11 | 12 | #define EL_BEGIN_NAMESPACE namespace el { 13 | #define EL_END_NAMESPACE } 14 | 15 | 16 | #endif // EL_GLOBAL_H 17 | -------------------------------------------------------------------------------- /example/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | namespace Ui { 8 | class Widget; 9 | } 10 | QT_END_NAMESPACE 11 | 12 | class Widget : public QWidget 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | Widget(QWidget *parent = nullptr); 18 | ~Widget(); 19 | 20 | private: 21 | Ui::Widget *ui; 22 | }; 23 | #endif // WIDGET_H 24 | -------------------------------------------------------------------------------- /qelement/el_select.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_SELECT_H 2 | #define EL_SELECT_H 3 | 4 | #include "el_global.h" 5 | 6 | #include 7 | 8 | EL_BEGIN_NAMESPACE 9 | 10 | // Select 选择器 11 | class Select : public QComboBox { 12 | Q_OBJECT 13 | public: 14 | Select(QWidget* parent = nullptr); 15 | 16 | protected: 17 | QSize sizeHint() const; 18 | void showPopup(); 19 | }; 20 | 21 | EL_END_NAMESPACE 22 | 23 | #endif // EL_SELECT_H 24 | -------------------------------------------------------------------------------- /example/widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Widget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 600 11 | 12 | 13 | 14 | Widget 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /qelement/el_tooltip.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_TOOLTIP_H 2 | #define EL_TOOLTIP_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | class Tooltip : public QToolTip { 10 | Q_OBJECT 11 | public: 12 | enum Effect { 13 | Dark, // 深色 14 | Light, // 浅色 15 | }; 16 | Q_ENUM(Effect) 17 | 18 | Tooltip(Effect effect = Dark, QWidget* parent = nullptr); 19 | }; 20 | 21 | EL_END_NAMESPACE 22 | 23 | #endif // EL_TOOLTIP_H 24 | -------------------------------------------------------------------------------- /qelement/el_awesome.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_AWESOME_H 2 | #define EL_AWESOME_H 3 | 4 | #include "QtAwesome.h" 5 | #include "el_global.h" 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | class Awesome : public fa::QtAwesome { 10 | Q_OBJECT 11 | public: 12 | static Awesome& instance() 13 | { 14 | static Awesome _instance; 15 | return _instance; 16 | } 17 | }; 18 | 19 | EL_END_NAMESPACE 20 | 21 | #define qAwesome (static_cast(&el::Awesome::instance())) 22 | 23 | #endif // EL_AWESOME_H 24 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | #include "QtAwesome.h" 4 | #include "el_awesome.h" 5 | #include 6 | #include 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) 11 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 12 | QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 13 | #endif 14 | QApplication a(argc, argv); 15 | 16 | qAwesome->initFontAwesome(); 17 | 18 | Widget w; 19 | w.show(); 20 | return a.exec(); 21 | } 22 | -------------------------------------------------------------------------------- /qelement/el_input.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_INPUT_H 2 | #define EL_INPUT_H 3 | 4 | #include "el_global.h" 5 | #include 6 | #include 7 | 8 | EL_BEGIN_NAMESPACE 9 | 10 | // Input 输入框 11 | class EL_EXPORT Input : public QLineEdit { 12 | Q_OBJECT 13 | 14 | public: 15 | enum Type { 16 | Default, 17 | Clearable, // 可清空 18 | ShowPassword, // 密码框 19 | Calendar, // 日历 20 | }; 21 | Q_ENUM(Type) 22 | 23 | Input(Type type = Default, QWidget* parent = nullptr); 24 | }; 25 | 26 | EL_END_NAMESPACE 27 | 28 | #endif // EL_INPUT_H 29 | -------------------------------------------------------------------------------- /qelement/el_card.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_CARD_H 2 | #define EL_CARD_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // Card 卡片 10 | class EL_EXPORT Card : public QAbstractButton { 11 | Q_OBJECT 12 | public: 13 | Card(const QIcon& icon, const QString& title, const QString& content, QWidget* parent = nullptr); 14 | 15 | protected: 16 | QSize sizeHint() const Q_DECL_OVERRIDE; 17 | void paintEvent(QPaintEvent* event); 18 | void iconToGrayscale(QPixmap* pm); 19 | 20 | private: 21 | QString _content; 22 | }; 23 | 24 | EL_END_NAMESPACE 25 | 26 | #endif // EL_CARD_H 27 | -------------------------------------------------------------------------------- /qelement/el_inputnumber.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUTNUMBER_H 2 | #define INPUTNUMBER_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | class QPushButton; 8 | 9 | EL_BEGIN_NAMESPACE 10 | 11 | // InputNumber 计数器 12 | class EL_EXPORT InputNumber : public QLineEdit { 13 | Q_OBJECT 14 | public: 15 | explicit InputNumber(int min, int max, QWidget* parent = nullptr); 16 | 17 | protected: 18 | void resizeEvent(QResizeEvent* event); 19 | void mouseMoveEvent(QMouseEvent* event); 20 | 21 | signals: 22 | 23 | private: 24 | QPushButton* _minusBtn; 25 | QPushButton* _plusBtn; 26 | }; 27 | 28 | EL_END_NAMESPACE 29 | 30 | #endif // INPUTNUMBER_H 31 | -------------------------------------------------------------------------------- /qelement/el_radio.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_RADIO_H 2 | #define EL_RADIO_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // Radio 单选框 10 | class EL_EXPORT Radio : public QAbstractButton { 11 | Q_OBJECT 12 | public: 13 | // 文本位置 14 | enum LabelPosition { 15 | LP_Left, // 文字在左 16 | LP_Right, // 文字在右 17 | }; 18 | 19 | Radio(const QString& text, LabelPosition placement = LP_Right, QWidget* parent = nullptr); 20 | 21 | protected: 22 | QSize sizeHint() const; 23 | void paintEvent(QPaintEvent* event); 24 | QColor getColor(); 25 | QIcon getIcon(); 26 | 27 | private: 28 | LabelPosition _placement; 29 | }; 30 | 31 | EL_END_NAMESPACE 32 | 33 | #endif // EL_RADIO_H 34 | -------------------------------------------------------------------------------- /qelement/el_checkbox.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_CHECKBOX_H 2 | #define EL_CHECKBOX_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // Checkbox 多选框 10 | class EL_EXPORT Checkbox : public QAbstractButton { 11 | Q_OBJECT 12 | public: 13 | // 文本位置 14 | enum LabelPosition { 15 | LP_Left, // 文字在左 16 | LP_Right, // 文字在右 17 | }; 18 | Checkbox(const QString& text, LabelPosition placement = LP_Right, QWidget* parent = nullptr); 19 | 20 | protected: 21 | QSize sizeHint() const; 22 | void paintEvent(QPaintEvent* event); 23 | QColor getColor(); 24 | QIcon getIcon(); 25 | 26 | private: 27 | LabelPosition _placement; 28 | }; 29 | 30 | EL_END_NAMESPACE 31 | 32 | #endif // EL_CHECKBOX_H 33 | -------------------------------------------------------------------------------- /qelement/el_lineprogress.h: -------------------------------------------------------------------------------- 1 | #ifndef LINEPROGRESS_H 2 | #define LINEPROGRESS_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // 线形进度条 10 | class EL_EXPORT LineProgress : public QProgressBar { 11 | Q_OBJECT 12 | public: 13 | // 进度条状态 14 | enum Status { 15 | Default, 16 | Success, 17 | Warning, 18 | Exception 19 | }; 20 | Q_ENUM(Status) 21 | 22 | LineProgress(QWidget* parent = nullptr); 23 | // 设置进度条当前状态 24 | void setStatus(Status status); 25 | 26 | protected: 27 | void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE; 28 | QColor getColor(); 29 | 30 | private: 31 | Status _status = Default; 32 | }; 33 | 34 | EL_END_NAMESPACE 35 | 36 | #endif // LINEPROGRESS_H 37 | -------------------------------------------------------------------------------- /example/example.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | CONFIG += c++17 6 | 7 | QMAKE_CFLAGS += /utf-8 8 | QMAKE_CXXFLAGS += /utf-8 9 | 10 | include(../qelement/qelement.pri) 11 | 12 | # You can make your code fail to compile if it uses deprecated APIs. 13 | # In order to do so, uncomment the following line. 14 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 15 | 16 | SOURCES += \ 17 | main.cpp \ 18 | widget.cpp 19 | 20 | HEADERS += \ 21 | widget.h 22 | 23 | FORMS += \ 24 | widget.ui 25 | 26 | # Default rules for deployment. 27 | qnx: target.path = /tmp/$${TARGET}/bin 28 | else: unix:!android: target.path = /opt/$${TARGET}/bin 29 | !isEmpty(target.path): INSTALLS += target 30 | 31 | RESOURCES += \ 32 | resource.qrc 33 | -------------------------------------------------------------------------------- /qelement/el_circleprogress.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_CIRCLEPROGRESS_H 2 | #define EL_CIRCLEPROGRESS_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // 环形进度条 10 | class EL_EXPORT CircleProgress : public QWidget { 11 | Q_OBJECT 12 | public: 13 | // 进度条状态 14 | enum Status { 15 | Default, 16 | Success, 17 | Warning, 18 | Exception 19 | }; 20 | Q_ENUM(Status) 21 | 22 | explicit CircleProgress(QWidget* parent = nullptr); 23 | void setPercent(int percent); 24 | // 设置进度条当前状态 25 | void setStatus(Status status); 26 | 27 | protected: 28 | void paintEvent(QPaintEvent*); 29 | QSize sizeHint() const; 30 | QColor getColor(); 31 | 32 | private: 33 | int _percent = 0; 34 | int _rotateAngle = 0; 35 | Status _status = Default; 36 | }; 37 | 38 | EL_END_NAMESPACE 39 | 40 | #endif // EL_CIRCLEPROGRESS_H 41 | -------------------------------------------------------------------------------- /qelement/el_imageprovider.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_IMAGEPROVIDER_H 2 | #define EL_IMAGEPROVIDER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "el_global.h" 9 | 10 | EL_BEGIN_NAMESPACE 11 | 12 | class ImageRunnable : public QObject, public QRunnable { 13 | Q_OBJECT 14 | public: 15 | ImageRunnable(const QString& url, const QString& fileName); 16 | void run(); 17 | 18 | signals: 19 | void taskStart(QString, QString); 20 | void taskEnd(QString, QString); 21 | 22 | private: 23 | QString _url; 24 | QString _fileName; 25 | }; 26 | 27 | class ImageProvider : public QObject { 28 | Q_OBJECT 29 | public: 30 | explicit ImageProvider(QObject* parent = nullptr); 31 | ~ImageProvider(); 32 | void getNetworkImage(const QString& url); 33 | QString generateId(const QString& url); 34 | 35 | signals: 36 | void imageReady(QString url, QString filePath); 37 | 38 | private: 39 | QThreadPool* _pool = nullptr; 40 | QString _cacheDir; 41 | }; 42 | 43 | EL_END_NAMESPACE 44 | 45 | #endif // EL_IMAGEPROVIDER_H 46 | -------------------------------------------------------------------------------- /qelement/el_link.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_LINK_H 2 | #define EL_LINK_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // Link 文字链接 10 | class EL_EXPORT Link : public QLabel { 11 | 12 | Q_OBJECT 13 | public: 14 | enum Type { 15 | Default, // 默认链接 16 | Primary, // 主要链接 17 | Success, // 成功链接 18 | Warning, // 警告链接 19 | Danger, // 危险链接 20 | Info // 信息链接 21 | }; 22 | Q_ENUM(Type) 23 | 24 | Link(const QString& text, const QString link, Type type = Default, QWidget* parent = nullptr); 25 | void setLink(const QString& link); 26 | QString getLink(); 27 | 28 | signals: 29 | void linkClicked(const QString& link); 30 | 31 | protected: 32 | void mousePressEvent(QMouseEvent* event); 33 | QSize sizeHint() const; 34 | void enterEvent(QEvent* event); 35 | void leaveEvent(QEvent* event); 36 | 37 | QString getColor(Type type); 38 | QString getDisabledColor(Type type); 39 | 40 | private: 41 | QString _link; 42 | }; 43 | 44 | EL_END_NAMESPACE 45 | 46 | #endif // EL_LINK_H 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 hk0x 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /qelement/el_lineprogress.cpp: -------------------------------------------------------------------------------- 1 | #include "el_lineprogress.h" 2 | #include 3 | 4 | EL_BEGIN_NAMESPACE 5 | 6 | LineProgress::LineProgress(QWidget* parent) 7 | : QProgressBar(parent) 8 | { 9 | setMinimum(0); 10 | setMaximum(100); 11 | setValue(0); 12 | } 13 | 14 | void LineProgress::setStatus(Status status) 15 | { 16 | _status = status; 17 | } 18 | 19 | void LineProgress::paintEvent(QPaintEvent*) 20 | { 21 | QPainter painter(this); 22 | QRect rect = QRect(0, 0, width(), height() / 2); 23 | // QRect textRect = QRect(0, height() / 2, width(), height() / 2); 24 | 25 | const double k = (double)(value() - minimum()) / (maximum() - minimum()); 26 | int x = (int)(rect.width() * k); 27 | QRect fillRect = rect.adjusted(0, 0, x - rect.width(), 0); 28 | 29 | painter.fillRect(rect, QBrush(QColor(0xebeef5))); 30 | painter.fillRect(fillRect, QBrush(getColor())); 31 | } 32 | 33 | QColor LineProgress::getColor() 34 | { 35 | switch (_status) { 36 | case Default: 37 | return QColor(0x409eff); 38 | case Success: 39 | return QColor(0x67c23a); 40 | case Warning: 41 | return QColor(0xe6a23c); 42 | case Exception: 43 | return QColor(0xf56c6c); 44 | } 45 | } 46 | 47 | EL_END_NAMESPACE 48 | -------------------------------------------------------------------------------- /qelement/qelement.pri: -------------------------------------------------------------------------------- 1 | 2 | QT += network 3 | 4 | CONFIG += fontAwesomeFree 5 | 6 | include($$PWD/../QtAwesome/QtAwesome/QtAwesome.pri) 7 | 8 | INCLUDEPATH += $$PWD/../FramelessWindow 9 | 10 | INCLUDEPATH += $$PWD 11 | 12 | HEADERS += \ 13 | $$PWD/el_avatar.h \ 14 | $$PWD/el_awesome.h \ 15 | $$PWD/el_button.h \ 16 | $$PWD/el_card.h \ 17 | $$PWD/el_checkbox.h \ 18 | $$PWD/el_circleprogress.h \ 19 | $$PWD/el_global.h \ 20 | $$PWD/el_imageprovider.h \ 21 | $$PWD/el_inputnumber.h \ 22 | $$PWD/el_lineprogress.h \ 23 | $$PWD/el_link.h \ 24 | $$PWD/el_input.h \ 25 | $$PWD/el_messagebox.h \ 26 | $$PWD/el_radio.h \ 27 | $$PWD/el_select.h \ 28 | $$PWD/el_slider.h \ 29 | $$PWD/el_style.h \ 30 | $$PWD/el_switch.h \ 31 | 32 | SOURCES += \ 33 | $$PWD/el_avatar.cpp \ 34 | $$PWD/el_button.cpp \ 35 | $$PWD/el_card.cpp \ 36 | $$PWD/el_checkbox.cpp \ 37 | $$PWD/el_circleprogress.cpp \ 38 | $$PWD/el_imageprovider.cpp \ 39 | $$PWD/el_inputnumber.cpp \ 40 | $$PWD/el_lineprogress.cpp \ 41 | $$PWD/el_link.cpp \ 42 | $$PWD/el_input.cpp \ 43 | $$PWD/el_messagebox.cpp \ 44 | $$PWD/el_radio.cpp \ 45 | $$PWD/el_select.cpp \ 46 | $$PWD/el_slider.cpp \ 47 | $$PWD/el_switch.cpp \ 48 | 49 | RESOURCES += \ 50 | $$PWD/qelement.qrc 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Element3 风格 Qt Widgets 2 | 3 | [Element3](https://e3.shengxinjing.cn/#/),一套为开发者、设计师和产品经理准备的基于 Vue 3.0 的桌面端组件库 4 | 5 | 部分控件通过QSS方式实现,部分通过重写QWidget的paintEvent方式实现 6 | 7 | ## Button 按钮 8 | - 默认按钮 9 | 10 | ![截图](snap/btn1.png) 11 | 12 | - 圆角按钮 13 | 14 | ![截图](snap/btn2.png) 15 | 16 | - 图标按钮 17 | 18 | ![截图](snap/btn3.png) 19 | 20 | ## Checkbox 多选框 21 | 22 | ![截图](snap/checkbox1.png) 23 | 24 | ## Radio 单选框 25 | 26 | ![截图](snap/radiobtn1.png) 27 | 28 | ## Switch 开关 29 | 30 | ![截图](snap/switchbtn1.png) 31 | 32 | ## Avatar 头像 33 | 34 | ![截图](snap/avatar1.png) 35 | 36 | ## InputNumber 计数器 37 | 38 | ![截图](snap/inputnum1.png) 39 | 40 | ## Card 卡片 41 | 42 | ![截图](snap/card1.png) 43 | 44 | ## Slider 滑块 45 | 46 | ![截图](snap/slider1.png) 47 | 48 | ## MessageBox 弹框 49 | 50 | - 消息提示 51 | 52 | ![截图](snap/msgbox2.png) 53 | 54 | - 错误提示 55 | 56 | ![截图](snap/msgbox3.png) 57 | 58 | ## Progress 进度条 59 | 60 | - 线形进度条 61 | 62 | ![截图](snap/lineprogress1.png) 63 | 64 | - 环形进度条 65 | 66 | ![截图](snap/circleprogress1.png) 67 | 68 | ## 已实现组件 69 | 70 | - [x] Button 按钮 71 | - [x] Checkbox 多选框 72 | - [x] Radio 单选框 73 | - [x] Input 输入框 74 | - [x] InputNumber 计数器 75 | - [x] Select 选择器 76 | - [x] Link 文字链接 77 | - [x] Switch 开关 78 | - [x] Avatar 头像 79 | - [x] MessageBox 弹框 80 | - [x] Slider 滑块 81 | - [x] Progress 进度条 82 | 83 | ## 未实现组件 84 | 85 | - [ ] Tabs 标签页 86 | - [ ] Badge 标记 87 | - [ ] Table 表格 88 | - [ ] Tag 标签 89 | - [ ] Alert 警告 90 | - [ ] Loading 加载 91 | - [ ] Tooltip 文字提示 92 | -------------------------------------------------------------------------------- /qelement/el_avatar.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_AVATAR_H 2 | #define EL_AVATAR_H 3 | 4 | #include "el_global.h" 5 | #include "el_imageprovider.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | EL_BEGIN_NAMESPACE 12 | 13 | // Avatar 头像 14 | class EL_EXPORT Avatar : public QWidget { 15 | Q_OBJECT 16 | public: 17 | enum Type { 18 | Icon, // 图标 19 | Image, // 图片 20 | Letter, // 字符 21 | }; 22 | Q_ENUM(Type) 23 | 24 | explicit Avatar(QWidget* parent = nullptr); 25 | explicit Avatar(const QIcon& icon, QWidget* parent = 0); 26 | explicit Avatar(const QString& letter, QWidget* parent = 0); 27 | explicit Avatar(const QImage& image, QWidget* parent = 0); 28 | 29 | QSize sizeHint() const Q_DECL_OVERRIDE; 30 | 31 | void setSize(int size); 32 | int size() const; 33 | 34 | void setLetter(const QString& letter); 35 | void setImage(const QImage& image); 36 | void setIcon(const QIcon& icon); 37 | 38 | void setUrl(const QString& url); 39 | 40 | Type type() const; 41 | 42 | protected: 43 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; 44 | 45 | protected slots: 46 | void onImageReady(QString url, QString filePath); 47 | 48 | private: 49 | int _size = 40; 50 | Type _type = Letter; 51 | QString _letter; 52 | QImage _image; 53 | QIcon _icon; 54 | QPixmap _pixmap; 55 | ImageProvider _provider; 56 | }; 57 | 58 | EL_END_NAMESPACE 59 | 60 | #endif // EL_AVATAR_H 61 | -------------------------------------------------------------------------------- /qelement/el_select.cpp: -------------------------------------------------------------------------------- 1 | #include "el_select.h" 2 | #include 3 | #include 4 | 5 | EL_BEGIN_NAMESPACE 6 | 7 | Select::Select(QWidget* parent) 8 | : QComboBox(parent) 9 | { 10 | setItemDelegate(new QStyledItemDelegate()); 11 | QString styleSheet; 12 | styleSheet += "QComboBox { border: 1px solid #dcdfe6; border-radius: 4px; background-color: white;}"; 13 | styleSheet += "QComboBox:on { border: 1px solid #409eff;}"; 14 | styleSheet += "QComboBox { color: #606266; font-family: Microsoft YaHei; font-size: 14px; padding-left: 15px;}"; 15 | styleSheet += "QComboBox QAbstractItemView { border: 1px solid #dcdfe6; border-radius: 4px; background-color: white; outline: 0px;}"; 16 | styleSheet += "QComboBox QAbstractItemView::item { color: #606266; font-family: Microsoft YaHei; font-size: 14px; height: 34px;}"; 17 | styleSheet += "QComboBox QAbstractItemView::item:hover { color: #606266; background-color: #f5f7fa; padding-left: 15px;}"; 18 | styleSheet += "QComboBox QAbstractItemView::item:selected {color: #409eff;}"; 19 | styleSheet += "QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: center right; width: 14px; height: 14px; border: none; image: url(:/images/arrow-down.png); padding-right: 8px;}"; 20 | styleSheet += "QComboBox::drop-down:on { image: url(:/images/arrow-up.png);}"; 21 | setStyleSheet(styleSheet); 22 | } 23 | 24 | QSize Select::sizeHint() const 25 | { 26 | return QSize(200, 40); 27 | } 28 | 29 | void Select::showPopup() 30 | { 31 | QComboBox::showPopup(); 32 | QWidget* popup = this->findChild(); 33 | if (popup != NULL) { 34 | popup->move(popup->pos().x(), popup->pos().y() + 4); 35 | } 36 | } 37 | EL_END_NAMESPACE 38 | -------------------------------------------------------------------------------- /qelement/el_circleprogress.cpp: -------------------------------------------------------------------------------- 1 | #include "el_circleprogress.h" 2 | #include 3 | 4 | EL_BEGIN_NAMESPACE 5 | 6 | CircleProgress::CircleProgress(QWidget* parent) 7 | : QWidget { parent } 8 | { 9 | } 10 | 11 | void CircleProgress::setPercent(int percent) 12 | { 13 | if (_percent != percent) { 14 | _percent = percent; 15 | update(); 16 | } 17 | } 18 | 19 | void CircleProgress::setStatus(Status status) 20 | { 21 | _status = status; 22 | } 23 | 24 | void CircleProgress::paintEvent(QPaintEvent*) 25 | { 26 | QPainter p(this); 27 | p.setRenderHint(QPainter::Antialiasing); 28 | 29 | _rotateAngle = 360 * _percent / 100; 30 | 31 | int side = qMin(width(), height()); 32 | QRectF outRect(0, 0, side, side); 33 | QRectF inRect(10, 10, side - 20, side - 20); 34 | QString valueStr = QString("%1%").arg(QString::number(_percent)); 35 | 36 | //画外圆 37 | p.setPen(Qt::NoPen); 38 | p.setBrush(QBrush(QColor(0xebeef5))); 39 | p.drawEllipse(outRect); 40 | p.setBrush(QBrush(getColor())); 41 | p.drawPie(outRect, (90 - _rotateAngle) * 16, _rotateAngle * 16); 42 | //画遮罩 43 | p.setBrush(palette().window().color()); 44 | p.drawEllipse(inRect); 45 | //画文字 46 | QFont f = QFont("Microsoft YaHei"); 47 | f.setPixelSize(14); 48 | p.setFont(f); 49 | p.setPen(QColor(0x606266)); 50 | p.drawText(inRect, Qt::AlignCenter, valueStr); 51 | } 52 | 53 | QSize CircleProgress::sizeHint() const 54 | { 55 | return QSize(120, 120); 56 | } 57 | 58 | QColor CircleProgress::getColor() 59 | { 60 | switch (_status) { 61 | case Default: 62 | return QColor(0x409eff); 63 | case Success: 64 | return QColor(0x67c23a); 65 | case Warning: 66 | return QColor(0xe6a23c); 67 | case Exception: 68 | return QColor(0xf56c6c); 69 | } 70 | } 71 | 72 | EL_END_NAMESPACE 73 | -------------------------------------------------------------------------------- /qelement/el_style.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_STYLE_H 2 | #define EL_STYLE_H 3 | 4 | #include "el_global.h" 5 | 6 | EL_BEGIN_NAMESPACE 7 | 8 | // Color 色彩 9 | // https://e3.shengxinjing.cn/#/component/color 10 | namespace Color { 11 | // 主色 12 | const Q_DECL_UNUSED char Brand[] = "#409EFF"; 13 | // 辅助色 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作) 14 | const Q_DECL_UNUSED char Success[] = "#67C23A"; 15 | const Q_DECL_UNUSED char SuccessDisabled[] = "#b3e19d"; 16 | const Q_DECL_UNUSED char Warning[] = "#E6A23C"; 17 | const Q_DECL_UNUSED char WarningDisabled[] = "#f3d19e"; 18 | const Q_DECL_UNUSED char Danger[] = "#F56C6C"; 19 | const Q_DECL_UNUSED char DangerDisabled[] = "#fab6b6"; 20 | const Q_DECL_UNUSED char Info[] = "#909399"; 21 | const Q_DECL_UNUSED char InfoDisabled[] = "#c8c9cc"; 22 | // 中性色 23 | // 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构 24 | // 主要文字 25 | const Q_DECL_UNUSED char PrimaryText[] = "#303133"; 26 | const Q_DECL_UNUSED char PrimaryTextDisabled[] = "#a0cfff"; 27 | // 常规文字 28 | const Q_DECL_UNUSED char DefaultText[] = "#606266"; 29 | const Q_DECL_UNUSED char DefaultTextDisabled[] = "#c0c4cc"; 30 | // 次要文字 31 | const Q_DECL_UNUSED char SecondaryText[] = "#909399"; 32 | //占位文字 33 | const Q_DECL_UNUSED char PlaceholderText[] = "#C0C4CC"; 34 | } 35 | 36 | // Border 边框 37 | // https://e3.shengxinjing.cn/#/component/border 38 | namespace Border { 39 | // 无圆角 40 | const Q_DECL_UNUSED int None = 0; 41 | // 小圆角 42 | const Q_DECL_UNUSED int Small = 2; 43 | // 大圆角 44 | const Q_DECL_UNUSED int Big = 4; 45 | // 圆形圆角 46 | const Q_DECL_UNUSED int Circle = 30; 47 | } 48 | 49 | // 字号 (像素px) 50 | namespace FontSize { 51 | // 辅助文字 52 | const Q_DECL_UNUSED int ExtraSamll = 12; 53 | // 正文(小) 54 | const Q_DECL_UNUSED int Samll = 13; 55 | // 正文 56 | const Q_DECL_UNUSED int Base = 14; 57 | // 小标题 58 | const Q_DECL_UNUSED int Medium = 16; 59 | // 标题 60 | const Q_DECL_UNUSED int Large = 18; 61 | // 主标题 62 | const Q_DECL_UNUSED int ExtraLarge = 20; 63 | } 64 | 65 | EL_END_NAMESPACE 66 | 67 | #endif // EL_STYLE_H 68 | -------------------------------------------------------------------------------- /qelement/el_switch.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef EL_SWITCH_H 3 | #define EL_SWITCH_H 4 | 5 | #include "el_global.h" 6 | #include 7 | 8 | QT_BEGIN_NAMESPACE 9 | class QPropertyAnimation; 10 | QT_END_NAMESPACE 11 | 12 | EL_BEGIN_NAMESPACE 13 | 14 | // Switch 开关 15 | class EL_EXPORT Switch final : public QAbstractButton { 16 | Q_OBJECT 17 | Q_PROPERTY(int thumbPosition READ thumbPosition WRITE setThumbPosition NOTIFY thumbPositionChanged FINAL) 18 | 19 | public: 20 | explicit Switch(QWidget* const parent = nullptr); 21 | explicit Switch(const QString& text, QWidget* const parent = nullptr); 22 | virtual ~Switch() = default; 23 | // 设置背景 激活/未激活 颜色 24 | void setTrackColor(const QColor& trackOnColor, const QColor& trackOffColor); 25 | // 设置滑块 激活/未激活 颜色 26 | void setThumbColor(const QColor& thumbOnColor, const QColor& thumbOffColor); 27 | void setHieght(int nHeight); 28 | void setRadius(qreal corner_radius, qreal thumb_radius); 29 | 30 | virtual QSize sizeHint() const override; 31 | 32 | signals: 33 | void stateChanged(int); 34 | void thumbPositionChanged(); 35 | 36 | protected: 37 | QRect indicatorRect(); 38 | QRect textRect(); 39 | 40 | virtual void paintEvent(QPaintEvent* const) override; 41 | virtual void nextCheckState() override; 42 | virtual void checkStateSet() override; 43 | 44 | void toggle(const Qt::CheckState& state); 45 | 46 | private: 47 | void setThumbPosition(const int& thumbPosition); 48 | int thumbPosition(); 49 | 50 | qreal CORNER_RADIUS, THUMB_RADIUS, SHADOW_ELEVATION; 51 | int height; 52 | QMargins indicatorMargin; 53 | 54 | QColor trackOnColor, trackOffColor, 55 | thumbOnColor, thumbOffColor, 56 | trackDisabledColor, thumbDisabledColor; 57 | qreal trackDisabledOpacity, disabledTextOpacity; 58 | 59 | QPropertyAnimation* const thumbPosAnimation; 60 | int _thumbPosition; 61 | QPixmap shadowPixmap; 62 | }; 63 | 64 | EL_END_NAMESPACE 65 | 66 | #endif // EL_SWITCH_H 67 | -------------------------------------------------------------------------------- /qelement/el_button.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_BUTTON_H 2 | #define EL_BUTTON_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | // Button 按钮 10 | class EL_EXPORT Button : public QPushButton { 11 | Q_OBJECT 12 | public: 13 | enum ButtonType { 14 | BT_Default, // 默认按钮 15 | BT_Primary, // 主要按钮 16 | BT_Success, // 成功按钮 17 | BT_Warning, // 警告按钮 18 | BT_Danger, // 危险按钮 19 | BT_Info // 信息按钮 20 | }; 21 | Q_ENUM(ButtonType) 22 | 23 | enum ButtonStyle { 24 | BS_Default, // 默认 25 | BS_Round, // 圆角 26 | BS_Circle // 圆形 27 | }; 28 | Q_ENUM(ButtonStyle) 29 | 30 | explicit Button(QWidget *parent = nullptr); 31 | // 默认按钮 32 | Button(const QString& text, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr); 33 | // 图标按钮 34 | Button(const QIcon& icon, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr); 35 | // 文字图标按钮 36 | Button(const QString& text, const QIcon& icon, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr); 37 | // FontAwesome图标按钮 38 | Button(int character, ButtonType type = BT_Default, ButtonStyle style = BS_Circle, QWidget* parent = nullptr); 39 | // FontAwesome文字图标按钮 40 | Button(const QString& text, int character, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr); 41 | 42 | void init(ButtonType type = BT_Default, ButtonStyle style = BS_Default); 43 | void init(const QIcon& icon, ButtonType type = BT_Default, ButtonStyle style = BS_Default); 44 | void init(int character, ButtonType type = BT_Default, ButtonStyle style = BS_Circle); 45 | protected: 46 | QSize sizeHint() const; 47 | 48 | QString getBorderStyle(ButtonType type, ButtonStyle style); 49 | QString getColorStyle(ButtonType type); 50 | QString getBkColorStyle(ButtonType type); 51 | }; 52 | 53 | EL_END_NAMESPACE 54 | 55 | #endif // EL_BUTTON_H 56 | -------------------------------------------------------------------------------- /qelement/el_input.cpp: -------------------------------------------------------------------------------- 1 | #include "el_input.h" 2 | #include "el_awesome.h" 3 | #include "el_style.h" 4 | #include 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | Input::Input(Type type, QWidget* parent) 10 | : QLineEdit(parent) 11 | { 12 | QString styleSheet; 13 | styleSheet += "QLineEdit { border: 1px solid #dcdfe6; border-radius: 4px; }"; 14 | styleSheet += "QLineEdit:focus { border: 1px solid #409eff; }"; 15 | styleSheet += "QLineEdit { font-family: Microsoft YaHei; font-size: 14px; }"; 16 | styleSheet += "QLineEdit { padding-left: 15px; padding-right: 15px; }"; 17 | styleSheet += "QLineEdit { color: #606266; min-height: 40px; }"; 18 | 19 | setStyleSheet(styleSheet); 20 | QVariantMap options; 21 | options.insert("color", QColor(Color::PlaceholderText)); 22 | options.insert("color-active", QColor(Color::SecondaryText)); 23 | 24 | if (type == Type::Clearable) { 25 | QAction* clearAction = new QAction; 26 | clearAction->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_xmark_circle, options)); 27 | addAction(clearAction, QLineEdit::TrailingPosition); 28 | connect(clearAction, &QAction::triggered, this, [this] { this->clear(); }); 29 | } else if (type == Type::ShowPassword) { 30 | setEchoMode(QLineEdit::Password); 31 | QAction* showPasswordAction = new QAction; 32 | showPasswordAction->setCheckable(true); 33 | showPasswordAction->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_eye, options)); 34 | addAction(showPasswordAction, QLineEdit::TrailingPosition); 35 | connect(showPasswordAction, &QAction::triggered, this, [this](bool show) { this->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); }); 36 | } else if (type == Type::Calendar) { 37 | QAction* calendarAction = new QAction; 38 | calendarAction->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_calendar_days, options)); 39 | calendarAction->setCheckable(true); 40 | addAction(calendarAction, QLineEdit::TrailingPosition); 41 | connect(calendarAction, &QAction::triggered, this, [this](bool show) { 42 | // TODO: 显示日历控件 43 | }); 44 | } 45 | } 46 | 47 | EL_END_NAMESPACE 48 | -------------------------------------------------------------------------------- /qelement/el_messagebox.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGEBOX_H 2 | #define MESSAGEBOX_H 3 | 4 | #include "FramelessWindow.hpp" 5 | #include "el_global.h" 6 | #include 7 | 8 | class QLabel; 9 | class QHBoxLayout; 10 | class QPushButton; 11 | 12 | EL_BEGIN_NAMESPACE 13 | 14 | // MessageBox 弹框 15 | class EL_EXPORT MessageBox : public FramelessWindow { 16 | Q_OBJECT 17 | public: 18 | enum StandardButton { 19 | NoButton = 1 << 0, // 无按钮 20 | Ok = 1 << 1, // 确定 21 | Yes = 1 << 2, // 是 22 | No = 1 << 3, // 否 23 | Close = 1 << 4, // 关闭 24 | Cancel = 1 << 5, // 取消 25 | 26 | FirstButton = Ok, 27 | LastButton = Cancel, 28 | }; 29 | 30 | Q_DECLARE_FLAGS(StandardButtons, StandardButton) 31 | Q_FLAG(StandardButtons) 32 | 33 | typedef QMap ButtonText; 34 | 35 | MessageBox(const QIcon& icon, const QString& title, const QString& text, QWidget* parent = nullptr); 36 | 37 | // 消息提示 38 | static int alert(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText); 39 | // 确认消息 40 | static int confirm(QWidget* parent, const QString& title, const QString& text, 41 | const QString& confirmButtonText, const QString& cancelButtonText); 42 | // 错误消息 43 | static int error(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText); 44 | 45 | protected: 46 | static StandardButton showNewMessageBox(QWidget* parent, const QIcon& icon, const QString& title, const QString& text, 47 | StandardButtons buttons, StandardButton defaultButton, ButtonText buttonText); 48 | QPushButton* addButton(StandardButton button, const QString& buttonText); 49 | void init(const QIcon& icon, const QString& title, const QString& text); 50 | void setupLayout(); 51 | void setText(const QString& text); 52 | void setIcon(const QIcon& icon); 53 | void setDefaultButton(QPushButton* button); 54 | QPushButton* closeButton(); 55 | 56 | private: 57 | QLabel* _iconLabel = nullptr; 58 | QLabel* _label = nullptr; 59 | QLabel* _titleLabel = nullptr; 60 | QLabel* _titleIcon = nullptr; 61 | QHBoxLayout* _buttonBox = nullptr; 62 | }; 63 | 64 | Q_DECLARE_OPERATORS_FOR_FLAGS(MessageBox::StandardButtons) 65 | 66 | EL_END_NAMESPACE 67 | 68 | #endif // MESSAGEBOX_H 69 | -------------------------------------------------------------------------------- /qelement/el_link.cpp: -------------------------------------------------------------------------------- 1 | #include "el_link.h" 2 | #include "el_style.h" 3 | #include 4 | 5 | EL_BEGIN_NAMESPACE 6 | 7 | Link::Link(const QString& text, const QString link, Type type, QWidget* parent) 8 | : QLabel(text, parent) 9 | , _link(link) 10 | { 11 | QWidget::setAttribute(Qt::WA_TranslucentBackground); 12 | QString styleSheet; 13 | styleSheet += QString("QLabel { color : %1;font-family: Microsoft YaHei;font-size: 14px;}").arg(getColor(type)); 14 | styleSheet += QString("QLabel::disabled { color : %1;}").arg(getDisabledColor(type)); 15 | setStyleSheet(styleSheet); 16 | setMouseTracking(true); 17 | } 18 | 19 | void Link::setLink(const QString& url) 20 | { 21 | _link = url; 22 | } 23 | 24 | QString Link::getLink() 25 | { 26 | return _link; 27 | } 28 | 29 | void Link::mousePressEvent(QMouseEvent* event) 30 | { 31 | Q_UNUSED(event); 32 | emit linkClicked(_link); 33 | } 34 | 35 | QSize Link::sizeHint() const 36 | { 37 | QFont font("Microsoft YaHei"); 38 | font.setPixelSize(14); 39 | QFontMetrics metrics(font); 40 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40); 41 | } 42 | 43 | void Link::enterEvent(QEvent* event) 44 | { 45 | setCursor(Qt::PointingHandCursor); 46 | QLabel::enterEvent(event); 47 | } 48 | 49 | void Link::leaveEvent(QEvent* event) 50 | { 51 | setCursor(Qt::ArrowCursor); 52 | QLabel::leaveEvent(event); 53 | } 54 | 55 | QString Link::getColor(Type type) 56 | { 57 | switch (type) { 58 | case Default: 59 | return Color::DefaultText; 60 | case Primary: 61 | return Color::PrimaryText; 62 | case Success: 63 | return Color::Success; 64 | case Warning: 65 | return Color::Warning; 66 | case Danger: 67 | return Color::Danger; 68 | case Info: 69 | return Color::Info; 70 | default: 71 | return Color::DefaultText; 72 | } 73 | } 74 | 75 | QString Link::getDisabledColor(Type type) 76 | { 77 | switch (type) { 78 | case Default: 79 | return Color::DefaultTextDisabled; 80 | case Primary: 81 | return Color::PrimaryTextDisabled; 82 | case Success: 83 | return Color::SuccessDisabled; 84 | case Warning: 85 | return Color::WarningDisabled; 86 | case Danger: 87 | return Color::DangerDisabled; 88 | case Info: 89 | return Color::InfoDisabled; 90 | default: 91 | return Color::DefaultTextDisabled; 92 | } 93 | } 94 | 95 | EL_END_NAMESPACE 96 | -------------------------------------------------------------------------------- /qelement/el_imageprovider.cpp: -------------------------------------------------------------------------------- 1 | #include "el_imageprovider.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | EL_BEGIN_NAMESPACE 10 | 11 | ImageRunnable::ImageRunnable(const QString& url, const QString& fileName) 12 | : _url(url) 13 | , _fileName(fileName) 14 | { 15 | } 16 | 17 | void ImageRunnable::run() 18 | { 19 | emit taskStart(_url, _fileName); 20 | 21 | QNetworkAccessManager manager; 22 | QNetworkRequest request; 23 | request.setUrl(QUrl(_url)); 24 | 25 | QEventLoop eventLoop; 26 | QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit())); 27 | QNetworkReply* reply = manager.get(request); 28 | eventLoop.exec(); 29 | 30 | if (reply->error() != QNetworkReply::NoError) { 31 | qDebug() << "Download Failed at {}\n" 32 | << _url; 33 | } 34 | 35 | QFile file(_fileName); 36 | if (!file.open(QIODevice::WriteOnly)) { 37 | qDebug() << "Failed to write " << _fileName; 38 | } 39 | file.write(reply->readAll()); 40 | file.flush(); 41 | file.close(); 42 | qDebug() << "Download compeleted: " << _fileName; 43 | 44 | emit taskEnd(_url, _fileName); 45 | } 46 | 47 | ImageProvider::ImageProvider(QObject* parent) 48 | : QObject { parent } 49 | { 50 | _pool = new QThreadPool(this); 51 | QString appDataDir = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first(); 52 | _cacheDir = appDataDir + "/imagecached"; 53 | QDir dir(_cacheDir); 54 | if (!dir.exists()) { 55 | dir.mkpath(_cacheDir); 56 | } 57 | } 58 | 59 | ImageProvider::~ImageProvider() 60 | { 61 | _pool->clear(); 62 | _pool->waitForDone(); 63 | } 64 | 65 | void ImageProvider::getNetworkImage(const QString& url) 66 | { 67 | QString id = generateId(url); 68 | QString filePath = _cacheDir + "/" + id; 69 | if (QFile::exists(filePath)) { 70 | emit imageReady(url, filePath); 71 | return; 72 | } 73 | ImageRunnable* runnable = new ImageRunnable(url, filePath); 74 | runnable->setAutoDelete(true); 75 | connect(runnable, &ImageRunnable::taskEnd, this, &ImageProvider::imageReady); 76 | _pool->start(runnable); 77 | } 78 | 79 | QString ImageProvider::generateId(const QString& url) 80 | { 81 | return QString(QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5).toHex()); 82 | } 83 | 84 | EL_END_NAMESPACE 85 | -------------------------------------------------------------------------------- /qelement/el_radio.cpp: -------------------------------------------------------------------------------- 1 | #include "el_radio.h" 2 | #include "el_awesome.h" 3 | #include 4 | 5 | EL_BEGIN_NAMESPACE 6 | 7 | Radio::Radio(const QString& text, LabelPosition placement, QWidget* parent) 8 | : QAbstractButton(parent) 9 | , _placement(placement) 10 | { 11 | setText(text); 12 | setCursor(Qt::PointingHandCursor); 13 | setCheckable(true); 14 | } 15 | 16 | QSize Radio::sizeHint() const 17 | { 18 | if (text().isEmpty()) { 19 | return QSize(40, 40); 20 | } 21 | QFont font("Microsoft YaHei"); 22 | font.setPixelSize(14); 23 | QFontMetrics metrics(font); 24 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40); 25 | } 26 | 27 | QColor Radio::getColor() 28 | { 29 | if (isEnabled()) { 30 | if (isChecked()) { 31 | return QColor(0x409eff); 32 | } else { 33 | return QColor(0x606266); 34 | } 35 | } else { 36 | return QColor(0xc0c4cc); 37 | } 38 | } 39 | 40 | QIcon Radio::getIcon() 41 | { 42 | if (isEnabled()) { 43 | if (isChecked()) { 44 | return qAwesome->icon(fa::fa_solid, fa::fa_circle_dot, 45 | { { "color", QColor(0x409eff) } }); 46 | } else { 47 | return qAwesome->icon(fa::fa_regular, fa::fa_o, 48 | { { "color", QColor(0x606266) } }); 49 | } 50 | } else { 51 | if (isChecked()) { 52 | return qAwesome->icon(fa::fa_solid, fa::fa_circle_dot, 53 | { { "color", QColor(0xc0c4cc) } }); 54 | } else { 55 | return qAwesome->icon(fa::fa_regular, fa::fa_o, 56 | { { "color", QColor(0xc0c4cc) } }); 57 | } 58 | } 59 | } 60 | 61 | void Radio::paintEvent(QPaintEvent* event) 62 | { 63 | Q_UNUSED(event) 64 | QPainter painter(this); 65 | 66 | QPen pen; 67 | pen.setColor(getColor()); 68 | QFont f("Microsoft YaHei"); 69 | const int fontSize = 14; 70 | f.setPixelSize(fontSize); 71 | QFontMetrics metrics(f); 72 | int textWidth = metrics.boundingRect(text()).size().width(); 73 | painter.setFont(f); 74 | painter.setPen(pen); 75 | const int iconSize = 16; 76 | const int margin = 4; 77 | if (LabelPosition::LP_Left == _placement) { 78 | painter.drawText(margin, 0, textWidth, height(), Qt::AlignCenter, text()); 79 | } else { 80 | painter.drawText(iconSize + margin * 2, 0, textWidth, height(), Qt::AlignCenter, text()); 81 | } 82 | QPixmap pixmap = getIcon().pixmap(iconSize, iconSize); 83 | int posY = (height() - iconSize) / 2 + 1; 84 | if (LabelPosition::LP_Left == _placement) { 85 | painter.drawPixmap(textWidth + margin * 2, posY, iconSize, iconSize, pixmap); 86 | } else { 87 | painter.drawPixmap(margin, posY, iconSize, iconSize, pixmap); 88 | } 89 | } 90 | 91 | EL_END_NAMESPACE 92 | -------------------------------------------------------------------------------- /qelement/el_checkbox.cpp: -------------------------------------------------------------------------------- 1 | #include "el_checkbox.h" 2 | #include "el_awesome.h" 3 | 4 | #include 5 | 6 | EL_BEGIN_NAMESPACE 7 | 8 | Checkbox::Checkbox(const QString& text, LabelPosition placement, QWidget* parent) 9 | : QAbstractButton(parent) 10 | , _placement(placement) 11 | { 12 | setText(text); 13 | setCursor(Qt::PointingHandCursor); 14 | setCheckable(true); 15 | } 16 | 17 | QColor Checkbox::getColor() 18 | { 19 | if (isEnabled()) { 20 | if (isChecked()) { 21 | return QColor(0x409eff); 22 | } else { 23 | return QColor(0x606266); 24 | } 25 | } else { 26 | return QColor(0xc0c4cc); 27 | } 28 | } 29 | 30 | QIcon Checkbox::getIcon() 31 | { 32 | if (isEnabled()) { 33 | if (isChecked()) { 34 | return qAwesome->icon(fa::fa_solid, fa::fa_square_check, 35 | { { "color", QColor(0x409eff) } }); 36 | } else { 37 | return qAwesome->icon(fa::fa_regular, fa::fa_square, 38 | { { "color", QColor(0x606266) } }); 39 | } 40 | } else { 41 | if (isChecked()) { 42 | return qAwesome->icon(fa::fa_solid, fa::fa_square_check, 43 | { { "color", QColor(0xc0c4cc) } }); 44 | } else { 45 | return qAwesome->icon(fa::fa_regular, fa::fa_square, 46 | { { "color", QColor(0xc0c4cc) } }); 47 | } 48 | } 49 | } 50 | 51 | QSize Checkbox::sizeHint() const 52 | { 53 | if (text().isEmpty()) { 54 | return QSize(40, 40); 55 | } 56 | QFont font("Microsoft YaHei"); 57 | font.setPixelSize(14); 58 | QFontMetrics metrics(font); 59 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40); 60 | } 61 | 62 | void Checkbox::paintEvent(QPaintEvent* event) 63 | { 64 | Q_UNUSED(event) 65 | QPainter painter(this); 66 | 67 | QPen pen; 68 | pen.setColor(getColor()); 69 | QFont f("Microsoft YaHei"); 70 | const int fontSize = 14; 71 | f.setPixelSize(fontSize); 72 | QFontMetrics metrics(f); 73 | int textWidth = metrics.boundingRect(text()).size().width(); 74 | painter.setFont(f); 75 | painter.setPen(pen); 76 | const int iconSize = 16; 77 | const int margin = 4; 78 | if (LabelPosition::LP_Left == _placement) { 79 | painter.drawText(margin, 0, textWidth, height(), Qt::AlignCenter, text()); 80 | } else { 81 | painter.drawText(iconSize + margin * 2, 0, textWidth, height(), Qt::AlignCenter, text()); 82 | } 83 | QPixmap pixmap = getIcon().pixmap(iconSize, iconSize); 84 | int posY = (height() - iconSize) / 2 + 1; 85 | if (LabelPosition::LP_Left == _placement) { 86 | painter.drawPixmap(textWidth + margin * 2, posY, iconSize, iconSize, pixmap); 87 | } else { 88 | painter.drawPixmap(margin, posY, iconSize, iconSize, pixmap); 89 | } 90 | } 91 | 92 | EL_END_NAMESPACE 93 | -------------------------------------------------------------------------------- /qelement/el_card.cpp: -------------------------------------------------------------------------------- 1 | #include "el_card.h" 2 | #include 3 | #include 4 | 5 | EL_BEGIN_NAMESPACE 6 | 7 | Card::Card(const QIcon& icon, const QString& title, const QString& content, QWidget* parent) 8 | : QAbstractButton(parent) 9 | , _content(content) 10 | { 11 | setIcon(icon); 12 | setText(title); 13 | } 14 | 15 | QSize Card::sizeHint() const 16 | { 17 | return QSize(230, 70); 18 | } 19 | 20 | void Card::paintEvent(QPaintEvent* event) 21 | { 22 | Q_UNUSED(event) 23 | 24 | const int leftOffsetX = 15; 25 | const int topOffsetY = 15; 26 | 27 | QString title = text(); 28 | 29 | QFont titleFont("Microsoft YaHei"); 30 | titleFont.setPixelSize(14); 31 | QFontMetrics fmTitle(titleFont); 32 | QRect fmRectTitle = fmTitle.boundingRect(title); 33 | 34 | int iconSize = 40; 35 | 36 | double titlePosX = iconSize + leftOffsetX * 2; 37 | double titlePosY = (height() - iconSize) / 2; 38 | double titleWidth = fmRectTitle.width(); 39 | double titleHeight = fmRectTitle.height(); 40 | 41 | QFont contentFont("Microsoft YaHei"); 42 | contentFont.setPixelSize(12); 43 | QFontMetrics fmContent(contentFont); 44 | QRect fmRectContext = fmContent.boundingRect(_content); 45 | 46 | double contentPosX = titlePosX; 47 | double contentPosY = height() / 2 + iconSize / 2 - fmRectContext.height(); 48 | double contentWidth = fmRectContext.width(); 49 | double contentHeight = fmRectContext.height(); 50 | 51 | QColor titleColor(0x606266); 52 | QColor contentColor(0x909399); 53 | 54 | if (!isEnabled()) { 55 | titleColor = QColor(0xc0c4cc); 56 | contentColor = QColor(0xc0c4cc); 57 | } 58 | 59 | QPainter painter(this); 60 | 61 | QStyleOptionButton option; 62 | option.initFrom(this); 63 | if (option.state & QStyle::State_MouseOver) { 64 | painter.fillRect(option.rect, QBrush(QColor(0xf6f9fc))); 65 | } 66 | 67 | QRectF titleRect(titlePosX, titlePosY, titleWidth, titleHeight); 68 | painter.setPen(titleColor); 69 | painter.setFont(titleFont); 70 | painter.drawText(titleRect, Qt::AlignLeft | Qt::AlignTop, title); 71 | 72 | QRectF contentRect(contentPosX, contentPosY, contentWidth, contentHeight); 73 | painter.setPen(contentColor); 74 | painter.setFont(contentFont); 75 | painter.drawText(contentRect, Qt::AlignLeft | Qt::AlignBottom, _content); 76 | 77 | QPixmap pixmap = icon().pixmap(iconSize, iconSize); 78 | if (!isEnabled()) { 79 | iconToGrayscale(&pixmap); 80 | } 81 | painter.drawPixmap(QRect(leftOffsetX, topOffsetY, iconSize, iconSize), pixmap); 82 | } 83 | 84 | void Card::iconToGrayscale(QPixmap* pm) 85 | { 86 | QImage qi(pm->toImage()); 87 | int h = qi.height(); 88 | int w = qi.width(); 89 | QRgb c_rgb; 90 | for (int i = 0; i < w; ++i) { 91 | for (int j = 0; j < h; ++j) { 92 | c_rgb = qi.pixel(i, j); 93 | int k = qMin(qRound(0.3 * qRed(c_rgb) + 0.59 * qGreen(c_rgb) + 0.11 * qBlue(c_rgb)), 255); 94 | qi.setPixel(i, j, qRgba(k, k, k, qAlpha(c_rgb))); 95 | } 96 | } 97 | *pm = QPixmap::fromImage(qi); 98 | } 99 | 100 | EL_END_NAMESPACE 101 | -------------------------------------------------------------------------------- /qelement/el_inputnumber.cpp: -------------------------------------------------------------------------------- 1 | #include "el_inputnumber.h" 2 | #include "el_awesome.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | EL_BEGIN_NAMESPACE 10 | 11 | InputNumber::InputNumber(int min, int max, QWidget* parent) 12 | : QLineEdit { parent } 13 | { 14 | 15 | QVariantMap options; 16 | options.insert("color", QColor(0x606266)); 17 | options.insert("color-active", QColor(0x7fb8fe)); 18 | 19 | _minusBtn = new QPushButton(this); 20 | _minusBtn->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_minus, options)); 21 | QString minusStyle; 22 | minusStyle += "QPushButton { background:#f5f7fa; width: 40px; height: 38px;}"; 23 | minusStyle += "QPushButton { border-left: none; border-top: none; border-bottom: none; border-right: 1px solid #dcdfe6;}"; 24 | minusStyle += "QPushButton { border-top-left-radius: 4px; border-bottom-left-radius: 4px;} "; 25 | _minusBtn->setStyleSheet(minusStyle); 26 | _minusBtn->setFocusProxy(this); 27 | _minusBtn->setMouseTracking(true); 28 | 29 | connect(_minusBtn, &QPushButton::pressed, [this, min] { 30 | int value = text().toInt(); 31 | value--; 32 | if (value < min) 33 | return; 34 | setText(QString::number(value)); 35 | }); 36 | 37 | _plusBtn = new QPushButton(this); 38 | _plusBtn->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_add, options)); 39 | QString plusStyle; 40 | plusStyle += "QPushButton { background:#f5f7fa; width: 40px; height: 38px;}"; 41 | plusStyle += "QPushButton { border-left: 1px solid #dcdfe6; border-top: none; border-bottom: none; border-right: none;}"; 42 | plusStyle += "QPushButton { border-top-right-radius: 4px; border-bottom-right-radius: 4px;} "; 43 | _plusBtn->setStyleSheet(plusStyle); 44 | _plusBtn->setFocusProxy(this); 45 | _plusBtn->setMouseTracking(true); 46 | connect(_plusBtn, &QPushButton::pressed, [this, max] { 47 | int value = text().toInt(); 48 | value++; 49 | if (value > max) 50 | return; 51 | setText(QString::number(value)); 52 | }); 53 | 54 | QString styleSheet; 55 | styleSheet += "QLineEdit { border-radius: 4px; border: 1px solid #dcdfe6; padding-left: 40px; padding-right: 40px;}"; 56 | styleSheet += "QLineEdit:focus { border: 1px solid #409eff; }"; 57 | styleSheet += "QLineEdit { qproperty-alignment: AlignHCenter;}"; 58 | styleSheet += "QLineEdit { font-family: Microsoft YaHei; font-size: 14px; }"; 59 | styleSheet += "QLineEdit { color: #606266; min-height: 40px; }"; 60 | 61 | setStyleSheet(styleSheet); 62 | setValidator(new QIntValidator(this)); 63 | } 64 | 65 | void InputNumber::resizeEvent(QResizeEvent* event) 66 | { 67 | if (auto resizeEvent = dynamic_cast(event)) { 68 | QSize sz = _minusBtn->sizeHint(); 69 | int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 70 | _minusBtn->move(1, 71 | (rect().bottom() - sz.height()) / 2); 72 | 73 | sz = _plusBtn->sizeHint(); 74 | _plusBtn->move(rect().right() - frameWidth - sz.width(), 75 | (rect().bottom() - sz.height()) / 2); 76 | } 77 | } 78 | 79 | void InputNumber::mouseMoveEvent(QMouseEvent* event) 80 | { 81 | if (_minusBtn->geometry().contains(event->pos()) 82 | || _plusBtn->geometry().contains(event->pos())) { 83 | setCursor(Qt::PointingHandCursor); 84 | } else { 85 | setCursor(Qt::IBeamCursor); 86 | } 87 | } 88 | 89 | EL_END_NAMESPACE 90 | -------------------------------------------------------------------------------- /qelement/el_slider.h: -------------------------------------------------------------------------------- 1 | #ifndef EL_SLIDER_H 2 | #define EL_SLIDER_H 3 | 4 | #include "el_global.h" 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | class OverlayWidget : public QWidget { 10 | Q_OBJECT 11 | public: 12 | explicit OverlayWidget(QWidget* parent = 0); 13 | ~OverlayWidget(); 14 | 15 | protected: 16 | bool event(QEvent* event) Q_DECL_OVERRIDE; 17 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE; 18 | 19 | virtual QRect overlayGeometry() const; 20 | }; 21 | 22 | class Slider; 23 | class SliderThumb : public OverlayWidget { 24 | Q_OBJECT 25 | public: 26 | explicit SliderThumb(Slider* slider); 27 | ~SliderThumb(); 28 | void setDiameter(qreal diameter); 29 | qreal diameter() const; 30 | 31 | void setBorderWidth(qreal width); 32 | qreal borderWidth() const; 33 | 34 | void setBorderColor(const QColor& color); 35 | QColor borderColor() const; 36 | 37 | void setFillColor(const QColor& color); 38 | QColor fillColor() const; 39 | 40 | void setHaloSize(qreal size); 41 | qreal haloSize() const; 42 | 43 | void setHaloColor(const QColor& color); 44 | QColor haloColor() const; 45 | 46 | void setOffset(int offset); 47 | int offset() const; 48 | 49 | protected: 50 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE; 51 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; 52 | 53 | private: 54 | const Slider* const _slider; 55 | QColor _borderColor; 56 | QColor _fillColor; 57 | QColor _haloColor; 58 | qreal _diameter; 59 | qreal _borderWidth; 60 | qreal _haloSize; 61 | int _offset; 62 | }; 63 | 64 | class SliderTrack : public OverlayWidget { 65 | Q_OBJECT 66 | public: 67 | explicit SliderTrack(SliderThumb* thumb, Slider* slider); 68 | ~SliderTrack(); 69 | 70 | void setFillColor(const QColor& color); 71 | QColor fillColor() const; 72 | 73 | void setTrackWidth(int width); 74 | int trackWidth() const; 75 | 76 | protected: 77 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE; 78 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; 79 | 80 | private: 81 | const Slider* const _slider; 82 | SliderThumb* const _thumb; 83 | QColor _fillColor; 84 | int _trackWidth; 85 | }; 86 | 87 | // Slider 滑块 88 | class Slider : public QAbstractSlider { 89 | Q_OBJECT 90 | public: 91 | Slider(QWidget* parent = nullptr); 92 | 93 | void setThumbColor(const QColor& color); 94 | QColor thumbColor() const; 95 | 96 | void setTrackColor(const QColor& color); 97 | QColor trackColor() const; 98 | 99 | void setDisabledColor(const QColor& color); 100 | QColor disabledColor() const; 101 | 102 | void setPageStepMode(bool pageStep); 103 | bool pageStepMode() const; 104 | 105 | QSize minimumSizeHint() const Q_DECL_OVERRIDE; 106 | void setInvertedAppearance(bool value); 107 | 108 | protected: 109 | void sliderChange(SliderChange change) Q_DECL_OVERRIDE; 110 | void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE; 111 | void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE; 112 | void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE; 113 | void leaveEvent(QEvent* event) Q_DECL_OVERRIDE; 114 | 115 | void updateThumbOffset(); 116 | 117 | private: 118 | void init(); 119 | QRectF trackBoundingRect() const; 120 | QRectF thumbBoundingRect() const; 121 | int valueFromPosition(const QPoint& pos) const; 122 | void setHovered(bool status); 123 | 124 | private: 125 | SliderThumb* _thumb; 126 | SliderTrack* _track; 127 | QColor _thumbColor; 128 | QColor _trackColor; 129 | QColor _disabledColor; 130 | int _stepTo; 131 | int _oldValue; 132 | int _trackWidth; 133 | bool _hoverTrack; 134 | bool _hoverThumb; 135 | bool _hover; 136 | bool _step; 137 | bool _pageStepMode; 138 | }; 139 | 140 | EL_END_NAMESPACE 141 | 142 | #endif // EL_SLIDER_H 143 | -------------------------------------------------------------------------------- /qelement/el_avatar.cpp: -------------------------------------------------------------------------------- 1 | #include "el_avatar.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | EL_BEGIN_NAMESPACE 8 | 9 | Avatar::Avatar(QWidget* parent) 10 | : QWidget { parent } 11 | { 12 | QSizePolicy policy(QSizePolicy::MinimumExpanding, 13 | QSizePolicy::MinimumExpanding); 14 | setSizePolicy(policy); 15 | 16 | connect(&_provider, &ImageProvider::imageReady, this, &Avatar::onImageReady); 17 | } 18 | 19 | Avatar::Avatar(const QIcon& icon, QWidget* parent) 20 | : Avatar(parent) 21 | { 22 | setIcon(icon); 23 | } 24 | 25 | Avatar::Avatar(const QString& letter, QWidget* parent) 26 | : Avatar(parent) 27 | { 28 | setLetter(letter); 29 | } 30 | 31 | Avatar::Avatar(const QImage& image, QWidget* parent) 32 | : Avatar(parent) 33 | { 34 | setImage(image); 35 | } 36 | 37 | QSize Avatar::sizeHint() const 38 | { 39 | return QSize(_size + 2, _size + 2); 40 | } 41 | 42 | void Avatar::setSize(int size) 43 | { 44 | _size = size; 45 | 46 | if (!_image.isNull()) { 47 | _pixmap = QPixmap::fromImage(_image.scaled(_size, _size, 48 | Qt::IgnoreAspectRatio, 49 | Qt::SmoothTransformation)); 50 | } 51 | 52 | update(); 53 | } 54 | 55 | int Avatar::size() const 56 | { 57 | return _size; 58 | } 59 | 60 | void Avatar::setLetter(const QString& letter) 61 | { 62 | _letter = letter; 63 | _type = Letter; 64 | update(); 65 | } 66 | 67 | void Avatar::setImage(const QImage& image) 68 | { 69 | _image = image; 70 | _type = Image; 71 | 72 | _pixmap = QPixmap::fromImage(image.scaled(_size, _size, 73 | Qt::IgnoreAspectRatio, 74 | Qt::SmoothTransformation)); 75 | update(); 76 | } 77 | 78 | void Avatar::setIcon(const QIcon& icon) 79 | { 80 | _icon = icon; 81 | _type = Icon; 82 | update(); 83 | } 84 | 85 | void Avatar::setUrl(const QString& url) 86 | { 87 | if (url.isEmpty()) { 88 | return; 89 | } 90 | _provider.getNetworkImage(url); 91 | } 92 | 93 | void Avatar::onImageReady(QString url, QString filePath) 94 | { 95 | Q_UNUSED(url) 96 | if (QFile::exists(filePath)) { 97 | setImage(QImage(filePath)); 98 | return; 99 | } 100 | } 101 | 102 | Avatar::Type Avatar::type() const 103 | { 104 | return _type; 105 | } 106 | 107 | void Avatar::paintEvent(QPaintEvent* event) 108 | { 109 | Q_UNUSED(event) 110 | 111 | QPainter painter(this); 112 | painter.setRenderHint(QPainter::Antialiasing); 113 | 114 | QRect r = rect(); 115 | const qreal hs = _size / 2; 116 | 117 | if (!isEnabled()) { 118 | QBrush brush; 119 | brush.setStyle(Qt::SolidPattern); 120 | brush.setColor(QColor(0xc0c4cc)); 121 | painter.setPen(Qt::NoPen); 122 | painter.setBrush(brush); 123 | painter.drawEllipse(QRectF((width() - _size) / 2, (height() - _size) / 2, 124 | _size, _size)); 125 | return; 126 | } 127 | 128 | if (Image != _type) { 129 | QBrush brush; 130 | brush.setStyle(Qt::SolidPattern); 131 | brush.setColor(QColor(0xc0c4cc)); 132 | painter.setPen(Qt::NoPen); 133 | painter.setBrush(brush); 134 | painter.drawEllipse(QRectF((width() - _size) / 2, (height() - _size) / 2, 135 | _size, _size)); 136 | } 137 | 138 | switch (_type) { 139 | case Image: { 140 | QPainterPath path; 141 | path.addEllipse(width() / 2 - hs, height() / 2 - hs, _size, _size); 142 | painter.setClipPath(path); 143 | 144 | painter.drawPixmap(QRect(width() / 2 - hs, height() / 2 - hs, _size, _size), _pixmap); 145 | break; 146 | } 147 | case Icon: { 148 | QRect iconGeometry((width() - hs) / 2, (height() - hs) / 2, hs, hs); 149 | QPixmap pixmap = _icon.pixmap(hs, hs); 150 | QPainter icon(&pixmap); 151 | icon.setCompositionMode(QPainter::CompositionMode_SourceIn); 152 | icon.fillRect(pixmap.rect(), QColor(0xffffff)); 153 | painter.drawPixmap(iconGeometry, pixmap); 154 | break; 155 | } 156 | case Letter: { 157 | QFont f("Microsoft YaHei"); 158 | f.setPixelSize(18); 159 | painter.setFont(f); 160 | painter.setPen(QColor(0xffffff)); 161 | painter.setBrush(Qt::NoBrush); 162 | painter.drawText(r, Qt::AlignCenter, _letter); 163 | break; 164 | } 165 | default: 166 | break; 167 | } 168 | } 169 | 170 | EL_END_NAMESPACE 171 | -------------------------------------------------------------------------------- /qelement/el_button.cpp: -------------------------------------------------------------------------------- 1 | #include "el_button.h" 2 | #include "el_awesome.h" 3 | 4 | EL_BEGIN_NAMESPACE 5 | 6 | Button::Button(QWidget *parent) 7 | :QPushButton(parent) 8 | { 9 | 10 | } 11 | 12 | Button::Button(const QString& text, ButtonType type, ButtonStyle style, QWidget* parent) 13 | : Button(text, QIcon(), type, style, parent) 14 | { 15 | } 16 | 17 | Button::Button(const QIcon& icon, ButtonType type, ButtonStyle style, QWidget* parent) 18 | : Button(QString(), icon, type, style, parent) 19 | { 20 | } 21 | 22 | Button::Button(const QString& text, const QIcon& icon, ButtonType type, ButtonStyle style, QWidget* parent) 23 | : QPushButton(icon, text, parent) 24 | { 25 | init(type, style); 26 | } 27 | 28 | Button::Button(int character, ButtonType type, ButtonStyle style, QWidget* parent) 29 | : Button(QString(), character, type, style, parent) 30 | { 31 | } 32 | 33 | Button::Button(const QString& text, int character, ButtonType type, ButtonStyle style, QWidget* parent) 34 | : QPushButton(text, parent) 35 | { 36 | init(character, type, style); 37 | } 38 | 39 | void Button::init(ButtonType type, ButtonStyle style) 40 | { 41 | 42 | setCursor(Qt::PointingHandCursor); 43 | 44 | QString styleSheet; 45 | styleSheet += "QPushButton {font-family: Microsoft YaHei; font-size: 14px;}"; 46 | styleSheet += getBorderStyle(type, style); 47 | styleSheet += getColorStyle(type); 48 | styleSheet += getBkColorStyle(type); 49 | setStyleSheet(styleSheet); 50 | } 51 | 52 | void Button::init(const QIcon& icon, ButtonType type, ButtonStyle style) 53 | { 54 | init(type, style); 55 | setIcon(icon); 56 | } 57 | 58 | void Button::init(int character, ButtonType type, ButtonStyle style) 59 | { 60 | setCursor(Qt::PointingHandCursor); 61 | 62 | QVariantMap options; 63 | if (type == BT_Default) { 64 | options.insert("color", QColor(0x606266)); 65 | options.insert("color-active", QColor(0x409eff)); 66 | } else { 67 | options.insert("color", QColor(0xffffff)); 68 | options.insert("color-active", QColor(0xffffff)); 69 | } 70 | 71 | QIcon icon = qAwesome->icon(fa::fa_solid, character, options); 72 | setIcon(icon); 73 | QString styleSheet; 74 | styleSheet += "QPushButton {font-family: Microsoft YaHei; font-size: 14px;}"; 75 | styleSheet += getBorderStyle(type, style); 76 | styleSheet += getColorStyle(type); 77 | styleSheet += getBkColorStyle(type); 78 | setStyleSheet(styleSheet); 79 | if (text().isEmpty()) { 80 | setFixedSize(40, 40); 81 | } 82 | } 83 | 84 | QSize Button::sizeHint() const 85 | { 86 | if (text().isEmpty()) { 87 | return QSize(40, 40); 88 | } 89 | QFont font("Microsoft YaHei"); 90 | font.setPixelSize(14); 91 | QFontMetrics metrics(font); 92 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40); 93 | } 94 | 95 | QString Button::getBorderStyle(ButtonType type, ButtonStyle style) 96 | { 97 | QString borderStyle; 98 | // 圆角样式 99 | if (style == BS_Default) { 100 | borderStyle += "QPushButton { border-radius: 4px; }"; 101 | } else if (style == BS_Round) { 102 | borderStyle += "QPushButton { border-radius: 20px; }"; 103 | } else if (style == BS_Circle) { 104 | borderStyle += "QPushButton { border-radius: 20px; }"; 105 | } 106 | // 边框样式 107 | if (type == BT_Default) { 108 | borderStyle += "QPushButton { border: 1px solid #dcdfe6; }"; 109 | borderStyle += "QPushButton:pressed { border: 1px solid #c6e2ff; }"; 110 | } else { 111 | borderStyle += "QPushButton { border: none; }"; 112 | } 113 | 114 | return borderStyle; 115 | } 116 | 117 | QString Button::getColorStyle(ButtonType type) 118 | { 119 | QString colorStyle; 120 | if (type == BT_Default) { 121 | colorStyle += "QPushButton { color: #606266; }"; 122 | colorStyle += "QPushButton:hover { color: #409eff; }"; 123 | colorStyle += "QPushButton:pressed { color: #409eff; }"; 124 | } else { 125 | colorStyle += "QPushButton { color: #ffffff; }"; 126 | } 127 | return colorStyle; 128 | } 129 | 130 | QString Button::getBkColorStyle(ButtonType type) 131 | { 132 | QString bkColorStyle; 133 | if (type == BT_Default) { 134 | bkColorStyle += "QPushButton { background: #ffffff; }"; 135 | bkColorStyle += "QPushButton:hover { background: #ecf5ff; }"; 136 | bkColorStyle += "QPushButton:pressed { background: #ecf5ff; }"; 137 | } else if (type == BT_Primary) { 138 | bkColorStyle += "QPushButton { background: #409eff; }"; 139 | bkColorStyle += "QPushButton:hover { background: #66b1ff; }"; 140 | bkColorStyle += "QPushButton:pressed { background: #3a8ee6; }"; 141 | } else if (type == BT_Success) { 142 | bkColorStyle += "QPushButton { background: #67c23a; }"; 143 | bkColorStyle += "QPushButton:hover { background: #85ce61; }"; 144 | bkColorStyle += "QPushButton:pressed { background: #5daf34; }"; 145 | } else if (type == BT_Warning) { 146 | bkColorStyle += "QPushButton { background: #e6a23c; }"; 147 | bkColorStyle += "QPushButton:hover { background: #ebb563; }"; 148 | bkColorStyle += "QPushButton:pressed { background: #cf9236; }"; 149 | } else if (type == BT_Danger) { 150 | bkColorStyle += "QPushButton { background: #f56c6c; }"; 151 | bkColorStyle += "QPushButton:hover { background: #f78989; }"; 152 | bkColorStyle += "QPushButton:pressed { background: #dd6161; }"; 153 | } else if (type == BT_Info) { 154 | bkColorStyle += "QPushButton { background: #909399; }"; 155 | bkColorStyle += "QPushButton:hover { background: #a6a9ad; }"; 156 | bkColorStyle += "QPushButton:pressed { background: #82848a; }"; 157 | } 158 | return bkColorStyle; 159 | } 160 | 161 | EL_END_NAMESPACE 162 | -------------------------------------------------------------------------------- /qelement/el_messagebox.cpp: -------------------------------------------------------------------------------- 1 | #include "el_messagebox.h" 2 | #include "el_awesome.h" 3 | #include "el_button.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | EL_BEGIN_NAMESPACE 14 | 15 | MessageBox::MessageBox(const QIcon& icon, const QString& title, const QString& text, QWidget* parent) 16 | : FramelessWindow(true, parent, true) 17 | { 18 | init(icon, title, text); 19 | } 20 | 21 | int MessageBox::alert(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText) 22 | { 23 | return showNewMessageBox(parent, {}, title, text, StandardButton::Ok, StandardButton::Ok, { { StandardButton::Ok, confirmButtonText } }); 24 | } 25 | 26 | int MessageBox::confirm(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText, const QString& cancelButtonText) 27 | { 28 | QVariantMap options; 29 | options.insert("color", QColor(0xe6a23c)); 30 | options.insert("color-active", QColor(0xe6a23c)); 31 | QIcon icon = qAwesome->icon(fa::fa_solid, fa::fa_circle_question, options); 32 | return showNewMessageBox(parent, icon, title, text, StandardButton::Cancel | StandardButton::Ok, 33 | StandardButton::Cancel, 34 | { { StandardButton::Cancel, cancelButtonText }, { StandardButton::Ok, confirmButtonText } }); 35 | } 36 | 37 | int MessageBox::error(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText) 38 | { 39 | QVariantMap options; 40 | options.insert("color", QColor(0xF56C6C)); 41 | QIcon icon = qAwesome->icon(fa::fa_solid, fa::fa_xmark_circle, options); 42 | return showNewMessageBox(parent, icon, title, text, StandardButton::Ok, 43 | StandardButton::Ok, 44 | { { StandardButton::Ok, confirmButtonText } }); 45 | } 46 | 47 | MessageBox::StandardButton MessageBox::showNewMessageBox(QWidget* parent, const QIcon& icon, const QString& title, const QString& text, 48 | StandardButtons buttons, StandardButton defaultButton, ButtonText buttonText) 49 | { 50 | MessageBox msgBox(icon, title, text, parent); 51 | 52 | uint mask = MessageBox::LastButton; 53 | while (mask >= MessageBox::FirstButton) { 54 | uint sb = buttons & mask; 55 | mask >>= 1; 56 | if (!sb) 57 | continue; 58 | QPushButton* button = msgBox.addButton((StandardButton)sb, buttonText[(StandardButton)sb]); 59 | if (sb == defaultButton) { 60 | msgBox.setDefaultButton(button); 61 | } 62 | } 63 | 64 | return (StandardButton)msgBox.exec(); 65 | } 66 | 67 | void MessageBox::setDefaultButton(QPushButton* button) 68 | { 69 | if (button == nullptr) 70 | return; 71 | 72 | button->setDefault(true); 73 | button->setFocus(); 74 | } 75 | 76 | QPushButton* MessageBox::addButton(MessageBox::StandardButton button, const QString& buttonText) 77 | { 78 | QPushButton* pushButton = nullptr; 79 | pushButton = new Button(buttonText, Button::BT_Primary, Button::BS_Default, this); 80 | connect(pushButton, &QPushButton::clicked, [this, button] { 81 | done(button); 82 | }); 83 | _buttonBox->addWidget(pushButton); 84 | return pushButton; 85 | } 86 | 87 | void MessageBox::init(const QIcon& icon, const QString& title, const QString& text) 88 | { 89 | setStyleSheet("border-radius: 4px;"); 90 | _label = new QLabel; 91 | _label->setTextInteractionFlags(Qt::TextInteractionFlags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this))); 92 | _label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); 93 | _label->setOpenExternalLinks(true); 94 | _iconLabel = new QLabel(this); 95 | _iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 96 | 97 | if (!icon.isNull()) 98 | _iconLabel->setPixmap(icon.pixmap(QSize(24, 24))); 99 | 100 | _titleLabel = new QLabel; 101 | _titleLabel->setStyleSheet("QLabel { font-family: Microsoft YaHei; font-size: 18px; color: #303133}"); 102 | _titleLabel->setText(title); 103 | 104 | _label->setStyleSheet("QLabel { font-family: Microsoft YaHei; font-size: 14px; color: #606266}"); 105 | 106 | setupLayout(); 107 | 108 | if (!title.isEmpty() || !text.isEmpty()) { 109 | setWindowTitle(title); 110 | setText(text); 111 | } 112 | 113 | setContentsMargins(14, 14, 14, 14); 114 | setMinimumSize(400, 200); 115 | 116 | setModal(true); 117 | } 118 | 119 | QPushButton* MessageBox::closeButton() 120 | { 121 | QPushButton* closeBtn = new QPushButton(); 122 | QVariantMap options; 123 | options.insert("color", QColor(0x909399)); 124 | options.insert("color-active", QColor(0x409eff)); 125 | QIcon icon = qAwesome->icon(fa::fa_solid, fa::fa_close, options); 126 | closeBtn->setIcon(icon); 127 | closeBtn->setStyleSheet("QPushButton { background-color: transparent; border: 0px }"); 128 | connect(closeBtn, &QPushButton::clicked, [this] { 129 | done(MessageBox::Close); 130 | }); 131 | return closeBtn; 132 | } 133 | 134 | void MessageBox::setupLayout() 135 | { 136 | QWidget* centralWidget = new QWidget(); 137 | QHBoxLayout* bkLayout = new QHBoxLayout(); 138 | bkLayout->setContentsMargins(0, 0, 0, 0); 139 | bkLayout->addWidget(centralWidget); 140 | setLayout(bkLayout); 141 | 142 | // 窗口拖动部位 143 | setTitlebar({ centralWidget, _label }); 144 | 145 | // 创建窗口阴影效果 146 | QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect(); 147 | shadow->setColor(QColor(0, 0, 0, 64)); 148 | shadow->setOffset(0, 2); 149 | shadow->setBlurRadius(14); 150 | centralWidget->setGraphicsEffect(shadow); 151 | 152 | const QPixmap* piamap = _iconLabel->pixmap(); 153 | const bool hasIcon = piamap != nullptr && !piamap->isNull(); 154 | 155 | QVBoxLayout* mainLayout = new QVBoxLayout(); 156 | 157 | QHBoxLayout* titleLeft = new QHBoxLayout(); 158 | titleLeft->setAlignment(Qt::AlignLeft); 159 | if (_titleIcon) { 160 | titleLeft->addWidget(_titleIcon); 161 | } 162 | titleLeft->addWidget(_titleLabel); 163 | 164 | // 标题栏部分 165 | QHBoxLayout* titleRight = new QHBoxLayout(); 166 | titleRight->setAlignment(Qt::AlignRight); 167 | QPushButton* closeBtn = closeButton(); 168 | titleRight->addWidget(closeBtn); 169 | 170 | QHBoxLayout* titleBar = new QHBoxLayout(); 171 | titleBar->addLayout(titleLeft); 172 | titleBar->addLayout(titleRight); 173 | 174 | mainLayout->addLayout(titleBar); 175 | 176 | QHBoxLayout* contentLayout = new QHBoxLayout; 177 | contentLayout->setContentsMargins(15, 10, 15, 10); 178 | if (hasIcon) 179 | contentLayout->addWidget(_iconLabel, Qt::AlignCenter); 180 | _iconLabel->setVisible(hasIcon); 181 | 182 | contentLayout->addWidget(_label, Qt::AlignCenter); 183 | 184 | _buttonBox = new QHBoxLayout(); 185 | _buttonBox->addStretch(0); 186 | 187 | mainLayout->addLayout(contentLayout); 188 | mainLayout->addLayout(_buttonBox); 189 | 190 | centralWidget->setLayout(mainLayout); 191 | } 192 | 193 | void MessageBox::setText(const QString& text) 194 | { 195 | _label->setText(text); 196 | _label->setWordWrap(_label->textFormat() == Qt::RichText 197 | || (_label->textFormat() == Qt::AutoText && Qt::mightBeRichText(text))); 198 | } 199 | 200 | EL_END_NAMESPACE 201 | -------------------------------------------------------------------------------- /qelement/el_switch.cpp: -------------------------------------------------------------------------------- 1 | // SwitchButton 2 | // Copyright (c) 2018 Iman Ahmadvand 3 | // Copyright (c) 2021 WANDERSON M.PIMENTA 4 | // Copyright (c) 2023 CM0use 5 | 6 | #include "el_switch.h" 7 | 8 | #include 9 | #include 10 | 11 | QT_BEGIN_NAMESPACE 12 | class QPropertyAnimation; 13 | extern Q_DECL_IMPORT void qt_blurImage(QPainter* p, QImage& blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); 14 | QT_END_NAMESPACE 15 | 16 | QPixmap drawShadowEllipse(const qreal& radius, const qreal& elevation, const QColor& color) 17 | { 18 | QPixmap px { qRound(radius * 2), qRound(radius * 2) }; 19 | px.fill(Qt::transparent); 20 | 21 | QPainter p { &px }; 22 | 23 | p.setBrush(color); 24 | p.setPen(Qt::NoPen); 25 | p.setRenderHint(QPainter::Antialiasing); 26 | p.drawEllipse(QRectF(0, 0, px.size().width(), px.size().height()).center(), 27 | radius - elevation, 28 | radius - elevation); 29 | p.end(); 30 | 31 | QImage tmp { px.size(), QImage::Format_ARGB32_Premultiplied }; 32 | tmp.setDevicePixelRatio(px.devicePixelRatioF()); 33 | tmp.fill(0); 34 | QImage blurred { tmp }; 35 | p.begin(&tmp); 36 | p.setCompositionMode(QPainter::CompositionMode_Source); 37 | p.drawPixmap(QPointF(), px); 38 | p.end(); 39 | 40 | p.begin(&blurred); 41 | qt_blurImage(&p, tmp, elevation * 4, true, false); 42 | p.end(); 43 | 44 | return QPixmap::fromImage(blurred); 45 | } 46 | 47 | EL_BEGIN_NAMESPACE 48 | 49 | Switch::Switch(QWidget* const parent) 50 | : QAbstractButton { parent } 51 | , CORNER_RADIUS { 14 } 52 | , THUMB_RADIUS { 14 } 53 | , SHADOW_ELEVATION { 2.0 } 54 | , height { 36 } 55 | , indicatorMargin { 8, 4, 8, 4 } 56 | , thumbOnColor { Qt::white } 57 | , thumbOffColor { Qt::white } 58 | , trackOnColor { 0x13ce66 } 59 | , trackOffColor { 0xff4949 } 60 | , trackDisabledColor { Qt::gray } 61 | , thumbDisabledColor { Qt::white } 62 | , trackDisabledOpacity { 0.25 } 63 | , disabledTextOpacity { 0.25 } 64 | , 65 | 66 | thumbPosAnimation { new QPropertyAnimation(this, "thumbPosition", this) } 67 | , _thumbPosition { isChecked() ? (indicatorMargin.left() + indicatorMargin.right() + 2) : 0 } 68 | , shadowPixmap { drawShadowEllipse(THUMB_RADIUS, SHADOW_ELEVATION, QColor(0, 0, 0, 70)) } 69 | { 70 | setCursor(Qt::PointingHandCursor); 71 | setCheckable(true); 72 | 73 | thumbPosAnimation->setDuration(150); 74 | thumbPosAnimation->setEasingCurve(QEasingCurve::OutQuad); 75 | } 76 | 77 | Switch::Switch(const QString& text, QWidget* const parent) 78 | : Switch { parent } 79 | { 80 | setText(text); 81 | } 82 | 83 | void Switch::setTrackColor(const QColor& trackOnColor, const QColor& trackOffColor) 84 | { 85 | this->trackOnColor = trackOnColor; 86 | this->trackOffColor = trackOffColor; 87 | } 88 | 89 | void Switch::setThumbColor(const QColor& thumbOnColor, const QColor& thumbOffColor) 90 | { 91 | this->thumbOnColor = thumbOnColor; 92 | this->thumbOffColor = thumbOffColor; 93 | } 94 | 95 | void Switch::setHieght(int nHeight) 96 | { 97 | this->height = nHeight; 98 | } 99 | 100 | void Switch::setRadius(qreal corner_radius, qreal thumb_radius) 101 | { 102 | CORNER_RADIUS = corner_radius; 103 | THUMB_RADIUS = thumb_radius; 104 | shadowPixmap = drawShadowEllipse(THUMB_RADIUS, SHADOW_ELEVATION, QColor(0, 0, 0, 70)); 105 | } 106 | 107 | QSize Switch::sizeHint() const 108 | { 109 | auto w { indicatorMargin.left() 110 | + height 111 | + indicatorMargin.right() 112 | + fontMetrics().horizontalAdvance(text()) }; 113 | 114 | return QSize { w, height }; 115 | } 116 | 117 | QRect Switch::indicatorRect() 118 | { 119 | const auto w { indicatorMargin.left() 120 | + height 121 | + indicatorMargin.right() }; 122 | 123 | return isLeftToRight() ? QRect(0, 0, w, height) : QRect(width() - w, 0, w, height); 124 | } 125 | 126 | QRect Switch::textRect() 127 | { 128 | const auto w { indicatorMargin.left() 129 | + height 130 | + indicatorMargin.right() }; 131 | 132 | return isLeftToRight() ? rect().marginsRemoved(QMargins(w, 0, 0, 0)) : rect().marginsRemoved(QMargins(0, 0, w, 0)); 133 | } 134 | 135 | void Switch::paintEvent(QPaintEvent* const) 136 | { 137 | QPainter p { this }; 138 | p.setPen(Qt::NoPen); 139 | p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); 140 | 141 | QMargins trackMargin { indicatorMargin }; 142 | trackMargin.setTop(trackMargin.top() + 2); 143 | trackMargin.setBottom(trackMargin.bottom() + 2); 144 | 145 | QRectF trackRect { indicatorRect().marginsRemoved(trackMargin) }; 146 | 147 | if (isEnabled()) { 148 | /* DRAW TRACK */ 149 | p.setBrush(isChecked() ? trackOnColor : trackOffColor); 150 | p.drawRoundedRect(trackRect, CORNER_RADIUS, CORNER_RADIUS); 151 | 152 | /* DRAW THUMB */ 153 | trackRect.setX(trackRect.x() - trackMargin.left() - trackMargin.right() - 2 154 | + thumbPosAnimation->currentValue().toInt()); 155 | if (!shadowPixmap.isNull()) 156 | p.drawPixmap(trackRect.center() - QPointF(THUMB_RADIUS, THUMB_RADIUS - 1.0), shadowPixmap); 157 | p.setBrush(isChecked() ? thumbOnColor : thumbOffColor); 158 | p.drawEllipse(trackRect.center(), THUMB_RADIUS - SHADOW_ELEVATION - 1.0, THUMB_RADIUS - SHADOW_ELEVATION - 1.0); 159 | 160 | /* DRAW TEXT */ 161 | if (!text().isEmpty()) { 162 | QFont font("Microsoft YaHei"); 163 | font.setPixelSize(14); 164 | p.setFont(font); 165 | p.setPen(QColor(0x303133)); 166 | p.setPen(palette().color(QPalette::Active, QPalette::ButtonText)); 167 | p.drawText(textRect(), Qt::AlignLeft | Qt::AlignVCenter, text()); 168 | } 169 | } else { 170 | /* DRAW TRACK */ 171 | p.setBrush(trackDisabledColor); 172 | p.setOpacity(trackDisabledOpacity); 173 | p.drawRoundedRect(trackRect, CORNER_RADIUS, CORNER_RADIUS); 174 | 175 | /* DRAW THUMB */ 176 | p.setOpacity(1.0); 177 | if (isChecked()) 178 | trackRect.setX(trackRect.x() + trackMargin.left() + trackMargin.right() + 2); 179 | else 180 | trackRect.setX(trackRect.x() - trackMargin.left() - trackMargin.right() - 2); 181 | if (!shadowPixmap.isNull()) 182 | p.drawPixmap(trackRect.center() - QPointF(THUMB_RADIUS, THUMB_RADIUS - 1.0), shadowPixmap); 183 | p.setBrush(thumbDisabledColor); 184 | p.drawEllipse(trackRect.center(), THUMB_RADIUS - SHADOW_ELEVATION - 1.0, THUMB_RADIUS - SHADOW_ELEVATION - 1.0); 185 | 186 | /* DRAW TEXT */ 187 | if (!text().isEmpty()) { 188 | QFont font("Microsoft YaHei"); 189 | font.setPixelSize(14); 190 | p.setFont(font); 191 | p.setOpacity(disabledTextOpacity); 192 | p.setPen(palette().color(QPalette::Disabled, QPalette::ButtonText)); 193 | p.drawText(textRect(), Qt::AlignLeft | Qt::AlignVCenter, text()); 194 | } 195 | } 196 | } 197 | 198 | void Switch::nextCheckState() 199 | { 200 | QAbstractButton::nextCheckState(); 201 | checkStateSet(); 202 | } 203 | 204 | void Switch::checkStateSet() 205 | { 206 | const Qt::CheckState state { isChecked() ? Qt::Checked : Qt::Unchecked }; 207 | toggle(state); 208 | emit stateChanged(state); 209 | } 210 | 211 | void Switch::toggle(const Qt::CheckState& state) 212 | { 213 | thumbPosAnimation->stop(); 214 | if (state == Qt::Unchecked) 215 | thumbPosAnimation->setEndValue(0); 216 | else 217 | thumbPosAnimation->setEndValue((indicatorMargin.left() + indicatorMargin.right() + 2) * 2); 218 | thumbPosAnimation->start(); 219 | } 220 | 221 | void Switch::setThumbPosition(const int& thumbPosition) 222 | { 223 | this->_thumbPosition = thumbPosition; 224 | update(); 225 | emit thumbPositionChanged(); 226 | } 227 | 228 | int Switch::thumbPosition() 229 | { 230 | return _thumbPosition; 231 | } 232 | 233 | EL_END_NAMESPACE 234 | -------------------------------------------------------------------------------- /example/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | #include "QtAwesome.h" 3 | #include "el_avatar.h" 4 | #include "el_button.h" 5 | #include "el_checkbox.h" 6 | #include "el_input.h" 7 | #include "el_link.h" 8 | #include "el_messagebox.h" 9 | #include "el_select.h" 10 | #include "el_switch.h" 11 | #include "el_inputnumber.h" 12 | #include "el_radio.h" 13 | #include "el_card.h" 14 | #include "el_slider.h" 15 | #include "el_lineprogress.h" 16 | #include "el_circleprogress.h" 17 | #include "ui_widget.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace el; 26 | 27 | Widget::Widget(QWidget* parent) 28 | : QWidget(parent) 29 | , ui(new Ui::Widget) 30 | { 31 | ui->setupUi(this); 32 | setStyleSheet("background-color: white"); 33 | 34 | QVBoxLayout* vLayout = new QVBoxLayout(); 35 | 36 | QHBoxLayout* hLayout = new QHBoxLayout(); 37 | vLayout->addLayout(hLayout); 38 | 39 | // Link 文字链接 40 | Link* link = new Link("默认链接", "https://www.baidu.com", Link::Danger, this); 41 | // link->setDisabled(true); 42 | connect(link, &Link::linkClicked, [](const QString& link) { 43 | qDebug() << "linkClicked" << link; 44 | }); 45 | 46 | Link* link2 = new Link("成功链接", "https://www.baidu.com", Link::Success, this); 47 | 48 | hLayout->addWidget(link); 49 | hLayout->addWidget(link2); 50 | 51 | // Input 输入框 52 | QHBoxLayout* hLayout2 = new QHBoxLayout(); 53 | vLayout->addLayout(hLayout2); 54 | Input* input = new Input(Input::Clearable, this); 55 | Input* input2 = new Input(Input::ShowPassword, this); 56 | Input* input3 = new Input(Input::Calendar, this); 57 | hLayout2->addWidget(input); 58 | hLayout2->addWidget(input2); 59 | hLayout2->addWidget(input3); 60 | 61 | // Button 按钮 62 | QHBoxLayout* hLayout3 = new QHBoxLayout(); 63 | vLayout->addLayout(hLayout3); 64 | Button* btn = new Button("默认按钮"); 65 | Button* btn2 = new Button("主要按钮", Button::BT_Primary); 66 | Button* btn3 = new Button("成功按钮", Button::BT_Success); 67 | Button* btn4 = new Button("警告按钮", Button::BT_Warning); 68 | Button* btn5 = new Button("危险按钮", Button::BT_Danger); 69 | Button* btn6 = new Button("信息按钮", Button::BT_Info); 70 | 71 | hLayout3->addWidget(btn); 72 | hLayout3->addWidget(btn2); 73 | hLayout3->addWidget(btn3); 74 | hLayout3->addWidget(btn4); 75 | hLayout3->addWidget(btn5); 76 | hLayout3->addWidget(btn6); 77 | 78 | // 圆角 按钮 79 | QHBoxLayout* hLayout4 = new QHBoxLayout(); 80 | vLayout->addLayout(hLayout4); 81 | Button* rbtn2 = new Button("主要按钮", Button::BT_Primary, Button::BS_Round); 82 | Button* rbtn3 = new Button("成功按钮", Button::BT_Success, Button::BS_Round); 83 | Button* rbtn4 = new Button("警告按钮", Button::BT_Warning, Button::BS_Round); 84 | Button* rbtn5 = new Button("危险按钮", Button::BT_Danger, Button::BS_Round); 85 | Button* rbtn6 = new Button("信息按钮", Button::BT_Info, Button::BS_Round); 86 | 87 | hLayout4->addWidget(rbtn2); 88 | hLayout4->addWidget(rbtn3); 89 | hLayout4->addWidget(rbtn4); 90 | hLayout4->addWidget(rbtn5); 91 | hLayout4->addWidget(rbtn6); 92 | 93 | // ICON 按钮 94 | QHBoxLayout* hLayout5 = new QHBoxLayout(); 95 | vLayout->addLayout(hLayout5); 96 | Button* ibtn = new Button(fa::fa_add, Button::BT_Default); 97 | Button* ibtn2 = new Button(fa::fa_add, Button::BT_Primary); 98 | Button* ibtn3 = new Button(fa::fa_bookmark, Button::BT_Success); 99 | Button* ibtn4 = new Button(fa::fa_camera, Button::BT_Warning); 100 | Button* ibtn5 = new Button(fa::fa_dashboard, Button::BT_Danger); 101 | Button* ibtn6 = new Button(fa::fa_edit, Button::BT_Info); 102 | Button* ibtn7 = new Button("搜索", fa::fa_search, Button::BT_Primary); 103 | 104 | hLayout5->addWidget(ibtn); 105 | hLayout5->addWidget(ibtn2); 106 | hLayout5->addWidget(ibtn3); 107 | hLayout5->addWidget(ibtn4); 108 | hLayout5->addWidget(ibtn5); 109 | hLayout5->addWidget(ibtn6); 110 | hLayout5->addWidget(ibtn7); 111 | 112 | // Switch 开关 113 | QHBoxLayout* hLayout6 = new QHBoxLayout(); 114 | vLayout->addLayout(hLayout6); 115 | Switch* switch1 = new Switch("开关"); 116 | Switch* switch2 = new Switch("禁用开关"); 117 | switch2->setDisabled(true); 118 | hLayout6->addWidget(switch1); 119 | hLayout6->addWidget(switch2); 120 | 121 | // Checkbox 多选框 122 | Checkbox* cbx1 = new Checkbox("备选项"); 123 | Checkbox* cbx2 = new Checkbox("备选项", Checkbox::LP_Left); 124 | Radio* rdo1 = new Radio("单选项1"); 125 | Radio* rdo2 = new Radio("单选项2"); 126 | QButtonGroup *group = new QButtonGroup(this); 127 | group->addButton(rdo1); 128 | group->addButton(rdo2); 129 | group->setExclusive(true); 130 | 131 | hLayout6->addWidget(cbx1); 132 | hLayout6->addWidget(cbx2); 133 | hLayout6->addWidget(rdo1); 134 | hLayout6->addWidget(rdo2); 135 | 136 | // Avatar 头像 137 | QHBoxLayout* hLayout7 = new QHBoxLayout(); 138 | vLayout->addLayout(hLayout7); 139 | Avatar* avatar1 = new Avatar("姓"); 140 | Avatar* avatar2 = new Avatar(QImage(":/avatar.png")); 141 | hLayout7->addWidget(avatar1); 142 | hLayout7->addWidget(avatar2); 143 | 144 | // MessageBox 弹框 145 | QHBoxLayout* hLayout8 = new QHBoxLayout(); 146 | vLayout->addLayout(hLayout8); 147 | Button* btn7 = new Button("消息提示 Message Box", Button::BT_Default); 148 | connect(btn7, &Button::clicked, [this]() { 149 | int ret = MessageBox::alert(this, "标题名称", "这是一段内容", "确定"); 150 | qDebug() << ret; 151 | }); 152 | Button* btn8 = new Button("确认消息 Message Box", Button::BT_Default); 153 | connect(btn8, &Button::clicked, [this]() { 154 | int ret = MessageBox::confirm(this, "提示", "此操作将永久删除该文件, 是否继续?", "确定", "取消"); 155 | qDebug() << ret; 156 | }); 157 | Button* btn9 = new Button("错误消息 Message Box", Button::BT_Default); 158 | connect(btn9, &Button::clicked, [this]() { 159 | int ret = MessageBox::error(this, "错误", "文件不存在!\n请重新选择", "确定"); 160 | qDebug() << ret; 161 | }); 162 | hLayout8->addWidget(btn7); 163 | hLayout8->addWidget(btn8); 164 | hLayout8->addWidget(btn9); 165 | 166 | // Select 选择器 167 | QHBoxLayout* hLayout9 = new QHBoxLayout(); 168 | vLayout->addLayout(hLayout9); 169 | Select* select1 = new Select(); 170 | select1->addItems(QStringList() << "黄金糕" 171 | << "双皮奶" 172 | << "蚵仔煎" 173 | << "龙须面"); 174 | hLayout9->addWidget(select1); 175 | 176 | QHBoxLayout* hLayout10 = new QHBoxLayout(); 177 | vLayout->addLayout(hLayout10); 178 | InputNumber* inputNum1 = new InputNumber(0, 10); 179 | hLayout10->addWidget(inputNum1); 180 | 181 | QHBoxLayout* hLayout11 = new QHBoxLayout(); 182 | vLayout->addLayout(hLayout11); 183 | Card* card1 = new Card(QIcon(":/avatar.png"), "卡片名称1", "列表内容 1"); 184 | Card* card2 = new Card(QIcon(":/avatar.png"), "卡片名称2", "列表内容 1"); 185 | card2->setEnabled(false); 186 | hLayout11->addWidget(card1); 187 | hLayout11->addWidget(card2); 188 | 189 | // 线形进度条 190 | QHBoxLayout* hLayout12 = new QHBoxLayout(); 191 | vLayout->addLayout(hLayout12); 192 | LineProgress* lineProgress1 = new LineProgress(); 193 | lineProgress1->setValue(50); 194 | LineProgress* lineProgress2 = new LineProgress(); 195 | lineProgress2->setValue(70); 196 | lineProgress2->setStatus(LineProgress::Success); 197 | LineProgress* lineProgress3 = new LineProgress(); 198 | lineProgress3->setValue(80); 199 | lineProgress3->setStatus(LineProgress::Warning); 200 | hLayout12->addWidget(lineProgress1); 201 | hLayout12->addWidget(lineProgress2); 202 | hLayout12->addWidget(lineProgress3); 203 | 204 | // 环形进度条 205 | QHBoxLayout* hLayout13 = new QHBoxLayout(); 206 | vLayout->addLayout(hLayout13); 207 | CircleProgress* circleProgress1 = new CircleProgress(); 208 | circleProgress1->setPercent(60); 209 | hLayout13->addWidget(circleProgress1); 210 | CircleProgress* circleProgress2 = new CircleProgress(); 211 | circleProgress2->setPercent(80); 212 | circleProgress2->setStatus(CircleProgress::Exception); 213 | hLayout13->addWidget(circleProgress2); 214 | 215 | setLayout(vLayout); 216 | } 217 | 218 | Widget::~Widget() 219 | { 220 | delete ui; 221 | } 222 | -------------------------------------------------------------------------------- /qelement/el_slider.cpp: -------------------------------------------------------------------------------- 1 | #include "el_slider.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define QT_MATERIAL_SLIDER_MARGIN 30 9 | 10 | EL_BEGIN_NAMESPACE 11 | 12 | OverlayWidget::OverlayWidget(QWidget* parent) 13 | : QWidget(parent) 14 | { 15 | if (parent) { 16 | parent->installEventFilter(this); 17 | } 18 | } 19 | 20 | OverlayWidget::~OverlayWidget() 21 | { 22 | } 23 | 24 | bool OverlayWidget::event(QEvent* event) 25 | { 26 | if (!parent()) { 27 | return QWidget::event(event); 28 | } 29 | switch (event->type()) { 30 | case QEvent::ParentChange: { 31 | parent()->installEventFilter(this); 32 | setGeometry(overlayGeometry()); 33 | break; 34 | } 35 | case QEvent::ParentAboutToChange: { 36 | parent()->removeEventFilter(this); 37 | break; 38 | } 39 | default: 40 | break; 41 | } 42 | return QWidget::event(event); 43 | } 44 | 45 | bool OverlayWidget::eventFilter(QObject* obj, QEvent* event) 46 | { 47 | switch (event->type()) { 48 | case QEvent::Move: 49 | case QEvent::Resize: 50 | setGeometry(overlayGeometry()); 51 | break; 52 | default: 53 | break; 54 | } 55 | return QWidget::eventFilter(obj, event); 56 | } 57 | 58 | QRect OverlayWidget::overlayGeometry() const 59 | { 60 | QWidget* widget = parentWidget(); 61 | if (!widget) { 62 | return QRect(); 63 | } 64 | return widget->rect(); 65 | } 66 | 67 | SliderThumb::SliderThumb(Slider* slider) 68 | : OverlayWidget(slider->parentWidget()) 69 | , _slider(slider) 70 | , _diameter(16) 71 | , _borderWidth(2) 72 | , _offset(0) 73 | { 74 | slider->installEventFilter(this); 75 | setAttribute(Qt::WA_TransparentForMouseEvents, true); 76 | } 77 | 78 | SliderThumb::~SliderThumb() 79 | { 80 | } 81 | 82 | void SliderThumb::setDiameter(qreal diameter) 83 | { 84 | _diameter = diameter; 85 | update(); 86 | } 87 | 88 | qreal SliderThumb::diameter() const 89 | { 90 | return _diameter; 91 | } 92 | 93 | void SliderThumb::setBorderWidth(qreal width) 94 | { 95 | _borderWidth = width; 96 | update(); 97 | } 98 | 99 | qreal SliderThumb::borderWidth() const 100 | { 101 | return _borderWidth; 102 | } 103 | 104 | void SliderThumb::setBorderColor(const QColor& color) 105 | { 106 | _borderColor = color; 107 | update(); 108 | } 109 | 110 | QColor SliderThumb::borderColor() const 111 | { 112 | return _borderColor; 113 | } 114 | 115 | void SliderThumb::setFillColor(const QColor& color) 116 | { 117 | _fillColor = color; 118 | update(); 119 | } 120 | 121 | QColor SliderThumb::fillColor() const 122 | { 123 | return _fillColor; 124 | } 125 | 126 | void SliderThumb::setHaloSize(qreal size) 127 | { 128 | _haloSize = size; 129 | update(); 130 | } 131 | 132 | qreal SliderThumb::haloSize() const 133 | { 134 | return _haloSize; 135 | } 136 | 137 | void SliderThumb::setHaloColor(const QColor& color) 138 | { 139 | _haloColor = color; 140 | update(); 141 | } 142 | 143 | QColor SliderThumb::haloColor() const 144 | { 145 | return _haloColor; 146 | } 147 | 148 | void SliderThumb::setOffset(int offset) 149 | { 150 | _offset = offset; 151 | update(); 152 | } 153 | 154 | int SliderThumb::offset() const 155 | { 156 | return _offset; 157 | } 158 | 159 | bool SliderThumb::eventFilter(QObject* obj, QEvent* event) 160 | { 161 | if (QEvent::ParentChange == event->type()) { 162 | setParent(_slider->parentWidget()); 163 | } 164 | 165 | return QWidget::eventFilter(obj, event); 166 | } 167 | 168 | void SliderThumb::paintEvent(QPaintEvent* event) 169 | { 170 | Q_UNUSED(event) 171 | 172 | QPainter painter(this); 173 | painter.setRenderHint(QPainter::Antialiasing); 174 | 175 | // Halo 176 | 177 | QBrush brush; 178 | brush.setStyle(Qt::SolidPattern); 179 | brush.setColor(_haloColor); 180 | painter.setBrush(brush); 181 | painter.setPen(Qt::NoPen); 182 | 183 | QPointF disp = Qt::Horizontal == _slider->orientation() 184 | ? QPointF(QT_MATERIAL_SLIDER_MARGIN + _offset, _slider->height() / 2) 185 | : QPointF(_slider->width() / 2, QT_MATERIAL_SLIDER_MARGIN + _offset); 186 | 187 | QRectF halo((_slider->pos() - QPointF(_haloSize, _haloSize) / 2) + disp, 188 | QSizeF(_haloSize, _haloSize)); 189 | 190 | painter.setOpacity(0.15); 191 | painter.drawEllipse(halo); 192 | 193 | // Knob 194 | 195 | const bool isMin = _slider->value() == _slider->minimum(); 196 | 197 | brush.setColor(_slider->isEnabled() 198 | ? _fillColor 199 | : _slider->disabledColor()); 200 | painter.setBrush(!_slider->isEnabled() && isMin 201 | ? Qt::NoBrush 202 | : brush); 203 | 204 | if (_slider->isEnabled() || isMin) { 205 | QPen pen; 206 | pen.setColor(_borderColor); 207 | pen.setWidthF((isMin && !_slider->isEnabled()) ? 1.7 : _borderWidth); 208 | painter.setPen(pen); 209 | } else { 210 | painter.setPen(Qt::NoPen); 211 | } 212 | 213 | QRectF geometry = Qt::Horizontal == _slider->orientation() 214 | ? QRectF(_offset, _slider->height() / 2 - QT_MATERIAL_SLIDER_MARGIN, 215 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2) 216 | .translated(_slider->pos()) 217 | : QRectF(_slider->width() / 2 - QT_MATERIAL_SLIDER_MARGIN, _offset, 218 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2) 219 | .translated(_slider->pos()); 220 | 221 | qreal s = _slider->isEnabled() ? _diameter : 7; 222 | 223 | QRectF thumb(0, 0, s, s); 224 | 225 | thumb.moveCenter(geometry.center()); 226 | 227 | painter.setOpacity(1); 228 | painter.drawEllipse(thumb); 229 | } 230 | 231 | // SliderTrack 232 | SliderTrack::SliderTrack(SliderThumb* thumb, Slider* slider) 233 | : OverlayWidget(slider->parentWidget()) 234 | , _slider(slider) 235 | , _thumb(thumb) 236 | { 237 | slider->installEventFilter(this); 238 | 239 | setAttribute(Qt::WA_TransparentForMouseEvents, true); 240 | 241 | connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(update())); 242 | } 243 | 244 | SliderTrack::~SliderTrack() 245 | { 246 | } 247 | 248 | void SliderTrack::setFillColor(const QColor& color) 249 | { 250 | _fillColor = color; 251 | update(); 252 | } 253 | 254 | QColor SliderTrack::fillColor() const 255 | { 256 | return _fillColor; 257 | } 258 | 259 | void SliderTrack::setTrackWidth(int width) 260 | { 261 | _trackWidth = width; 262 | update(); 263 | } 264 | 265 | int SliderTrack::trackWidth() const 266 | { 267 | return _trackWidth; 268 | } 269 | 270 | bool SliderTrack::eventFilter(QObject* obj, QEvent* event) 271 | { 272 | if (QEvent::ParentChange == event->type()) { 273 | setParent(_slider->parentWidget()); 274 | } 275 | 276 | return QWidget::eventFilter(obj, event); 277 | } 278 | 279 | void SliderTrack::paintEvent(QPaintEvent* event) 280 | { 281 | Q_UNUSED(event) 282 | 283 | QPainter painter(this); 284 | painter.setRenderHint(QPainter::Antialiasing); 285 | 286 | QBrush fg; 287 | fg.setStyle(Qt::SolidPattern); 288 | fg.setColor(_slider->isEnabled() ? _slider->thumbColor() 289 | : _slider->disabledColor()); 290 | QBrush bg; 291 | bg.setStyle(Qt::SolidPattern); 292 | bg.setColor(_slider->isEnabled() ? _fillColor 293 | : _slider->disabledColor()); 294 | 295 | qreal offset = _thumb->offset(); 296 | 297 | if (Qt::Horizontal == _slider->orientation()) { 298 | painter.translate(_slider->x() + QT_MATERIAL_SLIDER_MARGIN, 299 | _slider->y() + _slider->height() / 2 300 | - static_cast(_trackWidth) / 2); 301 | } else { 302 | painter.translate(_slider->x() + _slider->width() / 2 303 | - static_cast(_trackWidth) / 2, 304 | _slider->y() + QT_MATERIAL_SLIDER_MARGIN); 305 | } 306 | 307 | QRectF geometry = Qt::Horizontal == _slider->orientation() 308 | ? QRectF(0, 0, _slider->width() - QT_MATERIAL_SLIDER_MARGIN * 2, _trackWidth) 309 | : QRectF(0, 0, _trackWidth, _slider->height() - QT_MATERIAL_SLIDER_MARGIN * 2); 310 | 311 | QRectF bgRect; 312 | QRectF fgRect; 313 | 314 | if (Qt::Horizontal == _slider->orientation()) { 315 | fgRect = QRectF(0, 0, offset, _trackWidth); 316 | bgRect = QRectF(offset, 0, _slider->width(), _trackWidth).intersected(geometry); 317 | } else { 318 | fgRect = QRectF(0, 0, _trackWidth, offset); 319 | bgRect = QRectF(0, offset, _trackWidth, _slider->height()).intersected(geometry); 320 | } 321 | 322 | if (!_slider->isEnabled()) { 323 | fgRect = fgRect.width() < 9 ? QRectF() : fgRect.adjusted(0, 0, -6, 0); 324 | bgRect = bgRect.width() < 9 ? QRectF() : bgRect.adjusted(6, 0, 0, 0); 325 | } 326 | 327 | if (_slider->invertedAppearance()) { 328 | qSwap(bgRect, fgRect); 329 | } 330 | 331 | painter.fillRect(bgRect, bg); 332 | painter.fillRect(fgRect, fg); 333 | } 334 | 335 | // Slider 336 | Slider::Slider(QWidget* parent) 337 | : QAbstractSlider(parent) 338 | , _thumbColor(0x409eff) 339 | , _trackColor(0xe4e7ed) 340 | , _disabledColor(0xc0c4cc) 341 | { 342 | init(); 343 | } 344 | 345 | void Slider::setThumbColor(const QColor& color) 346 | { 347 | _thumbColor = color; 348 | update(); 349 | } 350 | 351 | QColor Slider::thumbColor() const 352 | { 353 | return _thumbColor; 354 | } 355 | 356 | void Slider::setTrackColor(const QColor& color) 357 | { 358 | _trackColor = color; 359 | update(); 360 | } 361 | 362 | void Slider::setDisabledColor(const QColor& color) 363 | { 364 | _disabledColor = color; 365 | update(); 366 | } 367 | 368 | QColor Slider::disabledColor() const 369 | { 370 | return _disabledColor; 371 | } 372 | 373 | void Slider::setPageStepMode(bool pageStep) 374 | { 375 | _pageStepMode = pageStep; 376 | } 377 | 378 | bool Slider::pageStepMode() const 379 | { 380 | return _pageStepMode; 381 | } 382 | 383 | QSize Slider::minimumSizeHint() const 384 | { 385 | return Qt::Horizontal == orientation() 386 | ? QSize(130, 34) 387 | : QSize(34, 130); 388 | } 389 | 390 | void Slider::setInvertedAppearance(bool value) 391 | { 392 | QAbstractSlider::setInvertedAppearance(value); 393 | 394 | updateThumbOffset(); 395 | } 396 | 397 | void Slider::sliderChange(SliderChange change) 398 | { 399 | if (SliderOrientationChange == change) { 400 | QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed); 401 | if (orientation() == Qt::Vertical) { 402 | sp.transpose(); 403 | } 404 | setSizePolicy(sp); 405 | } else if (SliderValueChange == change) { 406 | if (minimum() == value()) { 407 | triggerAction(SliderToMinimum); 408 | // d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderChangedToMinimum)); 409 | } else if (maximum() == value()) { 410 | triggerAction(SliderToMaximum); 411 | } 412 | if (minimum() == _oldValue) { 413 | // d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderChangedFromMinimum)); 414 | } 415 | _oldValue = value(); 416 | } 417 | 418 | updateThumbOffset(); 419 | 420 | QAbstractSlider::sliderChange(change); 421 | } 422 | 423 | void Slider::mouseMoveEvent(QMouseEvent* event) 424 | { 425 | if (isSliderDown()) { 426 | setSliderPosition(valueFromPosition(event->pos())); 427 | } else { 428 | QRectF track(trackBoundingRect().adjusted(-2, -2, 2, 2)); 429 | 430 | if (track.contains(event->pos()) != _hoverTrack) { 431 | _hoverTrack = !_hoverTrack; 432 | update(); 433 | } 434 | 435 | QRectF thumb(0, 0, 16, 16); 436 | thumb.moveCenter(thumbBoundingRect().center()); 437 | 438 | if (thumb.contains(event->pos()) != _hoverThumb) { 439 | _hoverThumb = !_hoverThumb; 440 | // QPoint point = mapToGlobal(event->pos()); 441 | // QToolTip::showText(point, QString::number(value())); 442 | update(); 443 | } 444 | 445 | setHovered(_hoverTrack || _hoverThumb); 446 | } 447 | 448 | QAbstractSlider::mouseMoveEvent(event); 449 | } 450 | 451 | void Slider::mousePressEvent(QMouseEvent* event) 452 | { 453 | const QPoint pos = event->pos(); 454 | 455 | QRectF thumb(0, 0, 16, 16); 456 | thumb.moveCenter(thumbBoundingRect().center()); 457 | 458 | if (thumb.contains(pos)) { 459 | setSliderDown(true); 460 | return; 461 | } 462 | 463 | if (!_pageStepMode) { 464 | setSliderPosition(valueFromPosition(event->pos())); 465 | _thumb->setHaloSize(0); 466 | setSliderDown(true); 467 | return; 468 | } 469 | 470 | _step = true; 471 | _stepTo = valueFromPosition(pos); 472 | 473 | SliderAction action = _stepTo > sliderPosition() 474 | ? SliderPageStepAdd 475 | : SliderPageStepSub; 476 | 477 | triggerAction(action); 478 | setRepeatAction(action, 400, 8); 479 | } 480 | 481 | void Slider::mouseReleaseEvent(QMouseEvent* event) 482 | { 483 | if (isSliderDown()) { 484 | setSliderDown(false); 485 | } else if (_step) { 486 | _step = false; 487 | setRepeatAction(SliderNoAction, 0); 488 | } 489 | 490 | QAbstractSlider::mouseReleaseEvent(event); 491 | } 492 | 493 | void Slider::leaveEvent(QEvent* event) 494 | { 495 | if (_hoverTrack) { 496 | _hoverTrack = false; 497 | update(); 498 | } 499 | if (_hoverThumb) { 500 | _hoverThumb = false; 501 | update(); 502 | } 503 | 504 | setHovered(false); 505 | 506 | QAbstractSlider::leaveEvent(event); 507 | } 508 | 509 | void Slider::updateThumbOffset() 510 | { 511 | const int offset = QCommonStyle::sliderPositionFromValue( 512 | minimum(), 513 | maximum(), 514 | sliderPosition(), 515 | Qt::Horizontal == orientation() 516 | ? width() - QT_MATERIAL_SLIDER_MARGIN * 2 517 | : height() - QT_MATERIAL_SLIDER_MARGIN * 2, 518 | invertedAppearance()); 519 | 520 | _thumb->setOffset(offset); 521 | } 522 | 523 | void Slider::init() 524 | { 525 | _thumb = new SliderThumb(this); 526 | _track = new SliderTrack(_thumb, this); 527 | _stepTo = 0; 528 | _oldValue = value(); 529 | _trackWidth = 6; 530 | _track->setTrackWidth(_trackWidth); 531 | 532 | _hoverTrack = false; 533 | _hoverThumb = false; 534 | _hover = false; 535 | _step = false; 536 | _pageStepMode = true; 537 | 538 | setMouseTracking(true); 539 | setFocusPolicy(Qt::StrongFocus); 540 | setPageStep(1); 541 | 542 | setCursor(Qt::PointingHandCursor); 543 | 544 | QSizePolicy sp(QSizePolicy::Expanding, 545 | QSizePolicy::Fixed); 546 | if (orientation() == Qt::Vertical) { 547 | sp.transpose(); 548 | } 549 | 550 | setSizePolicy(sp); 551 | setAttribute(Qt::WA_WState_OwnSizePolicy, false); 552 | 553 | _track->setFillColor(_trackColor); 554 | QColor holeColor = palette().color(QPalette::Base); 555 | if (parentWidget()) { 556 | holeColor = parentWidget()->palette().color(backgroundRole()); 557 | } 558 | _thumb->setFillColor(holeColor); 559 | _thumb->setHaloColor(_trackColor); 560 | _thumb->setBorderColor(_thumbColor); 561 | } 562 | 563 | QRectF Slider::trackBoundingRect() const 564 | { 565 | qreal hw = static_cast(_trackWidth) / 2; 566 | 567 | return Qt::Horizontal == orientation() 568 | ? QRectF(QT_MATERIAL_SLIDER_MARGIN, height() / 2 - hw, 569 | width() - QT_MATERIAL_SLIDER_MARGIN * 2, hw * 2) 570 | : QRectF(width() / 2 - hw, QT_MATERIAL_SLIDER_MARGIN, hw * 2, 571 | height() - QT_MATERIAL_SLIDER_MARGIN * 2); 572 | } 573 | 574 | QRectF Slider::thumbBoundingRect() const 575 | { 576 | return Qt::Horizontal == orientation() 577 | ? QRectF(_thumb->offset(), height() / 2 - QT_MATERIAL_SLIDER_MARGIN, 578 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2) 579 | : QRectF(width() / 2 - QT_MATERIAL_SLIDER_MARGIN, _thumb->offset(), 580 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2); 581 | } 582 | 583 | int Slider::valueFromPosition(const QPoint& pos) const 584 | { 585 | const int position = Qt::Horizontal == orientation() ? pos.x() : pos.y(); 586 | 587 | const int span = Qt::Horizontal == orientation() 588 | ? width() - QT_MATERIAL_SLIDER_MARGIN * 2 589 | : height() - QT_MATERIAL_SLIDER_MARGIN * 2; 590 | 591 | return QCommonStyle::sliderValueFromPosition( 592 | minimum(), 593 | maximum(), 594 | position - QT_MATERIAL_SLIDER_MARGIN, 595 | span, 596 | invertedAppearance()); 597 | } 598 | 599 | void Slider::setHovered(bool status) 600 | { 601 | if (_hover == status) { 602 | return; 603 | } 604 | _hover = status; 605 | update(); 606 | } 607 | 608 | EL_END_NAMESPACE 609 | --------------------------------------------------------------------------------