c++ - 按下QToolButton时如何更改QAction的图标图像
问题描述
我更改了 QToolButton 的样式表,但它不起作用,请帮忙
- 我想在鼠标悬停时删除 QToolButton 的边框。我更改了 QToolButton 的样式表
QToolButton:hover{ 边框:无;}
QToolButton:pressed{ 边框:无;}
但它显示边框底部和按钮像图像一样向左移动
解决方案
对于“热身”,我从QPushButton
. 此类提供信号pressed()
,released()
可用于更改图标。
testQPushButtonDownUp.cc
:
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// build UI
QIcon qIconBtn("dialog-info.svg");
QIcon qIconBtnDown("dialog-error.svg");
QPushButton qBtn(qIconBtn, QString::fromUtf8("Click Me."));
qBtn.show();
// install signal handlers
QObject::connect(&qBtn, &QPushButton::pressed,
[&qBtn, &qIconBtnDown]() { qBtn.setIcon(qIconBtnDown); });
QObject::connect(&qBtn, &QPushButton::released,
[&qBtn, &qIconBtn]() { qBtn.setIcon(qIconBtn); });
// runtime loop
return app.exec();
}
testQPushButtonDownUp.pro
:
SOURCES = testQPushButtonDownUp.cc
QT += widgets
在 Windows 10 上用cygwin64编译和测试:
$ qmake-qt5 testQPushButtonDownUp.pro
$ make && ./testQPushButtonDownUp
Qt Version: 5.9.4
这很容易。将其应用于QAction
有点复杂——QAction
只提供一个信号triggered()
。我没有检查它是否是为pressed()
or发出的released()
- 两个需要的信号之一肯定丢失了。
为了解决这个问题,我使用QAction::associatedWidgets()
了 which
返回已添加此操作的小部件列表。
扫描此列表以查找每个出现QToolButton
(来自QAbstractButton
以及QPushButton
和)提供相同信号的事件。
testQToolButtonDownUp.cc
:
#include <QtWidgets>
void connectAction(QAction &qCmd, const QIcon &qIconDown, const QIcon &qIconUp)
{
QList<QWidget*> pQWidgets = qCmd.associatedWidgets();
for (QWidget *pQWidget : pQWidgets) {
QToolButton *pQBtn = dynamic_cast<QToolButton*>(pQWidget);
if (!pQBtn) continue;
QObject::connect(pQBtn, &QToolButton::pressed,
[pQBtn, qIconDown]() { pQBtn->setIcon(qIconDown); });
QObject::connect(pQBtn, &QToolButton::released,
[pQBtn, qIconUp]() { pQBtn->setIcon(qIconUp); });
}
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// build UI
QToolBar qToolbar;
QIcon qIconBtn("dialog-info.svg");
QIcon qIconBtnDown("dialog-error.svg");
QAction qCmd(qIconBtn, QString::fromUtf8("Click Me."));
qToolbar.addAction(&qCmd);
qToolbar.show();
// install signal handlers
connectAction(qCmd, qIconBtnDown, qIconBtn);
// runtime loop
return app.exec();
}
testQToolButtonDownUp.pro
:
SOURCES = testQToolButtonDownUp.cc
QT += widgets
在 Windows 10 上的cygwin64中再次编译和测试:
$ qmake-qt5 testQToolButtonDownUp.pro
$ make && ./testQToolButtonDownUp
Qt Version: 5.9.4
这可行,但有点维护不友好 - 该函数必须在添加到所有小部件connectAction()
后调用。QAction
(为同一个实例重复调用它QAction
可能需要额外的努力来防止对同一个实例的重复信号处理程序QToolButton
。)
QToolButton
一旦这样的相关联的小部件自动连接 new s 会很好。QAction
已更改。我浏览了文档。上下寻找合适的东西——没有运气。我尝试了QAction::changed()
信号是否可以提供所需的行为(尽管文档给出的希望较小)但它没有用。
最后,我决定扭转局面——即检测何时将 aQAction
添加到 aQToolButton
中。但是,在我的代码中,我添加了QAction
aQToolBar
和 resp。QToolButton
自动出现。因此,我制作了一个事件过滤器,安装到qApp
. 此事件过滤器将接收任何事件,因此可以很好地检测QAction
添加到 any 的任何事件QWidget
。另外,我要做的就是为需要向下图标的QAction
s 和s 过滤这些事件。QToolButton
testQActionDownUp.cc
:
#include <set>
#include <QtWidgets>
class Action: public QAction {
public:
class FilterSingleton: public QObject {
private:
std::set<Action*> _pActions;
public:
FilterSingleton(): QObject()
{
qApp->installEventFilter(this);
}
~FilterSingleton() { qApp->removeEventFilter(this); }
FilterSingleton(const FilterSingleton&) = delete;
FilterSingleton& operator=(const FilterSingleton&) = delete;
void addAction(Action *pAction)
{
_pActions.insert(pAction);
}
bool removeAction(Action *pAction)
{
_pActions.erase(pAction);
return _pActions.empty();
}
protected:
virtual bool eventFilter(QObject *pQObj, QEvent *pQEvent) override;
};
private:
static FilterSingleton *_pFilterSingleton;
private:
QIcon _qIcon, _qIconDown;
public:
Action(
const QIcon &qIcon, const QIcon &qIconDown, const QString &text,
QObject *pQParent = nullptr);
~Action();
Action(const Action&) = delete;
Action& operator=(const Action&) = delete;
private:
void addToolButton(QToolButton *pQBtn)
{
QObject::connect(pQBtn, &QToolButton::pressed,
[pQBtn, this]() { pQBtn->setIcon(_qIconDown); });
QObject::connect(pQBtn, &QToolButton::released,
[pQBtn, this]() { pQBtn->setIcon(_qIcon); });
}
};
bool Action::FilterSingleton::eventFilter(QObject *pQObj, QEvent *pQEvent)
{
if (QToolButton *pQBtn = dynamic_cast<QToolButton*>(pQObj)) {
if (pQEvent->type() == QEvent::ActionAdded) {
qDebug() << "Action::eventFilter(QEvent::ActionAdded)";
QAction *pQAction = ((QActionEvent*)pQEvent)->action();
if (Action *pAction = dynamic_cast<Action*>(pQAction)) {
pAction->addToolButton(pQBtn);
}
}
}
return QObject::eventFilter(pQObj, pQEvent);
}
Action::FilterSingleton *Action::_pFilterSingleton;
Action::Action(
const QIcon &qIcon, const QIcon &qIconDown, const QString &text,
QObject *pQParent):
QAction(qIcon, text, pQParent),
_qIcon(qIcon), _qIconDown(qIconDown)
{
if (!_pFilterSingleton) _pFilterSingleton = new FilterSingleton();
_pFilterSingleton->addAction(this);
}
Action::~Action()
{
if (_pFilterSingleton->removeAction(this)) {
delete _pFilterSingleton;
_pFilterSingleton = nullptr;
}
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// build UI
QMainWindow qWin;
QToolBar qToolbar;
QIcon qIconBtn("dialog-info.svg");
QIcon qIconBtnDown("dialog-error.svg");
Action qCmd(qIconBtn, qIconBtnDown, QString::fromUtf8("Click Me."));
qToolbar.addAction(&qCmd);
qWin.addToolBar(&qToolbar);
QToolBar qToolbar2;
qWin.setCentralWidget(&qToolbar2);
qWin.show();
QTimer qTimer;
qTimer.setInterval(5000); // 5000 ms = 5s
qTimer.start();
// install signal handlers
int i = 0;
QObject::connect(&qTimer, &QTimer::timeout,
[&i, &qToolbar2, &qCmd]() {
if (++i & 1) qToolbar2.addAction(&qCmd);
else qToolbar2.removeAction(&qCmd);
});
// runtime loop
return app.exec();
}
有一个类Action
(派生自QAction
)将所有必要的东西捆绑在一起。该类在Action
内部使用一个单例(类Action::FilterSingleton
),以便在所有实例之间共享一个事件过滤器Action
。
AQTimer
用于Action qCmd
定期添加/删除样本,QToolBar qToolbar2
以测试/演示自动管理是否正常工作。
testQActionDownUp.pro
:
SOURCES = testQActionDownUp.cc
QT += widgets
在 Windows 10 上的cygwin64中再次编译和测试:
$ qmake-qt5 testQActionDownUp.pro
$ make && ./testQActionDownUp
Qt Version: 5.9.4
推荐阅读
- java - 编译失败:子进程失败
- java - 拆分空格分隔的字符串,忽略单引号内的空格
- html - 为什么我的“标题”和“主要”(HTML)之间有边距/空格?
- mysql - 如何计算一组单词以任意顺序出现在一列中的次数?
- python - pytest 夹具生成器何时继续使用,范围是否会影响这一点?
- matlab - 如何在 matlab 中免费安装 mosek 求解器?
- eiffel - 编译交通库的问题
- angular - Angular Http 与 HttpClient
- ruby-on-rails - 如何在 ruby on rails 中执行 .sh 文件
- php - 如何为目录中的所有 PHP 导入设置 ROOT?