QT绘图常用功能 & Trick: QT带背景图和文字的QPushButton制作

绘图

QPixmap类:绘图

  • 使用QLabel或QAbstractButton的子类之一(例如QPushButton和QToolButton),可以轻松地在屏幕上显示QPixmap
    • QLabel具有pixmap属性,而QAbstractButton具有icon属性
# 创建一个空的 pixmap, 并设定其尺寸
self.pix = QtGui.QPixmap(300, 300)  # 默认填充颜色为黑色
self.pix.fill('red') # 修改填充颜色为红色
self.setPixmap(self.pix) # 设定 QLabel 的 pixmap

QPixmap::scaled(): 根据给定的尺寸来放大缩小QPixmap

QPixmap::scaled(const QSize & size, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) const
  • IgnoreAspectRatio 矩形框有多大,图片就缩放成多大,不限制原图片的长宽比
  • KeepAspectRatio 保持原图片的长宽比,且不超过矩形框的大小
  • KeepAspectRatioByExpanding 根据矩形框的大小最大缩放图片

QPixmap为QLabel设置背景图片

QPixmap pixmap = QPixmap(":/xxx/xx.png").scaled(labelName->rect().size(), aspectMode);
ui->label->setPixmap(pixmap);

QLineEdit的样式只能通过QPalette

QPixmap VS QImage

  • QPixmap依赖于硬件,QImage不依赖于硬件。
  • QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O、图片访问和像素修改而设计的。
    • 当图片小的情况下,直接用QPixmap进行加载,画图时无所谓,当图片大的时候如果直接用QPixmap进行加载,会占很大的内存,一般一张几十K的图片,用QPixmap加载进来会放大很多倍,所以一般图片大的情况下,用QImage进行加载,然后转乘QPixmap用户绘制。QPixmap绘制效果是最好的。

paintEvent(QPaintEvent*) 绘图

注意:在编译器中resource中要包含该图片文件

  • 主要提供在窗体或者其他绘图设备上进行绘图的功能。
  • QWidget类中的虚函数,用于ui的绘制,会在多种情况下被其他函数自动调用
  • 常用函数:
    • drawXXX()函数,用于绘制图形、文字和路径等;
    • fillXXX()函数,用于填充,可在指定区域内进行填充;
    • brush()和pen() 笔刷和钢笔的相关操作
// 只要是继承自QWidget都会自动调用
void QWidget::paintEvent(QPaintEvent *event){
    QPixmap pixmap = QPixmap(":/Resource/images/LoginImg/BG.png").scaled(this->size());  // 设置为整个页面的背景
    QPainter painter(this);
    painter.drawPixmap(rect(), pixmap, QRect());
}

当发生一下情况时会产生绘制事件并调用paintEvent()函数:

  1. 在窗口部件第一次显示时,系统会自动产生一个绘图事件,从而强制绘制这个窗口部件。
  2. 重新调整窗口部件的大小时,系统也会产生一个绘制事件。
  3. 当窗口部件被其他窗口部件遮挡,然后又再次显示出来的时候,就会对那些隐藏的区域产生一个绘制事件。
    同时可以调用QWidget::update()或者QWidget::repaint()来强制产生一个绘制事件。二者的区别是:
    repaint()函数会强制产生一个即时的重绘事件,而update()函数只是在Qt下一次处理事件时才调用一次绘制事件。
    如果多次调用update(),Qt会把连续多次的绘制事件压缩成一个单一的绘制事件,这样可避免闪烁现象。

QIcon

大小设置

QPalette类:调色板

  • 对话框或控件的调色板
  • 管理控件或窗体的所有颜色信息,每个窗体或控件都包含一个QPalette对象,在显示时按照它的QPalette对象中对各部分各状态下的颜色的描述来进行绘制。

ColorGroup

QPalette::Disabled 不可用状态
QPalette::Active 活跃状态(获得焦点)
QPalette::Inactive 不活跃状态(未获得焦点)

ColorRole

QPalette::Window 一个常规的背景颜色
QPalette::Background 这个值是废弃的,使用window代替
QPalette::WindowText 一个一般的前景颜色
QPalette::Foreground 这个值是废弃的,使用windowText代替.
QPalette::Base 最长使用来作为text背景颜色为整个widget,但是也能被用来为其他的绘画,像combobox的上下清单的背景和工具栏句柄。它通常是白的或者其他亮的颜色.
QPalette::AlternateBase 被用来作为轮流的背景颜色,轮流的行颜色
QPalette::ToolTipBase 被用来作为背景颜色为QToolTip和QWhatsThis。工具尖端使用QPalette不活跃的颜色组,因为工具尖端不是活跃的窗口.
QPalette::ToolTipText 被用来作为前景颜色为QToolTip和QWhatsThis.工具尖端使用QPalette不活跃的颜色组,因为工具尖端不是活跃的窗口.
QPalette::Text 前景颜色使用base.这通常和windowText相同,它一定提供好的对比window和base
QPalette::Button button背景颜色。这个背景颜色能是不同于window作为一些风格,要求一个不同的背景颜色作为button
QPalette::ButtonText 一个前景颜色被用来作为button颜色.
QPalette::BrightText 一个text颜色是很不同于windowText,很好的对比与dark。典型的被用来为text,需要被画,在text或者windowText将给差的对比,就像在按下的button。注意text颜色能被用来为事情,而不只是单词;text颜色通常被用来为text,但是他是相当普通的使用text颜色角色为行,图标,等等。

QBrush画刷

 //注意要先调用setAutoFillBackground  
textEdit->setAutoFillBackground(true);  
QPalette palette;  

//设置QTextEdit文字颜色  
palette.setBrush(QPalette::Active, QPalette::Text, QBrush(Qt::yellow));  

//设置QTextEdit背景色  
palette.setBrush(QPalette::Active, QPalette::Base, QBrush(Qt::red));  

textEdit->setPalette(palette);  

常用设置颜色方法

  • void QPalette::setBrush ( ColorRole role, const QBrush & brush )
    改变所有组下指定角色role的画刷颜色值。
  • void QPalette::setBrush ( ColorGroup group, ColorRole role, const QBrush & brush )
    改变指定组group下的指定角色role的画刷颜色值。
  • void QPalette::setColor ( ColorRole role, const QColor & color )
    改变所有组下指定角色role的颜色值。
  • void QPalette::setColor ( ColorGroup group, ColorRole role, const QColor & color )
    改变指定组group下指定角色role的颜色值。

ps: 在以上代码之前,必须先调用函数 void setAutoFillBackground ( bool enabled );设置窗体运行自动填充、对话框和控件的背景色

QLineEdit设置背景颜色

QPalette palette(ui->lineEdit->palette());
palette.setBrush(QPalette::Base, QBrush(QColor(255,0,0,0)));  // 设置背景透明,QColor最后一个参数为透明度
palette.setBrush(QPalette::Text, QBrush(QColor(255,255,255)));  // 设置文字颜色
edtName->setPalette(palette);
edtName->setFrame(false);  // 取消边框

登录按钮制作 Trick

在图片上加文字

先用QImage创建图片,再用QPixmap显示图片

使用setWhatsThis可以获取到不同QPushButton的属性

https://blog.csdn.net/qianqiaoqianqi/article/details/110848718

QPixmap QPixmap::fromImage(QImage(":/xxx/btn-登录.png"));
QPainter painter(&pixmap);
//painter.begin(&pixmap);
painter.setPen(Qt::white);

QFont font = painter.font();
font.setPixelSize(12);
font.setBold(true);
font.setLetterSpacing(QFont::PercentageSpacing, 120);
font.setFamily("Microsoft YaHei");
painter.setFont(font);

painter.drawText(pixmap.rect(), Qt::AlignCenter, QString("登录").toStdString().c_str());  // setWhatsThis

//    painter.setPen(QPen(Qt::green,3));
//    painter.drawRect(pixmap.rect());
//    painter.setPen(QPen(Qt::red,3));
//    painter.drawRect(btnName->rect());

这样我们得到的pix图片就是已经在原图片上添加了文本的,新生成的一张图了,再根据需求直接调用pix

将带文字的图片作为pix给QPushButton显示

btnName->setIcon(QIcon(pixmap));
btnName->setIconSize(ui->pushButton_login->rect().size());

btnName->setFlat(true);
btnName->setFocusPolicy(Qt::NoFocus);
// btnName->setStyleSheet("border:none");

常见问题

p.load()将图片加载到缓冲区QPixmapCache中,当你加载图片二是,图片一并没有被覆盖,此时缓冲区内有图片一和图片二,当你再次加载图片一时,缓冲区里有了,所以p.load()直接返回true;但是图片仍是图片二,所以不能显示回图片一。

解决方案:

  • 直接定义局部变量,这样每次都是新的缓冲区;
  • 当再次加载图片时,先将缓冲区清空, QPixmapCache::clear();然后再加载;
  • 在初始化函数里写:QPixmapCache::setCacheLimit(1);设置缓冲区内只能放一张图片

为继承自QWidget的界面添加样式: 未重写paintEvent(QPaintEvent *e)函数

https://doc.qt.io/qt-5/stylesheet-reference.html中有如下介绍:
Supports only the background, background-clip and background-origin properties.
If you subclass from QWidget, you need to provide a paintEvent for your custom QWidget as below:

void CustomWidget::paintEvent(QPaintEvent *)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

The above code is a no-operation if there is no stylesheet set.
Warning: Make sure you define the Q_OBJECT macro for your custom widget.

They're expensive, buggy and unmaintained; basically a stop-gap and a quick'n'dirty way to customize look and feel. The only complete way to get non-native look and feel is subclassing QStyle. Moreover, people tend to abuse them even to get some basic effects (such as changing background color or similar, which can be obtained much more cheaply by changing the widget's palette or by a custom paint event).

解决方案:

  1. 添加paintEvent(QPaintEvent *){}
    https://www.dazhuanlan.com/wanghttt812/topics/1173634

  2. Setting Qt::WA_StyledBackground to true only works if you remember to add Q_OBJECT to your class. With these two changes you don’t need to reimplement paintEvent.

setAttribute(Qt::WA_StyledBackground, true)

另外还需要注意的是:如果在 Qt Designer 中改变样式表来设置背景图的话,最好别用 objectName 来作为 QSS 的选择器。因为提升后的 widget 对象名已经改变!可以用类名作为选择器。

https://stackoverflow.com/questions/7276330/qt-stylesheet-for-custom-widget
https://beyondyuanshu.github.io/2019/09/16/why-does-qwidget-disappear-after-promoted.html

按键加图片文字

BtnYes = new QToolButton(this);
BtnYes->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
QPixmap yesPix(":/res/yesBtn.png");
BtnYes->setIcon(yesPix);
BtnYes->setIconSize(QSize(26, 24));

资料

按钮添加图片的几种方法

https://baijiahao.baidu.com/s?id=1625725042120987082&wfr=spider&for=pc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值