Qt Doc.предоставляет пример для «непрямоугольных» виджетов - Пример Shaped Clock .
(Un-) К счастью, я запомнил это не раньше, чем запустил свой собственный образец.
Я начал в Qt doc.with
Вызывает отображение только тех пикселей виджета, для которых bitmap имеет соответствующий 1 бит.Если область включает пиксели за пределами rect () виджета, элементы управления оконной системой в этой области могут или не могут быть видны, в зависимости от платформы.
Обратите внимание, что этот эффект может бытьмедленный, если область особенно сложная.
Следующий код показывает, как изображение с альфа-каналом может использоваться для создания маски для виджета:
QLabel topLevelLabel;
QPixmap pixmap(":/images/tux.png");
topLevelLabel.setPixmap(pixmap);
topLevelLabel.setMask(pixmap.mask());
Метка, показанная этимКод маскируется с помощью содержащегося в нем изображения, создавая впечатление, что изображение неправильной формы рисуется непосредственно на экране.
Замаскированные виджеты получают события мыши только на своих видимых частях.
См. Также mask () , clearMask () , windowOpacity () и Пример формы часов .
(Когда я читал это, я все же пропустил ссылку на пример.)
Сначала я подготовил для себя подходящее растровое изображение - dialog-error.png
:
, для которых я конвертировал SVG из одного из моих приложений.
Я пытался применить его к QPushButton
в виде значка и маски.Это выглядело очень странно.Я не совсем уверен, в чем именно проблема: - используя респ.QPushButton
как виджет верхнего уровня (т.е. главное окно) - тот факт, что QPushButton
рендеринг иконок и маска могут не совпадать в отношении положения или размера.
Не копая глубже, я изменил код и исправил обе проблемыв следующей попытке:
- создание производной кнопки (как описано в OP)
- с использованием кнопки в качестве виджета без верхнего уровня.
Это сработало в ближайшее время,Я добавил некоторый код, чтобы сделать эффект более очевидным:
- обработчик события нажатия кнопки мыши для главного окна, чтобы показать, считается ли фигура правильным
- обработчик сигнала, чтобы показать, нажимает ли кнопка(в форме) получены правильно.
Итак, я пришел к следующему примеру - testQPushButtonMask.cc
:
#include <QtWidgets>
class MainWindow: public QWidget {
public:
explicit MainWindow(QWidget *pQParent = nullptr):
QWidget(pQParent)
{ }
virtual ~MainWindow() = default;
MainWindow(const MainWindow&) = delete;
MainWindow& operator=(const MainWindow&) = delete;
protected:
virtual void mousePressEvent(QMouseEvent *pQEvent) override;
};
void MainWindow::mousePressEvent(QMouseEvent *pQEvent)
{
qDebug() << "MainWindow::mousePressEvent:" << pQEvent->pos();
QWidget::mousePressEvent(pQEvent);
}
class RoundButton: public QPushButton {
private:
QPixmap _qPixmap;
public:
RoundButton(const QPixmap &qPixmap, QWidget *pQParent = nullptr):
QPushButton(pQParent),
_qPixmap(qPixmap)
{
setMask(_qPixmap.mask());
}
virtual ~RoundButton() = default;
RoundButton(const RoundButton&) = delete;
RoundButton& operator=(const RoundButton&) = delete;
virtual QSize sizeHint() const override;
protected:
virtual void paintEvent(QPaintEvent *pQEvent) override;
};
QSize RoundButton::sizeHint() const { return _qPixmap.size(); }
void RoundButton::paintEvent(QPaintEvent*)
{
QPainter qPainter(this);
const int xy = isDown() * -2;
qPainter.drawPixmap(xy, xy, _qPixmap);
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
QPixmap qPixmap("./dialog-error.png");
// setup GUI
MainWindow qWin;
qWin.setWindowTitle(QString::fromUtf8("QPushButton with Mask"));
QVBoxLayout qVBox;
RoundButton qBtn(qPixmap);
qVBox.addWidget(&qBtn);
qWin.setLayout(&qVBox);
qWin.show();
// install signal handlers
QObject::connect(&qBtn, &RoundButton::clicked,
[](bool) { qDebug() << "RoundButton::clicked()"; });
// runtime loop
return app.exec();
}
Соответствующий файл проекта Qt testQPushButtonMask.pro
SOURCES = testQPushButtonMask.cc
QT += widgets
Скомпилировано и протестировано на cygwin64 :
$ qmake-qt5 testQPushButtonMask.pro
$ make && ./testQPushButtonMask
Qt Version: 5.9.4
MainWindow::mousePressEvent: QPoint(23,22)
MainWindow::mousePressEvent: QPoint(62,24)
MainWindow::mousePressEvent: QPoint(62,61)
MainWindow::mousePressEvent: QPoint(22,60)
RoundButton::clicked()
Относительно выхода:
- Я нажал на четыре угла кнопки.
- Я нажал на центр кнопки.