QT实战-常见功能实现-精进篇

Qt版本:5.9.1

-----
0.如何设置所有按钮全局统一样式,如soui那样的?
如取消所有按钮默认样式
[
//全局设置,取消按钮默认样式
    this->setStyleSheet("QPushButton \
                        {\
                        border: none;\
                        background-color: transparent;\
                        outline: none;\
                         }");
]

该设置对该窗口上所有PushButton都会生效

具体:
整体程序:qApp->setStyleSheet("QLineEdit { background-color: yellow }");
对话框:myDialog->setStyleSheet("QLineEdit { background-color: yellow }");
具体控件:nameEdit->setStyleSheet("background-color: yellow");

参考代码:https://doc.qt.io/qt-5/stylesheet-examples.html

---
1.按钮上支持4态图片

样式内容:
[
QPushButton
{
background-image: url(:/image/res/btn_openaccount_normal.png);
}
QPushButton:hover
{
background-image: url(:/image/res/btn_openaccount_over.png);
}

QPushButton:pressed
{
background-image: url(:/image/res/btn_openaccount_down.png);
}
QPushButton:disabled
{
background-image: url(:/image/res/btn_openaccount_normal.png);
}

border: none;
background-color: transparent;
outline: none;  
]

对应代码:
[
mypushButton->setStyleSheet(QLatin1String("\n"
"QPushButton\n"
"{\n"
"background-image: url(:/image/res/btn_openaccount_normal.png);\n"
"}\n"
"QPushButton:hover\n"
"{\n"
"background-image: url(:/image/res/btn_openaccount_over.png);\n"
"}\n"
"\n"
"QPushButton:pressed\n"
"{\n"
"background-image: url(:/image/res/btn_openaccount_down.png);\n"
"}\n"
"QPushButton:disabled\n"
"{\n"
"background-image: url(:/image/res/btn_openaccount_normal.png);\n"
"}\n"
"\n"
"border: none;\n"
"background-color: transparent;\n"
"outline: none;   "));
]
(通过界面设置stylesheet后自动生成的代码)


后边3个缺一不可,必须都有

原因:qt按钮默认具有一些状态,导致设置了图像后,仍然存在边框,按下时边框等问题,
所以需要取消按钮默认效果,才能保证按钮效果

---
说明:QIcon不能实现按钮的4态功能
[
QString strPng[4]=
    {
        ":/image/res/btn_openaccount_normal.png",
        ":/image/res/btn_openaccount_over.png",
        ":/image/res/btn_openaccount_down.png",
        ":/image/res/btn_openaccount_normal.png",
    };

    QPixmap pix[4];
    for(int i=0; i< 4; i++)
    {
        pix[i].load(strPng[i]);
    }

    QIcon icon;
    icon.addPixmap(pix[0], QIcon::Normal);
    icon.addPixmap(pix[1], QIcon::Active);
    icon.addPixmap(pix[3], QIcon::Selected);
    icon.addPixmap(pix[3], QIcon::Disabled);

    ui->mypushButton->setIcon(icon);
    ui->mypushButton->setIconSize(pix[0].size());
]

此代码没有用,
QIcon::Normal         --是失去焦点时的状态
QIcon::Active           --得到焦点时的状态
QIcon::Selected       --选中,但是这里没效果
QIcon::Disabled       --这个有效

是没有hover这种状态的
而且4种状态,又分为On,Off,相当于checkbox的打开,关闭,目前不知道怎么用

只要明白QIcon不能实现按钮的4态功能就可以了

---
2.checkbox

理论上说是8态,即没有选中时的4态,和选中后的4态

样式内容:
[
QCheckBox::indicator:unchecked {
    image: url(:/image/res/check.png);
}

QCheckBox::indicator:unchecked:hover {
    image: url(:/image/res/checkbox_hover.png);
}

QCheckBox::indicator:unchecked:pressed {
    image: url(:/image/res/checkbox_press.png);
}

QCheckBox::indicator:unchecked:disabled {
    image: url(:/image/res/checkbox_press.png);
}

QCheckBox::indicator:checked {
    image: url(:/image/res/checkbox_sel.png);
}

QCheckBox::indicator:checked:hover {
    image: url(:/image/res/checkbox_sel_hover.png);
}

QCheckBox::indicator:checked:pressed {
    image: url(:/image/res/checkbox_sel_press.png);
}

QCheckBox::indicator:checked:disabled {
    image: url(:/image/res/checkbox_sel_press.png);
}

网址:https://doc.qt.io/qt-5/stylesheet-examples.html
]

自动生成代码:
[
        checkBox->setStyleSheet(QLatin1String("\n"
"QCheckBox::indicator:unchecked {\n"
"    image: url(:/image/res/check.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:unchecked:hover {\n"
"    image: url(:/image/res/checkbox_hover.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:unchecked:pressed {\n"
"    image: url(:/image/res/checkbox_press.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:unchecked:disabled {\n"
"    image: url(:/image/res/checkbox_press.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:checked {\n"
"    image: url(:/image/res/checkbox_sel.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:checked:hover {\n"
"    image: url(:/image/res/checkbox_sel_hover.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:checked:pressed {\n"
"    image: url(:/image/res/checkbox_sel_press.png);\n"
"}\n"
"\n"
"QCheckBox::indicator:checked:disabled {\n"
"    image: url(:/image/res/checkbox_sel_press.png);\n"
"}"));
]

---
3.RadioButton

8态,即没有选中时的4态,和选中后的4态

样式内容:
[
QRadioButton::indicator::unchecked {
    image: url(:/image/res/radio_normal.png);
}

QRadioButton::indicator:unchecked:hover {
    image: url(:/image/res/radio_hover.png);
}

QRadioButton::indicator:unchecked:pressed {
    image: url(:/image/res/radio_press.png);
}

QRadioButton::indicator::checked {
    image: url(:/image/res/radio_select_normal.png);
}

QRadioButton::indicator:checked:hover {
    image: url(:/image/res/radio_select_hover.png);
}

QRadioButton::indicator:checked:pressed {
    image: url(:/image/res/radio_select_press.png);
}
]

自动生成代码:
[
radioButton->setStyleSheet(QLatin1String("QRadioButton::indicator::unchecked {\n"
"    image: url(:/image/res/radio_normal.png);\n"
"}\n"
"\n"
"QRadioButton::indicator:unchecked:hover {\n"
"    image: url(:/image/res/radio_hover.png);\n"
"}\n"
"\n"
"QRadioButton::indicator:unchecked:pressed {\n"
"    image: url(:/image/res/radio_press.png);\n"
"}\n"
"\n"
"QRadioButton::indicator::checked {\n"
"    image: url(:/image/res/radio_select_normal.png);\n"
"}\n"
"\n"
"QRadioButton::indicator:checked:hover {\n"
"    image: url(:/image/res/radio_select_hover.png);\n"
"}\n"
"\n"
"QRadioButton::indicator:checked:pressed {\n"
"    image: url(:/image/res/radio_select_press.png);\n"
"}"));
]

这里没加禁用的,如果加就是
[
"QRadioButton::indicator:unchecked:disabled {\n"
"    image: url(:/image/res/radio_press.png);\n"
"}"));

"QRadioButton::indicator:checked:disabled {\n"
"    image: url(:/image/res/radio_select_sel_press.png);\n"
"}"));
]

---
4.如何添加一个小图标作为logo显示?或者一个大图片作为背景?
使用QLabel就可以
QLabel支持pixmap属性,而pixmap可以用ico,png等图片,所以QLabel可以用ico,png等图片

添加一个小图标:界面选择一个ico图片即可
添加一个大图片作为背景:界面选择一个png图片即可

自动生成代码:
[
小图标:
label->setPixmap(QPixmap(QString::fromUtf8(":/image/res/Main.ico")));

大图片:
label_2->setPixmap(QPixmap(QString::fromUtf8(":/image/res/big_pic.png")));
]

---
5.Edit
(1)QT中LineEdit、TextEdit 、PlainTextEdit 三个控件的区别:
QLineEdit是单行文本输入,一般用于用户名、密码等少量文本交互地方。
QTextEdit用于多行文本,也可以显示HTML格式文本。QTextEdit多用于显示
QPlainTextEdit与QTextEdit很像,但它多用于需要与文本进行处理的地方,而QTextEdit多用于显示,
可以说,QPlainTextEdit对于plain text处理能力比TextEdit强。(比如文本编辑器就用Qplain Text Edit)

-
(2)
样式1:正常、掠过、获得焦点边框变化
[
样式实现:
QLineEdit {
    border: 2px solid gray;
}

QLineEdit:hover {
    border: 2px solid blue;
}

QLineEdit:focus {
    border: 2px solid blue;
}

---
自动生成代码:
lineEdit->setStyleSheet(QLatin1String("QLineEdit {\n"
"    border: 2px solid gray;\n"
"}\n"
"\n"
"QLineEdit:hover {\n"
"    border: 2px solid blue;\n"
"}\n"
"\n"
"QLineEdit:focus {\n"
"    border: 2px solid blue;\n"
"}"));

]

样式2:圆角编辑框
[
样式实现:
QLineEdit {
    border: 2px solid rgb(7,7,7);
    border-radius: 10px;
    padding: 0 8px;
    background: yellow;
    selection-background-color: darkgray;
}

QLineEdit:hover {
    border: 2px solid rgb(0,255,0);
}

QLineEdit:focus {
    border: 2px solid rgb(0,255,0);
}

---
自动生成代码:
lineEdit_2->setStyleSheet(QLatin1String("QLineEdit {\n"
"    border: 2px solid rgb(7,7,7);\n"
"    border-radius: 10px;\n"
"    padding: 0 8px;\n"
"    background: yellow;\n"
"    selection-background-color: darkgray;\n"
"}\n"
"\n"
"QLineEdit:hover {\n"
"    border: 2px solid rgb(0,255,0);\n"
"}\n"
"\n"
"QLineEdit:focus {\n"
"    border: 2px solid rgb(0,255,0);\n"
"}"));
]

---
6.combobox

设置边框:
[
QComboBox {
    border: 1px solid gray;
}

QComboBox:hover {
    border: 1px solid blue;
}

QComboBox:pressed {
    border: 1px solid blue;
}

]

设置右边箭头:
[
/*样式*/
QComboBox::drop-down {
    width: 25px;/*下拉按钮宽度*/

    border-left-width: 1px;  /*箭头的左边竖线*/
    border-left-color: darkgray;
    border-left-style: solid; /* just a single line */
}

QComboBox::drop-down:hover {
    border-left-color: blue;
}

QComboBox::drop-down:pressed {
    border-left-color: blue;
}

---
/*下拉箭头图片*/
QComboBox::down-arrow {
    image: url(:/image/res/btn_dropdown_normal.png);
}

QComboBox::down-arrow:hover {
    image: url(:/image/res/btn_dropdown_over.png);
}

QComboBox::down-arrow::pressed{
    image: url(:/image/res/btn_dropdown_active.png);
}

]

设置下拉展开的item样式:
[
QComboBox QAbstractItemView {
    border: 1px solid blue;
    selection-background-color: lightgray;
}
]

自动生成代码:
[
comboBox->setStyleSheet(QLatin1String("\n"
"QComboBox {\n"
"    border: 1px solid gray;\n"
"}\n"
"\n"
"QComboBox:hover {\n"
"    border: 1px solid blue;\n"
"}\n"
"\n"
"QComboBox:pressed {\n"
"    border: 1px solid blue;\n"
"}\n"
"\n"
"QComboBox::drop-down {\n"
"    width: 25px;\n"
"\n"
"    border-left-width: 1px;\n"
"    border-left-color: darkgray;\n"
"    border-left-style: solid; /* just a single line */\n"
"}\n"
"\n"
"QComboBox::drop-down:hover {\n"
"    border-left-color: blue;\n"
"}\n"
"\n"
"QComboBox::drop-down:pressed {\n"
"    border-left-color: blue;\n"
"}\n"
"\n"
"QComboBox::down-arrow {\n"
"    image: url(:/image/res/btn_dropdown_normal.png);\n"
"}\n"
"\n"
"QComboBox::down-arrow:hover {\n"
"    image: url(:/image/res/btn_dropdown_over.png);\n"
"}\n"
"\n"
"QComboBox::down-arrow::pressed{\n"
"    image: url(:/image/res/btn_dropdown_active.png);\n"
"}\n"
"\n"
"QComboBox QAbstractItemView {\n"
"    border: 1px solid blue;\n"
"    selection-background-color: lightgray;\n"
"}"));
]

---
7.进度条

样式1:设置背景图片和前景图片
[
QProgressBar {
    text-align: center;
    border-image: url(:/image/res/progress_back.png);
    
}

QProgressBar::chunk {
    margin:1;
    border-image: url(:/image/res/progress_fore.png);
}

说明:
(1)imge和bakcground-image设置了都没用,必须是border-image
(2)另外chunk必须设置margin,否则与背景重合了

]

样式2:圆角边框
[
QProgressBar {
    border: 2px solid grey;
    border-radius: 5px;
    text-align: center;
}

QProgressBar::chunk {
    background-color: #05B8CC;
}
]

样式3:进度按格显示
[
QProgressBar {
    text-align: center;
}

QProgressBar::chunk {
    background-color: #CD96CD;
    width: 10px;
    margin: 0.5px;
}

说明:按格显示时,要设置chunk宽度,相当于一个格的宽度,然后margin设置一下
平常chunk也是有宽度的,只不过很小(如0.01),margin为0,然后,一个挨着一个,
就相当于一个整体了
]

---
8.滑块

样式1:设置背景图和滑块图
[
QSlider::groove:horizontal {
    border-image: url(:/image/res/slider_bg.png);
    margin: 2px 0;
}

QSlider::handle:horizontal {
    width: 13px;
    height: 13px;
    margin: -2px 0; 
    border-image: url(:/image/res/slider_thumb.png);
}

说明:
(1)groove是凹槽,handle是滑块,horizontal是水平的
(2)要设置border-image,image和background-image都不行
(3)各个margin要设置,保持凹槽和滑块位置一致
]

样式2:圆角滑块
[
QSlider::groove:horizontal {
    border: 1px solid #999999;
    height: 8px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);
    margin: 2px 0;
}

QSlider::handle:horizontal {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f);
    border: 1px solid #5c5c5c;
    width: 18px;
    margin: -2px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
    border-radius: 3px;
}
]

样式3:滑块滑上颜色和滑回颜色(add-page与sub-page)
[
QSlider::groove:vertical {
    background: red;
    position: absolute; /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */
    left: 4px; right: 4px;
}

QSlider::handle:vertical {
    height: 10px;
    background: green;
    margin: 0 -4px; /* expand outside the groove */
}

QSlider::add-page:vertical {
    background: white;
}

QSlider::sub-page:vertical {
    background: pink;
}
]

---
9.线

样式:
水平线:
设置高为1,设置背景色为
background-color: rgb(85, 170, 0);

说明:color,border-color都没有用,只有background-color有用

---
10.spinBox

可以被完全定制:https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qspinbox

样式:
[
QSpinBox {
    padding-right: 11px; /* make room for the arrows */
    border: 1px solid gray;
    border-width: 1;
}

QSpinBox::up-button {
    subcontrol-origin: border;
    subcontrol-position: top right; /* position at the top right corner */

    width: 10px; /* 16 + 2*1px border-width = 15px padding + 3px parent border */
    border-image: url(:/image/res/spinbox_up.png) 1;
    border-width: 1px;
    margin-top: 1;
    margin-right: 1;
}

QSpinBox::up-button:hover {
    border-image: url(:/image/res/spinbox_up_hover.png) 1;
}

QSpinBox::up-button:pressed {
    border-image: url(:/image/res/spinbox_up_sel.png) 1;
}

QSpinBox::up-arrow {
    image: url(:/image/res/spinbox_up_arrow.png);
    width: 7px;
    height: 7px;
}


QSpinBox::up-arrow:disabled, QSpinBox::up-arrow:off { /* off state when value is max */
   image: url(:/image/res/spinbox_up_arrow.png);
}

QSpinBox::down-button {
    subcontrol-origin: border;
    subcontrol-position: bottom right; /* position at bottom right corner */

    width: 10px;
    border-image: url(:/image/res/spinbox_down.png) 1;
    border-width: 1px;
    border-top-width: 0;
    margin-bottom: 1;
    margin-right: 1;
}

QSpinBox::down-button:hover {
    border-image: url(:/image/res/spinbox_down_hover.png) 1;
}

QSpinBox::down-button:pressed {
    border-image: url(:/image/res/spinbox_down_sel.png) 1;
}

QSpinBox::down-arrow {
    image: url(:/image/res/spinbox_down_arrow.png);
    width: 7px;
    height: 7px;
}

QSpinBox::down-arrow:disabled,
QSpinBox::down-arrow:off { /* off state when value in min */
   image: url(:/image/res/spinbox_down_arrow.png);
}

说明:
QSpinBox::up-button            --设置向上按钮的边框
QSpinBox::up-arrow              ---设置向上按钮的里面的小图

QSpinBox::down-button       --设置向下按钮的边框
QSpinBox::down-arrow         ---设置向下按钮的里面的小图
]

---
11.滚动条

水平滚动条:
[
样式:

QScrollBar:horizontal {
    border: 2px solid grey;
    background: #32CC99;
    height: 15px;
    margin: 0px 20px 0 20px;
}
QScrollBar::handle:horizontal {
    background: white;
    min-width: 20px;
}
QScrollBar::add-line:horizontal {
    border: 2px solid grey;
    background: #32CC99;
    width: 20px;
    subcontrol-position: right;
    subcontrol-origin: margin;
}

QScrollBar::sub-line:horizontal {
    border: 2px solid grey;
    background: #32CC99;
    width: 20px;
    subcontrol-position: left;
    subcontrol-origin: margin;
}

QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal {
    width: 3px;
    height: 3px;
    background: pink;
}

QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
    background: none;
}

说明:
QScrollBar::handle:horizontal           --水平滚动条,水平拖动的滑块
QScrollBar::add-line:horizontal         --水平滚动条,增加的按钮的边框
QScrollBar::sub-line:horizontal         --水平滚动条,减小的按钮的边框
QScrollBar:left-arrow:horizontal,    --水平滚动条,增加的按钮里面的左箭头
QScrollBar::right-arrow:horizontal    --水平滚动条,减小的按钮里面的右箭头
QScrollBar::add-page:horizontal,       --水平滚动条,点击的增加的部分的空白处
QScrollBar::sub-page:horizontal        --水平滚动条,点击的减小的部分的空白处

设置图片的情况,可以参考其他控件,这里没有单独的图片,就不弄了,猜也能猜个一二

]

竖直滚动条:
[
QScrollBar:vertical {
     border: 2px solid grey;
     background: #32CC99;
     width: 15px;
     margin: 22px 0 22px 0;
 }
 QScrollBar::handle:vertical {
     background: white;
     min-height: 20px;
 }
 QScrollBar::add-line:vertical {
     border: 2px solid grey;
     background: #32CC99;
     height: 20px;
     subcontrol-position: bottom;
     subcontrol-origin: margin;
 }

 QScrollBar::sub-line:vertical {
     border: 2px solid grey;
     background: #32CC99;
     height: 20px;
     subcontrol-position: top;
     subcontrol-origin: margin;
 }
 QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
     border: 2px solid grey;
     width: 3px;
     height: 3px;
     background: white;
 }

 QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
     background: none;
 }
]


---
12.QListView(官网没有QListWidget,只有QListView)

添加内容代码:
[
//ListView
    m_pListModel=new QStringListModel(this); //创建数据模型
    ui->listView1->setModel(m_pListModel); //为listView设置数据模型
    ui->listView1->setEditTriggers(QAbstractItemView::NoEditTriggers);

    QStringList theStrList; //保存初始 StringList
    theStrList<<"北京"<<"上海"<<"天津"<<"河北"<<"山东"<<"四川"<<"重庆"<<"广东"<<"河南"; //初始化 StringList
    m_pListModel->setStringList(theStrList); //为模型设置StringList,会导入StringList的内容
]

样式(带滚动条设置):
[
QListView {
    border: 1px solid grey;
    background: #32CC99;
    show-decoration-selected: 1; /* make the selection span the entire width of the view */
}

QListView::item:alternate {
    background: yellow;
}


QListView::item:selected {
    border: 2px solid blue;
}

QListView::item:selected:!active {
    background: blue;
}

QListView::item:selected:active {
    background: red;
}

QListView::item:hover {
    background: pink;
}

/*滚动条*/
QScrollBar:vertical {
     border-left: 1px solid grey;
     border-right: none;
     border-top: none;
     border-bottom: none;
     background: lightblue;
     width: 20px;
     margin: 20px 0 20px 0;
 }
 QScrollBar::handle:vertical {
     background: red;
     min-height: 20px;
     margin: 0px 0 0px 0;
 }

 QScrollBar::add-line:vertical {
     border-left: 1px solid grey;
     border-right: none;
     border-top: 1px solid grey;
     border-bottom: none;
     background: #32CC99;
     height: 20px;
     subcontrol-position: bottom;
     subcontrol-origin: margin;
 }

 QScrollBar::sub-line:vertical {
     border-left: 1px solid grey;
     border-top: none;
     border-right: none;
     border-bottom: 1px solid grey;
     background: #32CC99;
     height: 20px;
     subcontrol-position: top;
     subcontrol-origin: margin;
 }
 QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
     border: 1px solid grey;
     width: 3px;
     height: 3px;
     background: white;
 }

 QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
     background: none;
 }

说明:
(1)QListView用于单行显示,没有头部

属性viewMode分为ListMode和IconMode

ListMode     --就是单行显示
IconMode   --就是类似表格那种平铺显示

(2)QListView::item:alternate,交替色要勾选属性AlternatingRowColors启用才行,代码是listView1->setAlternatingRowColors(true);
(3)QListView的滚动条,直接用滚动条的属性就行

]

---
13.QTreeView(带表头和滚动条设置)

样式:
[
/*表头*/
QHeaderView::section{
    height: 25px;
    border: 1px solid #d9d9d9;
    border-left-color: transparent;
    background-color: green;
}

/*TreeView*/
QTreeView {
    border: 1px solid grey;
    background: pink;
    show-decoration-selected: 1;
    alternate-background-color: yellow;
}

QTreeView::item {
    border: 1px solid #d9d9d9;
    border-left-color: transparent;
    border-top-color: transparent;
    border-bottom-color: transparent;
}

QTreeView::item:hover {
    background: lightblue;
    border: 1px solid #bfcde4;
    border-left-color: transparent;
}

QTreeView::item:selected {
    border: 1px solid #567dbc;
    border-left-color: transparent;
}

QTreeView::item:selected:active{
    background: blue;
}

QTreeView::item:selected:!active {
    background: red;
}

/* branch-连接线,展开,合并 */
QTreeView::branch:has-siblings:!adjoins-item {
    border-image: url(:/image/res/branch_vline.png) 0;
}

QTreeView::branch:has-siblings:adjoins-item {
    border-image: url(:/image/res/branch_more.png) 0;
}

QTreeView::branch:!has-children:!has-siblings:adjoins-item {
    border-image: url(:/image/res/branch_end.png) 0;
}

QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
        border-image: none;
        image: url(:/image/res/branch_closed.png);
}

QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings  {
        border-image: none;
        image: url(:/image/res/branch_open.png);
}

/*竖直滚动条*/
QScrollBar:vertical {
     border-left: 1px solid grey;
     border-right: none;
     border-top: none;
     border-bottom: none;
     background: lightblue;
     width: 20px;
     margin: 20px 0 20px 0;
 }
 QScrollBar::handle:vertical {
     background: red;
     min-height: 20px;
     margin: 0px 0 0px 0;
 }

 QScrollBar::add-line:vertical {
     border-left: 1px solid grey;
     border-right: none;
     border-top: 1px solid grey;
     border-bottom: none;
     background: #32CC99;
     height: 20px;
     subcontrol-position: bottom;
     subcontrol-origin: margin;
 }

 QScrollBar::sub-line:vertical {
     border-left: 1px solid grey;
     border-top: none;
     border-right: none;
     border-bottom: 1px solid grey;
     background: #32CC99;
     height: 20px;
     subcontrol-position: top;
     subcontrol-origin: margin;
 }
 QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
     border: 1px solid grey;
     width: 3px;
     height: 3px;
     background: white;
 }

 QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
     background: none;
 }

/*水平滚动条*/
QScrollBar:horizontal {
     border-left: none;
     border-right: none;
     border-top: 1px solid grey;;
     border-bottom: none;
     background: lightblue;
     height: 20px;
     margin: 0px 20px 0px 20px;
 }
 QScrollBar::handle:horizontal {
     background: red;
     min-width: 20px;
     margin: 0px 0 0px 0;
 }

 QScrollBar::add-line:horizontal {
     border-left: 1px solid grey;
     border-right: none;
     border-top: 1px solid grey;
     border-bottom: none;
     background: #32CC99;
     width: 20px;
     subcontrol-position: right;
     subcontrol-origin: margin;
 }

 QScrollBar::sub-line:horizontal {
     border-left: none;
     border-top: 1px solid grey;
     border-right: 1px solid grey;
     border-bottom: none;
     background: #32CC99;
     width: 20px;
     subcontrol-position: left;
     subcontrol-origin: margin;
 }
 QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal {
     border: 1px solid grey;
     width: 3px;
     height: 3px;
     background: white;
 }

 QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
     background: none;
 }


说明:
(1)QTreeView包含“表头+treeview+水平滚动条+竖直滚动条”,背景要把表头和treeview都设置才行
(2)表头设置直接参考官网QHeaderView设置
(3)交替色要勾选属性AlternatingRowColors启用才行,代码是treeView1->setAlternatingRowColors(true);
(4)注意表头的section与tree的item是指其中的一个小的单元格,默认的显示效果中间的线是一行中的两个单元格各自占的,
所以看起来变粗了1px一样,这里可以把表头和tree的item的边框左边界线都设置为透明,只留下右边界,这样就只有一条线了,
看起来就不会那么粗了

设置方法就是把表头的QHeaderView::section和QTreeView::item都设置成下面这样:
border: 1px solid #d9d9d9;
border-left-color: transparent;

当然也可以"border-left:none",效果跟上面一样

(5)QTreeView::item的矩形边框,上下线设置成透明,这样上下线也就不会那么粗了
QTreeView::item {
    border: 1px solid #d9d9d9;
    border-top-color: transparent;
    border-bottom-color: transparent;
}

(6)tree的定制:
状态       --没展开和展开状态,各一个图片
branch   --节点间的连接线,各个节点间连接是一个小矩形区域,可以设置图片,看官网上展示效果图片,看第一节点,包括开始,中间,结尾3种,      
                需要3个图片

has-siblings        --兄弟姐妹
has-children       --孩子节点
adjoins-item       --理解为连接节点的小横线,方便理解

提供的图故意把最后一个图线不对齐,目的是便于理解
至于图上的白色,因为图不是透明的(不会ps用电脑自带画图工具把透明度弄没了导致的)

(7)水平滚动条,竖直滚动条,同样里面的两头按钮边框和中间边框都是距离外面1px,这里把不需要边框设置成透明即不显示,
目的是看起来合理一些,不那么刺眼

(8)滚动条的margin是按照"上下右左"顺序的(为什么不是左上右下呢,不理解)

]

---
14.TabWidget

样式:
[
QTabWidget::pane {
    border: 1px solid #C2C7CB;
    background: pink;
}

QTabBar::tab {
    background: lightblue;
    border: 1px solid #C4C4C3;
    border-bottom-color: transparent;
    min-width: 8ex;
    padding: 2px;
}

QTabBar::tab:hover {
    background: pink;
}

QTabBar::tab:selected {
    background: pink;
   /* border-bottom-color: pink;*/
    position: absolute;
    bottom: -2px;
}

QTabBar::tab:!selected {
    margin-top: 2px; 
}

QTabBar::tab:first {
    margin-left: 0; 
    margin-right: -1px;
}

QTabBar::tab:last {
    margin-left: -1; 
    margin-right: 0; 
}

QTabBar::tab:middle: {
    margin-left: -1; 
    margin-right: -1; 
}

说明:
(1)tab控件包括tabbar(上面整体)、pane(下面整体),tabbar里面的tab是针对具体的一个tab设置
(2)tab控件上面的高度不同是通过设置QTabBar::tab:!selected实现的
(3)tab控件分为第一个,中间的,最后的,QTabBar::tab:first,QTabBar::tab:middle,QTabBar::tab:last,
中间存在1px的偏差,可以通过这些单独设置

注意:
tab控件的tabbar下面始终有横线,无法实现与windows的资源管理器那样点击后是没有横线的效果

模拟实现:上面用radiobutton,下面放tab控件(把tab头隐藏掉)
]

---
15.自定义ip地址控件实现

实现1:
[
cmyippartlineedit.h  --CMyIpPartLineEdit
cmyipaddredit.h       --CMyIpAddrEdit

(1)4个Edit和3个Label组成一个,在CMyIpAddrEdit构造函数中创建,在resizeEvent中设置位置
(2)支持连续输入  --在CMyIpPartLineEdit,响应textEdited信号,在text_edited函数中处理实现
BackSpace键     --自己添加的,在keyPressEvent中
左键                  --左键、右键也是在keyPressEvent
右键
(3)设置样式的方式:整个控件包含了4个edit,label不用设置,因此设置样式,需要设置4个edit样式,从而达到
最终的效果
设置边框:setEditStyleSheet   --自己添加的,第一个edit右边边框没有,最后一个edit左边框没有,中间的edit左右
                                                边框都没有,这样就相当于整个边框了
设置背景:同样,在上面设置的时候把各个edit背景加入就好了

注意:
(1)edit自身就支持输入文字自动右移、backspace键、左右键,个人需要处理的是支持可以切换到下一个或前一个edit
(2)设置样式时,新设置的样式会替代原有的样式,所以可以把所有样式都设置上,也可以获取原有样式,再加上自己需要的样式
(3)控件是继承于QWidget的,所以拖动一个Widget到界面上,然后右键选择提升为,新建一个,然后提升就可以用了
参考"Qt自定义控件以及控件的提升"
(4)注意选中一段文字时,backspace要可以删除文字
]

实现2:
[
ipaddrlineedit.h  --IpPartLineEdit,IpAddrLineEdit

(1)4个Edit和3个Label组成一个,在IpAddrLineEdit构造函数中创建,使用的QHBoxLayout组合起来,注意
 mainLayout->setContentsMargins(1, 1, 1, 1);
 mainLayout->setSpacing(0);//必须设置,不然背景会有空隙

(2)支持连续输入  
BackSpace键     
左键                 
右键
 
实现方式:
QLineEdit *m_pNextLineEdit;//下一个edit
QLineEdit *m_pLastEdit;//前一个edit

第一个edit只有下一个edit,中间的两个edit都有,最后一个只有前一个edit,所以切换起来更方便

(3)设置样式的方式:

设置边框:因为 mainLayout->setContentsMargins(1, 1, 1, 1);所以可以直接设置stylesheet
设置背景:这里子控件edit控件与外边边框总是存在间隙,所以设置背景需要把外边的背景和edit、label的背景都设置了
(暂时没想到好的办法)

(4)控件是继承于QFrame的,所以拖动一个QFrame到界面上,然后右键选择提升为,新建一个,然后提升就可以用了

注意:选中一段文字时,backspace要可以删除文字
]

---
16.Gif支持

qt自身支持gif:Label和QMovie就行了
[
//gif
   QMovie *pMovie = new QMovie(":/image/res/loading.gif");
   ui->labelGif->setMovie(pMovie);//labelGif是界面上的Label控件
   pMovie->start();
]

---
17.自定义菜单

样式及使用:
[
void MainWindow::on_btnMenu_clicked()
{
    QMenu* menu= new QMenu();
    menu->addAction("11", this, SLOT(slot_ClickMenu1()));
    menu->addAction("22", this, SLOT(slot_ClickMenu2()));
    menu->addSeparator();
    menu->addAction("33", this, SLOT(slot_ClickMenu3()));

    //样式1  --直角矩形
    /*menu->setStyleSheet("QMenu {margin:0px;border: 1px solid rgb(0,0,0);} \
                        QMenu::item {height:25px;padding: 0px 20px 0px 20px;background-color: grey;} \
                        QMenu::item:selected {background-color: lightblue; } \
                        QMenu::item:pressed {background-color: rgb(255,0,0);}\
                        QMenu::separator {height: 1px;background: rgb(232,188,7);}");
                        */
    //样式2  --圆角矩形
    menu->setStyleSheet("QMenu {margin:0px;border: 1px solid rgb(0,0,0);border-radius: 3px;} \
                        QMenu::item {height:25px;padding: 0px 20px 0px 20px;background-color: grey;} \
                        QMenu::item:selected {background-color: lightblue; } \
                        QMenu::item:pressed {background-color: rgb(255,0,0);}\
                        QMenu::separator {height: 1px;background: rgb(232,188,7);}");


    QRect rcBtn = ui->btnMenu->geometry();
    QPoint pt(rcBtn.left()+rcBtn.width()*0.5, rcBtn.bottom()+rcBtn.height()*0.5);

    pt = mapToGlobal(pt);

    menu->popup(pt);

}

void MainWindow::slot_ClickMenu1()
{
    QMessageBox::information(this, "11", "11");

}

void MainWindow::slot_ClickMenu2()
{
    QMessageBox::information(this, "22", "22");
}

void MainWindow::slot_ClickMenu3()
{
    QMessageBox::information(this, "33", "33");
}

菜单组成:Menu和Action,Menu是整体,Action是里面的具体的item

说明:
QMenu                         --设置边框及整体背景色
QMenu::item                --设置item,padding可以固定位置,保证与外边框无边距
QMenu::item:selected  --鼠标移动到上面颜色
QMenu::item:pressed   --鼠标按下颜色
QMenu::separator        --分割条

更加高级配置参考官网:https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu

]

----
18.设置窗口默认图标、exe图标 

设置窗口默认图标:
[
//设置窗口默认图标,状态栏统一会生效
    setWindowIcon(QIcon(":/image/res/Main.ico"));
]

设置exe图标:任务管理器图标会统一变化
[
新建一个txt文件,改成app.rc,然后notepad++打开,加上 IDI_ICON1 ICON DISCARDABLE "res\Main.ico"  ,保存起来
然后pro工程文件中加入RC_FILE += app.rc,编译即可
]

---
19.托盘图标

Qt提供了托盘图标的类:QSystemTrayIcon
[
头文件添加:

添加托盘图标:
QSystemTrayIcon m_sysTrayIcon;//托盘图标

cpp文件构造函数中添加:

 //托盘图标
    m_sysTrayIcon.setIcon(QIcon(":/image/res/Main.ico"));

    QMenu* menu = new QMenu();//托盘菜单
    menu->addAction("11");
    menu->addAction("22");
    m_sysTrayIcon.setContextMenu(menu);//设置右键菜单
    m_sysTrayIcon.show();//显示

    //响应托盘图标事件
    connect(&m_sysTrayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(OnSysTrayicon(QSystemTrayIcon::ActivationReason)));

---
void MainWindow::OnSysTrayicon(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason) {
    case QSystemTrayIcon::Trigger://点击事件
    {
        if(!this->isVisible())
        {
            this->show();
        }
        else
        {
            this->hide();
        }
    }
    break;
    default:
        break;
    }
}

]


---
20.异形窗口

(1)实现方式

方式1:万能方法,对话框dialog和窗口Widget都支持
思路:去掉标题栏,设置背景透明属性,pain函数中贴图片

[
第一步:.h中添加:
QPixmap        m_pixmap;

第二步:.cpp中,构造函数添加:
[
setWindowFlags(Qt::FramelessWindowHint);    //去掉标题栏
m_pixmap.load(":/image/res/big_pic.png");          //加载
resize(m_pixmap.size());                    //设置窗口大小为图片大小

setAttribute(Qt::WA_TranslucentBackground);

然后
void myDialog::paintEvent(QPaintEvent *)      //绘制
{
    QPainter painter(this);
    painter.fillRect(this->rect(), QColor(0, 0, 255, 0));
    painter.drawPixmap(rect(), m_pixmap);
}
]

第三步:添加窗口支持拖动
头文件:
[
void mouseMoveEvent(QMouseEvent * event);
    void mousePressEvent(QMouseEvent * event);
    void mouseReleaseEvent(QMouseEvent * event);

//设置拖动
    QPoint m_ptPress;
    bool  m_bLeftBtnPress;
]

cpp文件:
[
void myDialog::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_ptPress = event->globalPos();        //记录按下位置
        m_bLeftBtnPress = true;
    }
    event->ignore();
}

void myDialog::mouseMoveEvent(QMouseEvent *event)
{
    if(m_bLeftBtnPress)                        //移动窗口
    {
        move(pos() + event->globalPos() - m_ptPress);
        m_ptPress = event->globalPos();
    }
    event->ignore();
}

void myDialog::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        m_bLeftBtnPress = false;
    event->ignore();
}
]

]

其他方法:但都没有上述方法好
[
思路2:遮罩方式,用图片把控件遮挡,然后设置图片掩码mask
setAutoFillBackground(true);                //设置自动填充
 setMask(m_pixmap.mask());                  //设置图片透明的地方为穿透

paint函数中:
QPalette palette = this->palette();
    palette.setBrush(QPalette::Background,m_pixmap);
    setPalette(palette);

缺点:有黑边

]

(2)控件Label异形
[

QPixmap m_pic;

m_pic.load(":/image/res/messag.png");
    //m_pic.load(":/image/res/mybmp.bmp");
    ui->labelYixing->resize(m_pic.size());
    ui->labelYixing->setPixmap(m_pic);
    ui->labelYixing->setMask(m_pic.mask());

控件只要是png图片就行了,png图片背景可以是透明的,所以讨论普通控件异形感觉没必要


]

说明:异形窗口通用的一般用widget就好了,而不是用对话框

---
21.半透明窗口

实现方法:直接设置窗口透明度
[
//设置窗口透明度
    setWindowOpacity(0.5);//0透明,1不透明,中间值代表透明度
]

----
22.按钮上有文字和图标

实现方式:
[
1.qt中pushButton和toolButton都支持设置文字和图片,
pushButton     --文字和图片在左右的都支持,上下不支持
toolButton      --文字和图片在左右的都支持,图片在上、文字在下支持,反过来不支持

自定义实现     --文字在上、图片在下需要自定义实现
因为qt控件都支持setLayout,所以理论上可以自定义实现任意功能
例子:

 //按钮4  --文字在上,图片在下
    QSize btnSize = ui->toolButton4->size();

    QLabel *iconLabel = new QLabel;
   // iconLabel->setStyleSheet("border:1px solid red;");
    iconLabel->setAlignment(Qt::AlignCenter);
    iconLabel->setFixedWidth(btnSize.width());//宽度长了不会影响图片显示,设置居中显示就可以了
    iconLabel->setFixedHeight(m_pic.size().height());
    iconLabel->setPixmap(m_pic);

    QLabel *textLabel = new QLabel;
   // textLabel->setStyleSheet("border:1px solid red;");
    textLabel->setAlignment(Qt::AlignCenter);
    textLabel->setFixedSize(btnSize.width(),12);
    textLabel->setText("按钮4");

    QVBoxLayout *myLayout = new QVBoxLayout(ui->toolButton4->window());
    myLayout->setContentsMargins(1, 1, 1, 1);//默认这两个参数有默认值,所以需要重新设置,不然位置对不上
    myLayout->setSpacing(0);

    myLayout->addStretch();//相当于一个长度自动填充的space
    myLayout->addWidget(textLabel);
    myLayout->addSpacing(2);
    myLayout->addWidget(iconLabel);
    myLayout->addStretch();
    ui->toolButton4->setLayout(myLayout);

注意点:
qt中的QVBoxLayout等都有默认边框和space,所以必须要如下设置,
[
myLayout->setContentsMargins(1, 1, 1, 1);//默认这两个参数有默认值,所以需要重新设置,不然位置对不上
myLayout->setSpacing(0);
]
避免位置对不上

]

]

---
23.设置动画
[
QT自带动画类,可以设置窗口显示和消失的动画效果

1.设置动画显示和隐藏
显示: --渐变效果
构造函数添加
 //界面动画,改变透明度的方式出现0 - 1渐变
        QPropertyAnimation *animation = new QPropertyAnimation(this, "windowOpacity");
        animation->setDuration(1000);
        animation->setStartValue(0);
        animation->setEndValue(1);
        animation->start();

界面消失时动画:  --渐变效果
//界面动画,改变透明度的方式消失1 - 0渐变
    QPropertyAnimation *animation = new QPropertyAnimation(this, "windowOpacity");
    animation->setDuration(1000);
    animation->setStartValue(1);
    animation->setEndValue(0);
    animation->start();
    connect(animation, SIGNAL(finished()), this, SLOT(close()));

说明:
1.QPropertyAnimation的第二个参数,与setStartValue、setEndValue是对应的,填什么属性,就要填什么值
窗口支持的属性,直接看QWidget源码,属性带Write的一般可以填

setDuration(1000);  --从开始到结束持续时间

一般比较常用的就是:
渐变显示  --用透明度实现,
[
 //界面动画,改变透明度的方式出现0 - 1渐变
        QPropertyAnimation *animation = new QPropertyAnimation(this, "windowOpacity");
        animation->setDuration(1000);
        animation->setStartValue(0);
        animation->setEndValue(1);
        animation->start();
]

左、右、上、下的移入移出窗口  --用设置窗口位置实现,
[
      QPropertyAnimation *animation = new QPropertyAnimation(this, "geometry");
        animation->setDuration(1000);
        animation->setStartValue(QRect(-200,100,0,500));
        animation->setEndValue(QRect(0,100,500,500));
        animation->start();
]

2.connect(animation, SIGNAL(finished()), this, SLOT(close()));  --指动画结束时,响应对话框的close函数

]

---
24.设置窗口背景
[
(1)第一步:设置背景:
[
方法1:样式表
QDialog#myDialogBk
{
    border-image: url(:/image/res/winbg2.png);
    /*background-image: url(:/image/res/winbg2.png);*/
}
注意点:
1.QT子控件会继承父窗口的背景,避免方法是指定使用的对象,即QDialog#myDialogBk(第二个是对象名称)
2.设置背景后,总感觉默认拖上去的控件显示好像不对一样,其实大部分是错觉,可能是处于焦点的状态,处理方法是focusPolicy选择NoFocus

方法2:
自绘,把图片绘制上去
void myDialogBk::paintEvent(QPaintEvent *event)
{
   QPainter painter( this);
   painter.drawPixmap(0,0,400,700,QPixmap(":/image/res/winbg.png"));
}

建议直接使用界面,加上stylesheet,可以省掉好多代码

(2)第二步:去掉标题栏
构造函数添加
this->setWindowFlags(Qt::FramelessWindowHint);//去掉标题栏

(3)第三步:设置窗口上面当作标题部分可移动
[
头文件:
protected:
    void mouseMoveEvent(QMouseEvent * event);
    void mousePressEvent(QMouseEvent * event);
    void mouseReleaseEvent(QMouseEvent * event);

//设置拖动
    QPoint m_ptPress;
    bool  m_bLeftBtnPress;

cpp文件:
void myDialogBk::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        QRect rect;
        rect = this->geometry();
        rect.setHeight(37);
        if(rect.contains(event->globalPos()))
        {
            m_ptPress = event->globalPos();        //记录按下位置
            m_bLeftBtnPress = true;
        }
    }
    event->ignore();
}

void myDialogBk::mouseMoveEvent(QMouseEvent *event)
{
    if(m_bLeftBtnPress)                        //移动窗口
    {
        move(pos() + event->globalPos() - m_ptPress);
        m_ptPress = event->globalPos();
    }
    event->ignore();
}

void myDialogBk::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        m_bLeftBtnPress = false;
    event->ignore();
}

(4)第4步:关闭按钮
void myDialogBk::on_btn_close_clicked()
{
    this->close();
}

]

]
]

---
25.拖拽
[
进入拖拽:  --拖
鼠标按下,然后移动5个像素仍然在控件内,认为是拖拽,进入拖拽方法是
//进入拖拽
    QDrag drag(this);
    
    //设置拖拽数据
    QMimeData* mimeData = new QMimeData();
    if (m_dragLabel == ui->m_htmlLabel)
        mimeData->setHtml("<html>This is a html page</html>");

//进入拖拽
    drag.exec(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction);

---
响应拖拽:  --放

第一步:支持拖拽的控件先设置支持拖拽
this->setAcceptDrops(true);

第二步:重写响应拖拽函数
(1)进入、离开接受控件,接受控件设置要设置背景变化
注意进入时dragEnterEvent函数要
event->setDropAction(m_acceptableDropAction);//
event->accept();

(2)注意最后接受响应的函数是dropEvent

(3)需要重载的接受函数如下:
virtual void dragEnterEvent(QDragEnterEvent *event);//拖拽进入支持拖拽的控件
    virtual void dragLeaveEvent(QDragLeaveEvent *event);//拖拽离开支持拖拽的控件
    virtual void dragMoveEvent(QDragMoveEvent *event);//拖拽在支持拖拽的控件上面移动
    virtual void dropEvent(QDropEvent *event);//接受拖拽

//注意整个窗口都是拖拽区域,所以开始拖拽时已经在目标区域了
void myDialog_drag_drop::dragEnterEvent(QDragEnterEvent *event)
{
    //进入拖拽区域
    event->setDropAction(m_acceptableDropAction);//
    event->accept();
    m_currentBkColor = m_dragEnteredColor;

    QWidget::dragEnterEvent(event);
}

//因为一开始就在整个窗口了,所以离开整个窗口才叫离开
void myDialog_drag_drop::dragLeaveEvent(QDragLeaveEvent *event)
{
    //离开拖拽区域
    m_currentBkColor = m_dragLeavedColor;

    repaint();
    QWidget::dragLeaveEvent(event);
}

void myDialog_drag_drop::dragMoveEvent(QDragMoveEvent *event)
{
    //在拖拽区域移动
    if (m_acceptableRect.contains(event->answerRect()))
        m_currentDragableAreaColor = m_highlightColor;
    else
        m_currentDragableAreaColor = m_unhighlightColor;

    repaint();
}

//整个窗口都是拖拽区域,所以松开时在窗口内就是接受成功了,那个指定的区域只是用来显示内容显示
void myDialog_drag_drop::dropEvent(QDropEvent *event)
{
    m_currentDragableAreaColor = m_unhighlightColor;
    m_currentBkColor = m_dragLeavedColor;
    m_mimeData = event->mimeData();

    repaint();
    m_mimeData = nullptr;
}

]


------
额外的提示:
[
ip地址

gif

窗口背景


按钮:上面图片,下面文字
按钮:左边图片,右边文字

半透明

异形窗口

动画显示

拖拽
]

-------
通用功能:
1.stylesheet


2.property
如何新增属性

----------------------------------------------------------------------------------------------
Qt官网自定义所有控件例子参考网址:
https://doc.qt.io/qt-5/stylesheet-examples.html

 

-----------

Demo图片:

Demo地址:QT实战-常见功能实现-精进篇

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值