C++ Qt 学习(四):自定义控件与 qss 应用

1. qss 简介

  • Qt style sheet(qss,Qt 样式表),不需要用 C++ 代码控件进行重载,就可以修改控件外观,类似于前端的 css

2. qss 选择器

2.1 通配符选择器

/* 设置后控件窗口背景色都被修改为黄色 */
* {background-color:yellow;
}/* 指明子类 */
* QPushButton{background-color:yellow;
}

2.2 类型选择器

/* 通过控件类型来匹配控件的 (包括子类) */
QWidget {background-color:yellow
}/* 禁止父窗口影响子窗口样式 (不包括子类) */
setAttribute(Qt::WA_StyledBackground);/* 在类前面加个 .(不包括子类),这样就只对 QWidget 生效,如果界面上有其它控件则不生效 */
.QWidget {background-color:yellow
}

2.3 ID 选择器

  • ID 选择器是结合控件的 objectname 来匹配控件的,qss 里 objectname 前加个 “#” 来表示
    /* 只对 pushButton_2 有效*/
    QPushButton#pushButton_2 {background-color:blue
    }
    

2.4 属性选择器

  • 属性选择器是结合控件的属性值来匹配控件的,首先要设定控件的属性,qss 里属性用 [proterty = attitude] 来限制
    label1.setProperty('notice_level', 'error')
    label2.setProperty('notice_level', 'warning')
    
    .QLabel {background-color:pink;
    }.QLabel[notice_level='warning'] {border:5px solid yellow;
    }.QLabel[notice_level='error'] {border:5px solid red;
    }
    

3. QLabel

/* 设置普通样式 */
QLabel {font-family: "Microsoft YaHei";  /*字体类型*/font-size: 18px;                 /*字体大小*/color: #BDC8E2;                  /*字体颜色*/    font-style: normal;              /*字体斜体样式*/font-weight: normal;             /*字体加粗样式*//*设置边框属性*/border-style: solid;border-width: 2px;border-color: aqua;border-radius: 20px;/*设置文字显示位置*/padding-left: 20px;padding-top: 3px;/*设置背景样式*/background-color: #2E3648;background-image: url("./res/image/123.png");background-repeat: no-repeat;background-position: left center;
}/* 设置鼠标悬浮样式*/
QLabel:hover {color: red;border-color: green;background-color: aqua;
}/* 设置禁止样式 */
QLabel:disabled {color: blue;border-color: brown;background-color: #363636;
}

4. QLineEdit

在这里插入图片描述

  • widget.ui
    在这里插入图片描述

  • qss 样式

QWidget{background-color:rgb(54,54,54);
}QLineEdit{border: 1px solid #ABCDA0;      /* 边框宽度为1px,颜色为#A0A0A0 */border-radius: 3px;             /* 边框圆角 */padding-left: 5px;              /* 文本距离左边界有5px */background-color: #F2F2F2;      /* 背景颜色 */color: black;                   /* 文本颜色 */selection-background-color: #A0A0A0;  /* 选中文本的背景颜色 */selection-color: #F2F2F2;         /* 选中文本的颜色 */font-family: "Microsoft YaHei";   /* 文本字体族 */font-size: 10pt;                  /* 文本字体大小 */
}QLineEdit:hover { /* 鼠标悬浮在QLineEdit时的状态 */border: 1px solid #298DFF;border-radius: 3px;background-color: #F2F2F2;color: #298DFF;selection-background-color: #298DFF;selection-color: #F2F2F2;
}QLineEdit[echoMode="2"] { /* QLineEdit有输入掩码时的状态 */lineedit-password-character: 9679;lineedit-password-mask-delay: 2000;
}QLineEdit:disabled { /* QLineEdit在禁用时的状态 */border: 1px solid #CDCDCD;background-color: #CDCDCD;color: #B4B4B4;
}QLineEdit:read-only { /* QLineEdit在只读时的状态 */background-color: #CDCDCD;color: #F2F2F2;
}
  • widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_lineEdit_rex_returnPressed();void on_lineEdit_rex_inputRejected();void on_btnCheck_clicked();private:Ui::Widget *ui;
};
#endif // WIDGET_H
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QRegExpValidator>  // 使用正则表达式限制输入
#include <QDebug>
#include <QMessageBox>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->lineEdit_1->setText("Hello LineEdit");ui->lineEdit_2->setReadOnly(true);  // 设置为只读状态ui->lineEdit_2->setText("Hello LineEdit");ui->lineEdit_3->setText("Hello LineEdit");ui->lineEdit_3->setEchoMode(QLineEdit::Password);  // 设置密码为圆点隐藏状态ui->lineEdit_4->setDisabled(true);  // 设置为不可用状态// 使用正则表达式(QRegExp)来验证电子邮件地址的格式QRegExp regx("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}");// 指定验证的目标为 ui->lineEdit_rex(一个文本输入框)QValidator *validator = new QRegExpValidator(regx, ui->lineEdit_rex);// 将验证器应用到 lineEdit_rex上,这样用户在该输入框中输入文本时,将根据正则表达式进行验证ui->lineEdit_rex->setValidator(validator);
}Widget::~Widget() {delete ui;
}// 当用户在 lineEdit_rex 中按下回车键并释放时触发这个函数
void Widget::on_lineEdit_rex_returnPressed() {qDebug() << "on_lineEdit_rex_returnPressed";
}// 当 lineEdit_rex 中的输入被验证器拒绝时触发这个函数
void Widget::on_lineEdit_rex_inputRejected() {qDebug() << "on_lineEdit_rex_inputRejected";
}// 获取 lineEdit_rex 文本框的验证器,并根据输入的文本内容进行验证
void Widget::on_btnCheck_clicked() {// 验证器 validator 用于限制用户输入的内容符合特定的模式或规则const QValidator *v = ui->lineEdit_rex->validator();int pos = 0;// 获取 lineEdit_rex 文本框中的文本内容QString text = ui->lineEdit_rex->text();// 用于检查刚才获取的文本内容是否满足验证器的要求if (v->validate(text, pos) != QValidator::Acceptable) {ui->lineEdit_rex->setText(QString::fromLocal8Bit("邮箱格式不正确"));} else {QMessageBox::information(this, u8"标题", u8"邮箱格式正确");}
}

5. QPushButton

5.1 点击按钮弹出菜单

在这里插入图片描述

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMenu>
#include <QAction>
#include <QFileDialog>
#include "qss.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setStyleSheet("background-color:rgb(54,54,54)");// 1、创建 文件 菜单项QMenu *fileMenuItems = new QMenu;fileMenuItems->setIcon(QIcon(":/resources/file.png"));fileMenuItems->setTitle(u8"文件");fileMenuItems->setStyleSheet(QString::fromStdString(menuItemQss));QList<QAction*> acList;  // 用于存放子级菜单// 为 文件 菜单项添加 action 构成子菜单QAction *openFileAc = new QAction(QIcon(":/resources/file.png"), u8"打开文件", this);//openFileAc->setShortcuts(QKeySequence::Print);   // 设置快捷键,系统内置枚举量openFileAc->setShortcut(QKeySequence("Ctrl+8"));   // 随意指定快捷键QAction *openFloderAc = new QAction(u8"打开文件夹", this);QAction *openUrlAc = new QAction(u8"打开url", this);// QMenu 添加 QMenu 构成多级菜单acList << openFileAc << openFloderAc << openUrlAc;fileMenuItems->addActions(acList);// 0、主菜单(父菜单,包括 文件 播放 工具 设置 退出)QMenu *pMenu = new QMenu;pMenu->addMenu(fileMenuItems);// 2、创建 播放 工具 菜单项(无子级菜单)QAction *play = new QAction(QIcon(":/resources/play.png"), u8"播放", this);QAction *tools = new QAction(QIcon(":/resources/tools.png"), u8"工具", this);pMenu->addAction(play);pMenu->addAction(tools);pMenu->addSeparator();  // 添加分割线// 3、创建 设置 菜单项QMenu *setMenuItems = new QMenu;setMenuItems->setTitle(u8"设置");setMenuItems->setIcon(QIcon(":/resources/set.png"));QList<QAction*> setList;// 为 设置 菜单项添加 action 构成子菜单QAction *sysSetAc = new QAction(u8"系统设置", this);QAction *playSetAc = new QAction(u8"播放设置", this);QAction *zimuSetAc = new QAction(u8"字幕设置", this);setList << sysSetAc << playSetAc << zimuSetAc;setMenuItems->addActions(setList);setMenuItems->setStyleSheet(QString::fromStdString(menuItemQss));pMenu->addMenu(setMenuItems);pMenu->addSeparator();  // 添加分割线// 4、创建 退出 菜单项QAction *exitAc = new QAction(QIcon(":/resources/exit.png"), u8"退出", this);pMenu->addAction(exitAc);ui->pushButton->setMenu(pMenu);connect(openFileAc, &QAction::triggered, [=]{QString fileName = QFileDialog::getOpenFileName(this,u8"请选择视频文件","D:/","视频(*.mp4 *.flv);;");if (fileName.isEmpty()) {return;}});ui->pushButton->setText(u8"QW影音");ui->pushButton->setFixedSize(100, 32);ui->pushButton->setStyleSheet(QString::fromStdString(button_qss));pMenu->setStyleSheet(QString::fromStdString(menuQss));
}Widget::~Widget() {delete ui;
}
  • qss.h
#ifndef QSS_H
#define QSS_H#include <string>using namespace std;string button_qss = R"(QPushButton {font:18px "Microsoft YaHei";color:rgb(255,255,255);border:none}QPushButton::menu-indicator:open {image:url(:/resources/down_arrow.svg);subcontrol-position:right center;subcontrol-origin:padding;border:none;}QPushButton::menu-indicator:closed {image:url(:/resources/up_arrow.svg);subcontrol-position:right center;subcontrol-origin:padding;border:none;}
)";string menuQss = R"(QMenu {background-color:rgb(53, 63, 73);}QMenu::item {font:16px;color:white;background-color:rgb(53, 63, 73);padding:8px 32px;margin:8px 8px;/*border-bottom:1px solid #DBDBDB;  item底部颜色*/}/*选择项设置*/QMenu::item:selected {background-color:rgb(54, 54, 54);}
)";string menuItemQss = R"(QMenu {background-color:rgb(73, 73, 73);}QMenu::item {font:16px;color:white;background-color:rgb(73, 73, 73);padding:8px 32px;margin:8px 8px;/*border-bottom:1px solid #DBDBDB;  item底部颜色*/}/*选择项设置*/QMenu::item:selected {background-color:rgb(54, 54, 54);}
)";#endif // QSS_H

5.2 鼠标悬浮弹出对话框

在这里插入图片描述

5.2.1 主窗口
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include "CVolumeButton.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);resize(800, 600);QHBoxLayout *pHlay = new QHBoxLayout(this);// 音量调节按钮CVolumeButton* pVolumeButton = new CVolumeButton(this);pHlay->addWidget(pVolumeButton);
}Widget::~Widget() {delete ui;
}
5.2.2 音量按钮
  • CVolumeButton.h
/*
音量调节按钮
功能:1. 鼠标悬浮到音量时显示 slider dialog2. 点击时 mute
注意问题:重写按钮类,样式表无效
*/
#pragma once#include <QPushButton>
#include "CVolumeSliderDialog.h"class CVolumeButton : public QPushButton {Q_OBJECTpublic:CVolumeButton(QWidget* parent = nullptr);~CVolumeButton();bool getMute() const {return m_isMute;}// 设置静音void setMute(bool mute) { m_isMute = mute;}signals:void sig_VolumeValue(int value);protected:void paintEvent(QPaintEvent* event) override;void enterEvent(QEvent* event) override;//void leaveEvent(QEvent* event) override;void mousePressEvent(QMouseEvent* event) override;void timerEvent(QTimerEvent* event) override;private:bool m_isMute = false;  // 是否静音CVolumeSliderDialog* m_pVolumeSliderDlg = nullptr;int m_timerId = -1;
};
  • CVolumeButton.cpp
#include "CVolumeButton.h"
#include <QMouseEvent>
#include <QStylePainter>
#include <QStyleOptionButton>
#include <iostream>
#include <QThread>using namespace std;CVolumeButton::CVolumeButton(QWidget* parent) : QPushButton(parent) {this->setFixedSize(32, 32);  // 音量按钮大小setStyleSheet("QPushButton{background-image:url(:/resources/audio_open.svg);border:none;}""QPushButton:hover{background-image:url(:/resources/audio_open_hover.svg);border:none;}""QPushButton:pressed{background-image:url(:/resources/audio_open.svg);border:none;}");
}CVolumeButton::~CVolumeButton() {}// 绘制一个样式化的按钮,以便与应用程序的整体外观和主题保持一致
void CVolumeButton::paintEvent(QPaintEvent*) {QStylePainter p(this);  // QStylePainter 用于样式化绘制 widgetQStyleOptionButton option;  // 用于存储按钮的样式选项initStyleOption(&option);   // 初始化 option 对象,以便正确设置按钮的样式选项p.drawControl(QStyle::CE_PushButton, option);  // 绘制一个样式化的按钮
}// 在鼠标进入 CVolumeButton 对象时显示一个音量滑动条,其位置在 CVolumeButton 的正上方
void CVolumeButton::enterEvent(QEvent* event) {if (!m_pVolumeSliderDlg)m_pVolumeSliderDlg = new CVolumeSliderDialog(this);// 将 widget 坐标 pos 转换为全局屏幕坐标QPoint p1 = this->mapToGlobal(QPoint(0, 0));  // 声音按钮左上角相对于桌面的绝对位置QRect rect1 = this->rect();QRect rect2 = m_pVolumeSliderDlg->rect();     // rect 包含标题栏,去掉标题栏后 height 不变int x = p1.x() + (rect1.width() - rect2.width()) / 2;int y = p1.y() - rect2.height() - 5;m_pVolumeSliderDlg->move(x, y);               // move 是相对于桌面原点的位置m_pVolumeSliderDlg->show();m_timerId = startTimer(250);connect(m_pVolumeSliderDlg, &CVolumeSliderDialog::sig_SliderValueChanged, [=](int value) {emit sig_VolumeValue(value);});
}// 鼠标移出控件或窗口
//void CVolumeButton::leaveEvent(QEvent* event)
//{
//	根据鼠标的位置判断音量调节窗口是否消失
//	//QPoint p1 = QCursor::pos();   // 绝对位置
//
//	//cout << "QCursor x= " << p1.x() << " y = " << p1.y() << endl;
//
//	//if (m_pVolumeSliderDlg) {
//	//	QRect rect1 = this->rect();  // 按钮矩形
//	//	QRect rect2 = m_pVolumeSliderDlg->rect();
//	//	QRect rect3 = m_pVolumeSliderDlg->geometry();
//
//	//	QPoint p2 = this->mapToGlobal(QPoint(0, 0));   // 声音按钮左上角相对于桌面的绝对位置
//
//	//	// 已知:音量框宽 40 > 按钮宽 30
//	//  // 左上宽高
//	//	QRect area(rect3.left(), rect3.top(), rect2.width(), p2.y() + rect1.height() - rect3.top());
//	//	cout << "p1 x = " << p1.x() << " y = " << p1.y() << endl;
//
//	//	if (!area.contains(p1)) {
//	//		m_pVolumeSliderDlg->hide();
//	//	}
//	//}
//}// 鼠标按下事件,用于处理音量按钮的交互行为
void CVolumeButton::mousePressEvent(QMouseEvent* event) {if (event->button() == Qt::LeftButton) {  // 检测鼠标事件的按钮类型是否为左键m_isMute = !m_isMute;if (m_isMute) {  // 如果是左键点击,则切换静音状态if (m_pVolumeSliderDlg)m_pVolumeSliderDlg->setSliderValue(0);} else {         // 如果静音状态为假,将滑动条的值设置为 50if (m_pVolumeSliderDlg)m_pVolumeSliderDlg->setSliderValue(50);}}
}/*** @brief 用定时器模拟 leaveEvent* 直接在 leaveEvent 里让 m_pVolumeSliderDlg 消失,效果不太好* 用鼠标移动事件也不太好,定时器是比较好的做法*/
void CVolumeButton::timerEvent(QTimerEvent* event) {if ((m_pVolumeSliderDlg != nullptr) && (m_pVolumeSliderDlg->isVisible())) {QPoint p1 = QCursor::pos();      // 鼠标绝对位置if (m_pVolumeSliderDlg) {QRect rect1 = this->rect();  // 按钮矩形QRect rect2 = m_pVolumeSliderDlg->rect();QRect rect3 = m_pVolumeSliderDlg->geometry();QPoint p2 = this->mapToGlobal(QPoint(0, 0));   // 声音按钮左上角相对于桌面的绝对位置// 已知:音量框宽 40 > 按钮宽 30// 左上宽高QRect area(rect3.left(), rect3.top(), rect2.width(), p2.y() + rect1.height() - rect3.top());if (!area.contains(p1)) {m_pVolumeSliderDlg->hide();}}} else {killTimer(m_timerId);}
}
5.2.3 音量调节滑动条
  • CVolumeSliderDialog.h
#ifndef CVOLUMESLIDERDIALOG_H
#define CVOLUMESLIDERDIALOG_H#include <QDialog>
#include <QSlider>class CVolumeSliderDialog : public QDialog {Q_OBJECTpublic:CVolumeSliderDialog(QWidget *parent = Q_NULLPTR);~CVolumeSliderDialog();void setSliderValue(int value) {m_pSlider->setValue(value);}protected:bool event(QEvent* event) override;signals:void sig_SliderValueChanged(int value);private:QSlider* m_pSlider = nullptr;
};#endif
  • CVolumeSliderDialog.cpp
#include "CVolumeSliderDialog.h"
#include <QVBoxLayout>
#include <QEvent>
#include <windows.h>// 注意由于此类使用了 windows 的函数 SetClassLong,需要包含 user32.lib
// 如果是在 vs2019 中使用则不需要包含 user32.lib
#pragma comment(lib, "user32.lib")CVolumeSliderDialog::CVolumeSliderDialog(QWidget* parent) : QDialog(parent) {// 创建竖直滑动条并添加进竖直布局中this->setFixedSize(40, 200);QVBoxLayout* pVLay = new QVBoxLayout(this);m_pSlider = new QSlider(this);m_pSlider->setOrientation(Qt::Vertical);pVLay->addWidget(m_pSlider);// 创建滑动按钮setFixedSize(40, 120);setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);   // ToolTip : 悬浮是显示,离开时消失// 0.5 表示透明度,0 表示全透明、1 表示不透明;也可以使用百分比表示setStyleSheet("QDialog{background-color: rgba(54, 54, 54, 0.5);}");connect(m_pSlider, &QSlider::valueChanged, [=](int value) {emit sig_SliderValueChanged(value);});
}CVolumeSliderDialog::~CVolumeSliderDialog() {}// 参考 qt 文档:bool QWidget::event(QEvent *event)
// 设置 popup 后,dialog 有窗口阴影,需要去除就重写 event 函数
bool CVolumeSliderDialog::event(QEvent* event) {static bool class_amended = false;if (event->type() == QEvent::WinIdChange) {HWND hwnd = (HWND)winId();if (class_amended == false) {class_amended = true;DWORD class_style = ::GetClassLong(hwnd, GCL_STYLE);class_style &= ~CS_DROPSHADOW;::SetClassLong(hwnd, GCL_STYLE, class_style); // windows 系统函数}}return QWidget::event(event);
}

6. QCheckBox 实现打开、关闭状态按钮

在这里插入图片描述

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->checkBox->setFixedSize(128, 64);QString qss = "QCheckBox::indicator:unchecked{ \image:url(:/resources/status_close.png); \} \QCheckBox::indicator:checked { \image: url(:/resources/status_open.png); \}";ui->checkBox->setStyleSheet(qss);ui->checkBox->setChecked(true);//ui->checkBox->setTristate(true);connect(ui->checkBox, &QCheckBox::stateChanged, [=](int state){qDebug() << state;});
}Widget::~Widget() {delete ui;
}

7. QComboBox 样式表

在这里插入图片描述

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <string>
#include <QListView>using namespace std;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QStringList strList;strList << "item1" << "item2" << "item3" << "item4"<< "item1" << "item2" << "item3" << "item4"<< "item1" << "item2" << "item3" << "item4"<< "item1" << "item2" << "item3" << "item4";ui->comboBox->addItems(strList);// 将 QComboBox 的下拉列表视图设置为 QListView,并将此视图限定在当前的 QWidget 类的范围内显示ui->comboBox->setView(new QListView(this));ui->comboBox->setEditable(true);//ui->comboBox->insertSeparator(10);//ui->comboBox->insertSeparator(12);
}Widget::~Widget() {delete ui;
}
  • qss
/* 未下拉时,QComboBox的样式 */
QComboBox {border: 1px solid gray;   /* 边框 */border-radius: 5px;   /* 圆角 */padding: 1px 18px 1px 3px;   /* 字体填衬 */color: white;font: normal normal 24px "Microsoft YaHei";background:rgb(54,54,54);
}/* 下拉后,整个下拉窗体样式 */
QComboBox QAbstractItemView {outline: 0px solid gray;   /* 选定项的虚框 */border: 1px solid yellow;   /* 整个下拉窗体的边框 */color: rgb(250,251,252);background-color: rgb(70,80,90);   /* 整个下拉窗体的背景色 */selection-background-color: lightgreen;   /* 整个下拉窗体被选中项的背景色 */
}/* 下拉后,整个下拉窗体每项的样式 */
/* 项的高度(设置 ComboBox->setView(new QListView(this)); 后该项才起作用) */
QComboBox QAbstractItemView::item {height: 50px;   
}/* 下拉后,整个下拉窗体越过每项的样式 */
QComboBox QAbstractItemView::item:hover {color: rgb(90,100,105);background-color: lightgreen;   /* 整个下拉窗体越过每项的背景色 */
}/* 下拉后,整个下拉窗体被选择的每项的样式 */
QComboBox QAbstractItemView::item:selected {color: rgb(12, 23, 34);background-color: lightgreen;
}/* QComboBox中的垂直滚动条 */
QComboBox QAbstractScrollArea QScrollBar:vertical {width: 13px;background-color: #d0d2d4;   /* 空白区域的背景色*/
}QComboBox QAbstractScrollArea QScrollBar::handle:vertical {border-radius: 5px;   /* 圆角 */background: rgb(60,60,60);   /* 小方块的背景色深灰lightblue */
}QComboBox QAbstractScrollArea QScrollBar::handle:vertical:hover {background: rgb(90, 91, 93);   /* 越过小方块的背景色yellow */
}/* 设置为可编辑(setEditable(true))editable时,编辑区域的样式 */
QComboBox:editable {background: green;
}/* 设置为非编辑(setEditable(false))!editable时,整个QComboBox的样式 */
QComboBox:!editable {background: rgb(54,54,54);
}/* 设置为可编辑editable时,点击整个QComboBox的样式 */
QComboBox:editable:on {background: rgb(54,54,54);
}/* 设置为非编辑!editable时,点击整个QComboBox的样式 */
QComboBox:!editable:on {background: rgb(54,54,54);
}/* 设置为可编辑editable时,下拉框的样式 */
QComboBox::drop-down:editable {background: rgb(54,54,54);
}/* 设置为可编辑editable时,点击下拉框的样式 */
QComboBox::drop-down:editable:on {background: rgb(54,54,54);
}/* 设置为非编辑!editable时,下拉框的样式 */
QComboBox::drop-down:!editable {background: rgb(54,54,54);
}/* 设置为非编辑!editable时,点击下拉框的样式 */
QComboBox::drop-down:!editable:on {background: rgb(54,54,54);image: url(:/resources/up.png); /* 显示上拉箭头 */ 
}/* 下拉框样式 */
QComboBox::drop-down {subcontrol-origin: padding;   /* 子控件在父元素中的原点矩形。如果未指定此属性,则默认为padding。 */subcontrol-position: top right;   /* 下拉框的位置(右上) */width: 32px;   /* 下拉框的宽度 */border-left-width: 1px;   /* 下拉框的左边界线宽度 */border-left-color: darkgray;   /* 下拉框的左边界线颜色 */border-left-style: solid;   /* 下拉框的左边界线为实线 */border-top-right-radius: 3px;   /* 下拉框的右上边界线的圆角半径(应和整个QComboBox右上边界线的圆角半径一致) */border-bottom-right-radius: 3px;   /* 同上 */image: url(:/resources/down.png); 
}/* 越过下拉框样式 */
QComboBox::drop-down:hover {background: rgb(80, 75, 90);
}/* 下拉箭头样式 */ 
QComboBox::down-arrow {  width: 32px; /* 下拉箭头的宽度(建议与下拉框drop-down的宽度一致) */   background: rgb(54,54,54); /* 下拉箭头的的背景色 */   padding: 0px 0px 0px 0px; /* 上内边距、右内边距、下内边距、左内边距 */  image: url(:/resources/down.png); 
} /* 点击下拉箭头 */ 
QComboBox::down-arrow:on {   image: url(:/resources/up.png); /* 显示上拉箭头 */ 
}

8. QProgressBar 用法及样式表

在这里插入图片描述

  • widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTimer>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnStart_clicked();void on_btnStop_clicked();private:Ui::Widget *ui;QTimer *m_pTimer = nullptr;
};
#endif // WIDGET_H
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);m_pTimer = new QTimer(this);ui->progressBar->setValue(0);ui->progressBar->setRange(0, 100);ui->progressBar->setFormat("%p%");// lambda 表达式用于每个定时器超时时更新 QProgressBar 组件的当前进度值,其中的 step 变量用于存储当前进度值// 当定时器超时时,step 的值会自增 1,并将新的进度值设置到 QProgressBar 组件上connect(m_pTimer, &QTimer::timeout, [=]{static int step = 0;ui->progressBar->setValue(step++);});ui->progressBar_2->setOrientation(Qt::Vertical);ui->progressBar_2->setFixedWidth(60);ui->progressBar_2->setFixedHeight(300);
}Widget::~Widget() {delete ui;
}void Widget::on_btnStart_clicked() {m_pTimer->start(50);
}void Widget::on_btnStop_clicked() {m_pTimer->stop();
}
  • qss
QProgressBar {background:rgb(54,54,54);border:none;   /*无边框*/border-radius:5px;text-align:center;   /*文本的位置*/color: rgb(229, 229, 229);  /*文本颜色*/
}QProgressBar::chunk  {background-color:rgb(58, 154, 255);border-radius:4px;
}
QProgressBar:vertical {border-radius:5px;background-color:darkgray;text-align:center;padding-left: 5px; padding-right: 4px; padding-bottom: 2px; 
}QProgressBar::chunk:vertical {background-color:QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #00ff58,stop: 1 #034f1f);margin:1px;
}

9. QSlider 用法及样式表

在这里插入图片描述

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "qss.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->hSlider->setStyleSheet(QString::fromStdString(hslider_qss));
}Widget::~Widget() {delete ui;
}
  • qss.h
#ifndef QSS_H
#define QSS_H#include <string>using namespace std;string hslider_qss = R"(QSlider {background-color: #FF0000;border-style: outset;border-radius: 1px;}QSlider::groove:horizontal {height: 12px;background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);margin: 2px 0}QSlider::handle:horizontal {background: QRadialGradient(cx:0, cy:0, radius: 1, fx:0.5, fy:0.5, stop:0 white, stop:1 green);width: 16px;height: 16px;margin: -5px 6px -5px 6px;border-radius:11px;border: 3px solid #ffffff;}
)";#endif // QSS_H

10. qss 加载方式详解

  • 方式一:在 qt 设计器里写

  • 方式二:C++ 代码写

    • QString 或 R 字符串
  • 方式三:写到 qss 文件里,读文件

    • 放到程序外部,暴露给用户
    • 加到 qrc 文件里,编译到 exe 里
  • widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTextStream>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QFile file(":/res/skin.qss");QString lineStr;if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {QTextStream txtInput(&file);while (!txtInput.atEnd()) {lineStr += txtInput.readLine();  // 逐行读取 qss 代码}}file.close();this->setStyleSheet(lineStr);
}Widget::~Widget() {delete ui;
}
  • skin.css
QWidget {background-color: rgb(54, 54, 54);border-top:2px;border-bottom:2px;border-left:2px;border-right:2px;
}QLineEdit {background-color: rgb(249, 249, 249); border: 1px solid black;border-radius:5;font:14px;
}QLabel {background-color: rgb(54, 54, 54); font:12px;color:white;
}QPushButton {color:rgb(251,251,251);    font:12px, "微软雅黑";background-color:rgb(105, 105, 105);border-radius:4px;padding:2px; 
}QPushButton:hover {color:#0000ff;background-color:rgb(210, 205, 205); /*改变背景色*/border-style:inset;/*改变边框风格*/padding-left:2px;padding-top:2px;
} QPushButton:flat {  border:2px solid red;  
} QPushButton:pressed {color:green;
} QPlainTextEdit {background-color: rgb(169, 169, 169); font:14px;color:white;
}

11. 控件提升与自定义控件

  • 控件提升相当于把控件变成另一个控件,或者说称为自定义控件,控件提升需要在 qt 设计器里操作
  • 案例:按钮图片在上,文字在下

在这里插入图片描述

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->pushButton->setText("");ui->pushButton->setFixedSize(64, 88);
}Widget::~Widget() {delete ui;
}

在这里插入图片描述

  • cmybutton.h
#ifndef CMYBUTTON_H
#define CMYBUTTON_H#include <QPushButton>
#include <QObject>
#include <QLabel>class CMyButton : public QPushButton {Q_OBJECTpublic:CMyButton(QWidget *parent = nullptr);void set_Text(const QString& text);private:QLabel *m_pIconLabel;QLabel *m_pTextLabel;
};#endif // CMYBUTTON_H
  • cmybutton.cpp
#include "cmybutton.h"
#include <QVBoxLayout>CMyButton::CMyButton(QWidget *parent) : QPushButton(parent) {this->setFixedSize(64, 88);this->setText("");m_pTextLabel = new QLabel(this);m_pIconLabel->setFixedSize(64, 64);m_pIconLabel->setPixmap(QPixmap(":/resources/save.png"));m_pTextLabel = new QLabel(this);m_pTextLabel->setFixedSize(64, 24);m_pTextLabel->setText(u8"保存");QVBoxLayout* pVlay = new QVBoxLayout(this);pVlay->addWidget(m_pIconLabel);//pVlay->addSpacing(5);pVlay->addWidget(m_pTextLabel);pVlay->setContentsMargins(0, 0, 0, 0);
}void CMyButton::set_Text(const QString& text) {m_pTextLabel->setText(text);
}

12. Qt 鼠标、控件、窗口位置详解

在这里插入图片描述

  • 桌面原点:在电脑桌面左上角(上图红点处)
  • 应用程序原点:在应用程序左上角
  • 坐标系一般都是 x 向左为正,y 向下为正
  • 绝对位置:相对于电脑桌面左上角的位置
  • 相对位置:相对于应用程序左上角的位置

12.1 鼠标的位置

  • 获取鼠标相对于桌面左上角的绝对位置

    QCursor::pos()
    
  • 获取 mousePressEvent 的参数 event 的位置

    event->pos()        // 鼠标相对于应用程序的位置,相对位置
    event->globalPos()  // 鼠标相对于桌面原点的位置,绝对位置
    

12.2 控件的位置

  • 相对位置
    • 按钮相对于应用窗口原点的位置
    QPoint p = ui->pushButton->pos();
    
  • 绝对位置
    • 按钮相对于桌面原点的位置
    QPoint p = ui->pushButton->mapToGlobal(QPoint(0, 0));
    
  • 控件大小
    QRect rect = ui->pushButton->rect();
    

12.3 应用程序窗口的位置

  • 相对位置
    QRect rect = m_pDlg->pos();
    
  • 绝对位置
    • 对话框相对于桌面原点的 rect
    QRect rect = m_pDlg->geometry();
    
  • 应用窗口大小
    QRect rect = m_pDlg->rect();
    

12.4 案例

在这里插入图片描述

在这里插入图片描述

  • widget.cpp
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();private:void mousePressEvent(QMouseEvent *event) override;private:Ui::Widget *ui;
};
#endif // WIDGET_H
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMouseEvent>
#include "tempdialog.h"
#include <memory>using namespace std;Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->pushButton->setFixedSize(100,200);
}Widget::~Widget() {delete ui;
}void Widget::mousePressEvent(QMouseEvent *event) {qDebug() << QCursor::pos();  // 鼠标绝对位置qDebug() << "event->pos()         " << event->pos();qDebug() << "event->globalPos()   " << event->globalPos();
}void Widget::on_pushButton_clicked() {qDebug() << u8"控件相对位置" << ui->pushButton->pos();QPoint jPos = ui->pushButton->mapToGlobal(QPoint(0,0));qDebug() << u8"控件绝对位置" << jPos;QRect rect = ui->pushButton->rect();qDebug() << rect;qDebug() << u8"窗口绝对位置" << this->geometry();  // 绝对位置qDebug() << u8"窗口矩形" << this->rect();//TempDialog *dlg = new TempDialog(this);std::unique_ptr<TempDialog> dlg(new TempDialog(this));dlg->move(jPos.x() - dlg->width(), jPos.y());dlg->exec();
}
  • tempdialog.h
#ifndef TEMPDIALOG_H
#define TEMPDIALOG_H#include <QDialog>namespace Ui {class TempDialog;
}class TempDialog : public QDialog {Q_OBJECTpublic:explicit TempDialog(QWidget *parent = nullptr);~TempDialog();private:Ui::TempDialog *ui;
};#endif // TEMPDIALOG_H
  • tempdialog.cpp
#include "tempdialog.h"
#include "ui_tempdialog.h"
#include <QDebug>TempDialog::TempDialog(QWidget *parent) : QDialog(parent), ui(new Ui::TempDialog) {ui->setupUi(this);
}TempDialog::~TempDialog() {delete ui;qDebug() << "123456";
}

13. 自定义 QLineEdit 实现搜索编辑框

在这里插入图片描述

13.1 主窗口

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include "csearchlineedit.h"
#include <QDebug>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setStyleSheet("background-color:#1A1E21");// 创建搜索栏实例化对象 pEditCSearchLineEdit* pEdit = new CSearchLineEdit(this);QVBoxLayout* pVLay = new QVBoxLayout(this);pVLay->addWidget(pEdit);// 链接 搜索栏 搜索信号与 主窗口 控制台打印槽函数connect(pEdit, &CSearchLineEdit::sig_Search, this, &Widget::onSearch);
}Widget::~Widget() {delete ui;
}// 在控制台打印搜索的内容
void Widget::onSearch(const QString& text) {qDebug() << u8"搜索的内容是 " << text;
}

13.2 搜索输入栏

  • csearchlineedit.h
#ifndef CSEARCHLINEEDIT_H
#define CSEARCHLINEEDIT_H#include <QLineEdit>
#include <QObject>
#include "csearchbutton.h"class CSearchLineEdit : public QLineEdit {Q_OBJECTpublic:CSearchLineEdit(QWidget *parent = nullptr);signals:void sig_Search(const QString& text);private:CSearchButton* m_pBtn = nullptr;
};#endif // CSEARCHLINEEDIT_H
  • csearchlineedit.cpp
#include "csearchlineedit.h"
#include <QHBoxLayout>
#include <string>using namespace std;CSearchLineEdit::CSearchLineEdit(QWidget *parent) : QLineEdit(parent) {// 将当前的窗口部件设置为使用样式背景this->setAttribute(Qt::WA_StyledBackground);string qss = R"(QLineEdit{background-color:#33373E;             /* 背景颜色 */border: 1px solid #33373E;            /* 边框宽度为1px,颜色为#A0A0A0 */border-radius: 20px;                  /* 边框圆角 */padding-left: 10px;                   /* 文本距离左边界有5px */color: #FFFFFF;                       /* 文本颜色 */selection-background-color: #A0A0A0;  /* 选中文本的背景颜色 */selection-color: #F2F2F2;             /* 选中文本的颜色 */font-family: \"Microsoft YaHei\";     /* 文本字体族 */font-size:18px;                       /* 文本字体大小 */})";this->setStyleSheet(QString::fromStdString(qss));this->setPlaceholderText(u8"请输入搜索内容");  // 只要行编辑为空,行编辑就会显示一个变灰显示占位符文本this->setFixedHeight(40);this->setMinimumWidth(400);// 创建搜索按钮实例化对象 m_pBtnm_pBtn = new CSearchButton(this);QHBoxLayout* pHlay = new QHBoxLayout(this);pHlay->addStretch();  // 添加弹簧挤压占位pHlay->addWidget(m_pBtn);// 设置控件周围边框大小pHlay->setContentsMargins(0, 0, 0, 0);// 设置文本周围的边距this->setTextMargins(10, 0, 130 + 5, 0);// 链接 搜索按钮点击信号 与 搜索栏 搜索信号connect(m_pBtn, &CSearchButton::clicked, [=]{emit sig_Search(this->text());});
}

13.3 搜索按钮

  • csearchbutton.h
#ifndef CSEARCHBUTTON_H
#define CSEARCHBUTTON_H#include <QPushButton>
#include <QObject>class CSearchButton : public QPushButton {Q_OBJECTpublic:CSearchButton(QWidget *parent = nullptr);private:void normalStyle();  // 按钮控件默认样式protected:// 鼠标进入事件void enterEvent(QEvent *event) override;// 鼠标离开事件void leaveEvent(QEvent *event) override;
};#endif // CSEARCHBUTTON_H
  • csearchbutton.cpp
#include "csearchbutton.h"
#include <string>using namespace std;CSearchButton::CSearchButton(QWidget *parent) : QPushButton(parent) {this->setAttribute(Qt::WA_StyledBackground);this->setFixedHeight(40);normalStyle();  // 设置默认样式
}// 鼠标进入按钮控件时触发的事件
void CSearchButton::enterEvent(QEvent *event) {string qss = R"(QPushButton{background-color:#148AFF;background-image: url(:/resources/search.png);background-repeat: no-repeat;background-position:left;background-origin:content;padding-left:15px; /*图片相对于左边的偏移*/text-align:right;  /*文本的对齐方式*/padding-right:15px; /*文本相对于右边的偏移*/border-radius:20px;color:#FFFFFF;font-family: \"Microsoft YaHei\";font-size: 20px;})";this->setStyleSheet(QString::fromStdString(qss));this->setFixedWidth(130);this->setText(u8"搜全网");
}// 鼠标离开按钮控件时触发的事件
void CSearchButton::leaveEvent(QEvent *event) {normalStyle();
}// 鼠标离开按钮控件时的 默认样式
void CSearchButton::normalStyle() {string qss = R"(QPushButton{background-color:#148AFF;background-image: url(:/resources/search.png);background-repeat: no-repeat;background-position: center;border-radius:20px;})";this->setStyleSheet(QString::fromStdString(qss));this->setFixedWidth(60);this->setText(u8"");
}

14. 自定义 QTabWidget 实现 tab 在左,文本水平

在这里插入图片描述

14.1 主窗口

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include "tabwidget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 创建 标签窗口 实例对象TabWidget *tabWidget = new TabWidget(this);// 分别插入三个标签页QWidget* w1 = new QWidget;w1->setStyleSheet("background-color:rgb(54,54,54)");// int insertTab(int index, QWidget *widget, const QString &);tabWidget->insertTab(0, w1, u8"参数设置");QWidget* w2 = new QWidget;w2->setStyleSheet("background-color:rgb(154,54,54)");tabWidget->insertTab(1, w2, u8"设备管理");QWidget* w3 = new QWidget;w3->setStyleSheet("background-color:rgb(154,54,154)");tabWidget->insertTab(2, w3, u8"设备管理");QHBoxLayout* hLay = new QHBoxLayout(this);hLay->addWidget(tabWidget);
}Widget::~Widget() {delete ui;
}

14.2 标签窗口

  • tabwidget.cpp
#include "tabwidget.h"
#include <string>using namespace std;TabWidget::TabWidget(QWidget *parent): QTabWidget(parent) {// 创建一个新的选项卡栏对象,并将其设置为当前的选项卡栏this->setTabBar(new TabBar);// 将选项卡位置设置为西边(左侧)this->setTabPosition(QTabWidget::West);// 注意在 QTabBar::tab 里不能设置 tab 的大小,否则自定义的 TabBar 无效string qss = R"(QTabWidget::pane {border-top:1px solid #EAEAEA;position:absolute;top:-0.1px;}QTabBar::tab {font-size:18px;font-family:Microsoft YaHei;font-weight:400;background:#FFFFFF;border:2px solid #FFFFFF;border-bottom-color:#FFFFFF;border-top-left-radius:4px;border-top-right-radius:4px;padding:2px;}QTabBar::tab:selected {color:#333333;border-color:#FFFFFF;border-bottom-color:#4BA4F2;}QTabBar::tab:!selected {color:#B2B2B2;border-color:#FFFFFF;border-bottom-color:#FFFFFF;})";this->setStyleSheet(QString::fromStdString(qss));
}

14.3 标签栏

  • tabbar.h
#ifndef TABBAR_H
#define TABBAR_H#include <QTabBar>class TabBar : public QTabBar {
public:TabBar(QWidget* parent = nullptr);QSize tabSizeHint(int index) const override;protected:void paintEvent(QPaintEvent *event) override;
};#endif // TABBAR_H
  • tabbar.cpp
#include "tabbar.h"
#include <QStylePainter>
#include <QStyleOptionTab>TabBar::TabBar(QWidget* parent) : QTabBar(parent) {}// 获取原始选项卡的大小建议,交换宽度和高度,再返回修改后的大小建议,表达了对选项卡大小的自定义设置
QSize TabBar::tabSizeHint(int index) const {QSize s = QTabBar::tabSizeHint(index);s.transpose();// 设置每个 tabBar 中 item 的大小// 注意在 qss QTabBar::tab 里不能设置 tab 的大小,否则自定义的 TabBar 无效s.rwidth() = 90;s.rheight() = 44;return s;
}// 绘制标签栏,将标签栏的形状绘制为横向的条形,标签内容垂直显示
void TabBar::paintEvent(QPaintEvent *event) {// QStylePainter 类用于 widget 窗口内部绘制 QStyle 元素QStylePainter painter(this);// QStyleOptionTab 类用于描述 标签栏 的参数QStyleOptionTab opt;for (int i = 0; i < count(); i++) {initStyleOption(&opt, i);  // i 为标签栏索引painter.drawControl(QStyle::CE_TabBarTabShape, opt);  // 绘制标签栏的形状painter.save();  // 保存当前绘图状态// 根据 opt.rect 的大小创建一个矩形 r,并将其移动到 opt.rect 的中心位置QSize s = opt.rect.size();s.transpose();QRect r(QPoint(), s);r.moveCenter(opt.rect.center());opt.rect = r;// 将绘图原点移到当前标签的中心位置,然后旋转 90 度,再将绘图原点移回初始位置QPoint c = tabRect(i).center();painter.translate(c);painter.rotate(90);painter.translate(-c);painter.drawControl(QStyle::CE_TabBarTabLabel, opt);  // 绘制标签栏的标签painter.restore();  // 恢复之前保存的绘图状态}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/136102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OpenCV实现图像:用OpenCV图像处理技巧之白平衡算法】

文章目录 概要加载样例图像统计数据分析White Patch Algorithm小结 概要 白平衡技术在摄影和图像处理中扮演着至关重要的角色。在不同的光照条件下&#xff0c;相机可能无法准确地捕捉到物体的真实颜色&#xff0c;导致图像呈现出暗淡、色调不自然或者褪色的效果。为了解决这个…

项目实战:中央控制器实现(2)-优化Controller,将共性动作抽取到中央控制器

1、FruitController FruitController已经和Web没有关系了&#xff0c;和Web容器解耦&#xff0c;可以脱离Web容器做单元测试 package com.csdn.fruit.controller; import com.csdn.fruit.dto.PageInfo; import com.csdn.fruit.dto.PageQueryParam; import com.csdn.fruit.dto.R…

5G与物联网应用:新一代网络技术融合开创新时代

5G与物联网应用&#xff1a;新一代网络技术融合开创新时代 随着信息技术的不断演进&#xff0c;5G和物联网作为新一代网络技术&#xff0c;正在引领我们走向一个更加智能化、互联互通的新时代。本文将分析5G与物联网应用的技术原理、应用场景与发展趋势&#xff0c;并探讨它们…

软件测试|selenium执行js脚本

JavaScript是运行在客户端&#xff08;浏览器&#xff09;和服务器端的脚本语言&#xff0c;允许将静态网页转换为交互式网页。可以通过 Python Selenium WebDriver 执行 JavaScript 语句&#xff0c;在Web页面中进行js交互。那么js能做的事&#xff0c;Selenium应该大部分也能…

软件测试|测试方法论—边界值

边界值分析法是一种很实用的黑盒测试用例方法&#xff0c;它具有很强的发现故障的能力。边界值分析法也是作为对等价类划分法的补充&#xff0c;测试用例来自等价类的边界。 这个方法其实是在测试实践当中发现&#xff0c;Bug 往往出现在定义域或值域的边界上&#xff0c;而不…

Godot4实现游戏的多语言版本

要在Godot 4中实现多语言版本的游戏&#xff0c;您需要按照以下几个步骤来设置和管理游戏文本以及可能的其他资源&#xff0c;如图像或声音。以下是根据官方文档和详细教程整理的简明指南&#xff1a; 准备翻译文件&#xff1a; Godot支持使用.csv文件或.po文件进行国际化​​…

基于单片机GP2D12测距-proteus仿真-源程序

基于51单片机红外测距-proteus仿真-源程序 一、系统方案 本设计采用51单片机作为主控器&#xff0c;液晶1602显示&#xff0c;GP2D12采集距离值&#xff0c;按键设置报警阀值&#xff0c;测量值超过阀值&#xff0c;蜂鸣器报警。 二、硬件设计 原理图如下&#xff1a; 三、单…

Day45 力扣动态规划 : 1143.最长公共子序列 |1035.不相交的线 | 53. 最大子序和

Day45 力扣动态规划 : 1143.最长公共子序列 &#xff5c;1035.不相交的线 &#xff5c; 53. 最大子序和 1143.最长公共子序列第一印象看完题解的思路实现中的困难感悟代码 1035.不相交的线第一印象感悟代码 53. 最大子序和第一印象dp递推公式初始化遍历顺序 实现中的困难感悟代…

数字政府!3DCAT实时云渲染助推上海湾区数字孪生平台

数字孪生&#xff0c;是一种利用物理模型、传感器数据、运行历史等信息&#xff0c;在虚拟空间中构建实体对象或系统的精确映射&#xff0c;从而实现对其全生命周期的仿真、优化和管理的技术。数字孪生可以应用于各个领域&#xff0c;如工业制造、智慧城市、医疗健康、教育培训…

原厂可调漏电继电器 LLJ-125F Φ45导轨安装可选面板安装

LLJ-F(S)系列漏电继电器 原厂漏电继电器 LLJ-125F Φ45 导轨安装 系列型号&#xff1a; LLJ-10F(S)漏电继电器LLJ-15F(S)漏电继电器LLJ-16F(S)漏电继电器 LLJ-25F(S)漏电继电器LLJ-30F(S)漏电继电器LLJ-32F(S)漏电继电器 LLJ-60F(S)漏电继电器LLJ-63F(S)漏电继电器LLJ-80F(S)…

渲染管线详解

光栅化的渲染管线一般分为三大阶段&#xff1a;应用程序阶段->几何阶段->光栅化阶段 也可以四大阶段&#xff1a; 应用程序阶段->几何阶段->光栅化阶段->逐片元操作阶段 更详细的流程如下&#xff1a; Vertex Specification&#xff08;顶点规范化&#xff09…

一文搞定多端开发,做全栈大牛 附三大企业实战项目

一个功能三套代码 一改需求就是加不完的班&#xff1f; 不存在的&#xff0c;告别改改改 拥抱多端开发 一套代码搞定多个平台 高效开发&#xff1a;一套代码&#xff0c;多端通用 根据统计数据&#xff0c;全球移动设备用户数已经超过了50亿。随着智能手机、平板电脑等移动…

JSON——数组语法

一段JSON可能是以 ”{“ 开头 也可能仅包含一段JSON数组 如下 [ { "name" : "hello,world"}, {"name" : "SB JSON”}&#xff0c; {“name” : "SB互联网房地产CNM“}&#xff0c; ] 瞧&#xff0c;蛋疼不...CJSON过来还是得搜下网…

【ES专题】Logstash与FileBeat详解以及ELK整合详解

目录 前言阅读对象阅读导航前置知识笔记正文一、ELK架构1.1 经典的ELK1.2 整合消息队列Nginx架构 二、LogStash介绍2.1 Logstash核心概念2.1.1 Pipeline2.1.2 Event2.1.3 Codec (Code / Decode)2.1.4 Queue 2.2 Logstash数据传输原理2.3 Logstash的安装&#xff08;以windows为…

Python tkinter用iconphoto方法修改窗口标题的图片

修改Python Tkinter窗口的标题图片&#xff0c;可以使用PhotoImage、iconphoto方法。这个方法允许你设置窗口的图标。 运行结果 代码示例如下&#xff1a; import tkinter as tkroot Tk()# 加载图片&#xff0c;记住一定是要PNG图片 icon tk.PhotoImage(filephoto\\图片.pn…

python的format函数的用法及实例

目录 1.format函数的语法及用法 &#xff08;1&#xff09;语法&#xff1a;{}.format() &#xff08;2&#xff09;用法&#xff1a;用于格式化字符串。可以接受无限个参数&#xff0c;可以指定顺序。返回结果为字符串。 2.实例 &#xff08;1&#xff09;不设置位置&…

ChatGPT - 在ChatGPT中设置通用提示模板

文章目录 Prompt设置验证 Prompt VERBOSITY: 我可能会使用 V[0-3] 来定义代码的详细程度&#xff1a;V0 简洁明了 V1 简练 V2 详细 V3 非常详细&#xff0c;附有例子助理回应 您是用户问题背景下的主题专家。我们一步一步来&#xff1a;除非您只是回答一个简短的问题&#xff…

探索环保葡萄酒之生物动力

根据生物动力农业和园艺协会的说法&#xff0c;生物动力农业是“一种精神-伦理-生态的农业、园艺、食品生产和营养方法。”生物动力农民将他们的农场或葡萄园视为一个坚固的有机体&#xff0c;一个自我维持的生态系统。这些农业哲学和实践在整个农业周期中应用了一种整体方法。…

计算机毕业设计基于springboot+java+vue的健身房课程预约信息网站

运行环境 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven 项目介绍 本健身网…

C/C++轻量级并发TCP服务器框架Zinx-游戏服务器开发005:守护进程与进程监控

文章目录 1 守护进程1.1 进程组和会话1.2 会话的相关概念1.3 守护进程的概念1.4 守护线程的特点1.5 守护进程创建的基本步骤1.6 本项目守护进程的实现 2 进程监控2.1 进程监控的实现 1 守护进程 1.1 进程组和会话 进程除了有进程的PID之外还有一个进程组&#xff0c;进程组是…