// 重新设定按钮的位置
pBtnTest->move(100, 50);// 重新设定按钮的大小
pBtnTest->resize(80, 50);// 设置按钮的位置和大小
pBtnTest->setGeometry(100, 50, 80, 50);
pBtnTest->setFont(QFont("宋体", 18));
pBtnTest->setText("我是一个很长很长很长的文本");// adjustSize():自动调整控件的大小,以适应其内容;
pBtnTest->adjustSize();
// 设置控件获取焦点
pBtnTest->setFocus();// 获取控件是否具有焦点;如果控件有焦点,返回 true;
bool b = pBtnTest->hasFocus();
qDebug() << b;// 清除控件的焦点
pBtnTest->clearFocus();
pBtnTest->setCursor(QCursor(Qt::BusyCursor));
// 禁用控件
pBtnTest->setDisabled(true);// 启用控件
pBtnTest->setEnabled(true);
pBtnTest->setFlat(true);
pBtnTest->setDefault(true);
// 设置按钮上显示的图标
pBtnTest->setIcon(QIcon(":/Image/Luffy.png"));// 设置图标的大小
pBtnTest->setIconSize(QSize(24, 24));
auto earMonitorSwitch = new QPushButton(this);
earMonitorSwitch->setCheckable(true);
earMonitorSwitch->setStyleSheet("QPushButton{border-image:url(./resource/audio/audio_setting/btn_earmonitor_close.png);}"
"QPushButton:checked{border-image:url(./resource/audio/audio_setting/btn_earmonitor_open.png);}");
pBtnTest->setStyleSheet("QPushButton{border-image:url(./resource/audio/audio_setting/close_normal.png);border:none;}""QPushButton:hover{border-image:url(./resource/audio/audio_setting/close_hover.png);}""QPushButton:pressed{border-image:url(./resource/audio/audio_setting/close_press.png);}");
// 定义初始样式集合
QStringList list;
list.append("color:white"); // 前景色
list.append("background-color:rgb(85,170,255)"); // 背景色
list.append("border-style:outset"); // 边框风格
list.append("border-width:5px"); // 边框宽度
list.append("border-color:rgb(10,45,110)"); // 边框颜色
list.append("border-radius:20px"); // 边框倒角
list.append("font:bold 30px"); // 字体
list.append("padding:4px"); // 内边距// 设置按钮初始样式
pBtnTest->setStyleSheet(list.join(';')); // 按钮按下时修改样式
list.replace(6, "font:bold 35px");
connect(pBtnTest, &QPushButton::pressed, [=](){pBtnTest->setStyleSheet(list.join(';'));
});// 按钮弹起时恢复样式
list.replace(6, "font:bold 30px");
connect(pBtnTest, &QPushButton::released, [=](){pBtnTest->setStyleSheet(list.join(';'));
});
auto button = new QPushButton(u8"按钮");
button->setContextMenuPolicy(Qt::ActionsContextMenu);
if (type == AccomSoundType::mySound)
{auto deleteAction = new QAction(left);deleteAction->setText(u8"删除");connect(deleteAction, &QAction::triggered, this, [=]() {trace("删除");});button->addAction(deleteAction);
}
// 菜单
QMenu *pMenu = new QMenu(this);
pMenu->addAction(QString::fromLocal8Bit("设置"));
pMenu->addAction(QString::fromLocal8Bit("版本检测"));
pMenu->addSeparator();
pMenu->addAction(QString::fromLocal8Bit("关于我们"));
pMenu->addAction(QString::fromLocal8Bit("退出"));// 按钮
QPushButton *pButton = new QPushButton(this);
pButton->setText(QString::fromLocal8Bit("主菜单"));// 设置菜单
pButton->setMenu(pMenu);
上面的方法会让按钮显示一个下拉的三角形图标,如果想取消这个图片可以用 qss 去除:
QPushButton::menu-indicator#btn_room_setting{image:none;
}
实现部分
void MainWidget::initBtnMeun()
{this->setStyleSheet("background-color:rgb(54,54,54)");QMenu *fileMenuItems = new QMenu;//菜单添加iconfileMenuItems->setIcon(QIcon(":/resources/file.png"));fileMenuItems->setTitle(u8"文件");fileMenuItems->setStyleSheet(QString::fromStdString(menuItemQss));QList acList;// action添加iconQAction *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);//多级子菜单项acList << openFileAc << openFloderAc << openUrlAc;fileMenuItems->addActions(acList);QMenu *pMenu = new QMenu; //主菜单pMenu->addMenu(fileMenuItems);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();QMenu *setMenuItems = new QMenu;setMenuItems->setTitle(u8"设置");setMenuItems->setIcon(QIcon(":/resources/set.png"));QList setList;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();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));
}
qss 的实现
#ifndef QSS_H
#define QSS_H#include 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
两个关键类如下:
CVolumeButton
/*音量调节按钮功能:1. 鼠标悬浮到音量时显示slider dialog2. 点击时mute注意问题:重写按钮类,样式表无效
*/#pragma once#include
#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;
};
#include "CVolumeButton.h"
#include
#include
#include
#include
#include 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);QStyleOptionButton option;initStyleOption(&option);p.drawControl(QStyle::CE_PushButton, option);
}void CVolumeButton::enterEvent(QEvent* event)
{if (!m_pVolumeSliderDlg)m_pVolumeSliderDlg = new CVolumeSliderDialog(this);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{if (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 > 按钮宽30QRect area(rect3.left(), rect3.top(), rect2.width(), p2.y() + rect1.height() - rect3.top()); //左上宽高if (!area.contains(p1)){m_pVolumeSliderDlg->hide();}}}else{killTimer(m_timerId);}
}
CVolumeSliderDialog 类
#ifndef CVOLUMESLIDERDIALOG_H
#define CVOLUMESLIDERDIALOG_H#include
#include 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
#include "CVolumeSliderDialog.h"
#include
#include
#include //注意由于此类使用了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 : 悬浮是显示,离开时消失setStyleSheet("QDialog{background-color: rgba(54, 54, 54, 0.5);}"); //0.5表示透明度,0表示全透明、1表示不透明;也可以使用百分百表示如: frm->setStyleSheet(“QFrame{background-color: rgba(255, 0, 0, 50%);}”);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);
}
实现部分
void MainWidget::initHoteBtnMenu()
{QHBoxLayout *pHlay = new QHBoxLayout(this);CVolumeButton* pVolumeButton = new CVolumeButton(this);pHlay->addWidget(pVolumeButton);}
源码实现