自学内容网 自学内容网

Qt——升级系列(Level Eight):界面优化

目录

QSS

  背景介绍

  基本语法

  QSS设置方式

        指定控件样式设置

        全局样式设置

        从文件加载样式表

        使用Qt Designer 编辑样式

  选择器

        选择器概况

        子控件选择器

        伪类选择器

  样式属性

        盒模型

  控件样式示例

        按钮

        复选框、单选框

        输入框

        列表

        菜单栏

        登录界面

绘图

  基本概念

  绘制各种形状

        绘制线段

        绘制矩形

        绘制圆形

        绘制文本

        设置画笔

        设置画刷

  绘制图片

        绘制简单图片

        缩放图片

        旋转图片

  特殊的画图设备

        QPixmap

        QImage

        QPicture

QSS

  背景介绍

        在⽹⻚前端开发领域中, CSS 是⼀个⾄关重要的部分. 描述了⼀个⽹⻚的 "样式". 从⽽起到对⽹⻚美化的作⽤.

        Qt 仿照 CSS 的模式, 引⼊了 QSS, 来对 Qt 中的控件做出样式上的设定, 从⽽允许程序员写出界⾯更好看代码.

        QSS(Qt Style Sheets)是Qt中用于定义和定制界面样式的一种机制。类似于CSS(Cascading Style Sheets),QSS允许开发者通过简单的语法规则为Qt应用程序的控件(如窗口、按钮、标签等)设置样式,从而实现界面的美化和个性化定制。

注意:如果通过 QSS 设置的样式和通过 C++ 代码设置的样式冲突, 则 QSS 优先级更⾼.

  基本语法

        对于 CSS 来说, 基本的语法结构⾮常简单.

选择器 
{
    属性名: 属性值; 
}

        QSS 沿⽤了这样的设定.  

选择器 
{
    属性名: 属性值; 
}

 其中:
        • 选择器 描述了 "哪个 widget 要应⽤样式规则".
        • 属性 则是⼀个键值对, 属性名表⽰要设置哪种样式, 属性值表⽰了设置的样式的值.

下面是一个典型的 Qt 程序中用于设置界面样式的示例:

Widget::Widget(QWidget *parent)
    : QWidget(parent),  // 构造函数的初始化列表,将 parent 作为父类的构造函数参数
    ui(new Ui::Widget)  // 创建了 Ui::Widget 对象的实例,通常是在 Qt Designer 生成的 UI 类
{
    ui->setupUi(this);  // 调用 setupUi 函数初始化界面,将当前 Widget 作为参数传递

    // 为 QPushButton 设置样式表,使其文字颜色为红色
    ui->pushButton->setStyleSheet("QPushButton { color: red; }");
}

  QSS设置方式

        指定控件样式设置

        QWidget 中包含了 setStyleSheet ⽅法, 可以直接设置样式.上述代码我们已经演⽰了上述设置⽅式.

        另⼀⽅⾯, 给指定控件设置样式之后, 该控件的⼦元素也会受到影响.

代码⽰例: ⼦元素受到影响

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个垂直布局管理器
    QVBoxLayout layout(&parentWidget);

    // 创建一个 QPushButton 作为父级控件的子元素
    QPushButton *button1 = new QPushButton("Button 1", &parentWidget);
    layout.addWidget(button1);

    // 创建另一个 QPushButton 作为父级控件的子元素
    QPushButton *button2 = new QPushButton("Button 2", &parentWidget);
    layout.addWidget(button2);

    // 设置父级控件的样式表,同时会影响其所有子元素
    parentWidget.setStyleSheet("QWidget { background-color: lightblue; }"
                               "QPushButton { color: white; background-color: green; }");

    parentWidget.show();

    return app.exec();
}

代码结果:

        全局样式设置

        还可以通过 QApplication 的 setStyleSheet ⽅法设置整个程序的全局样式.

全局样式优点:
        • 使同⼀个样式针对多个控件⽣效, 代码更简洁.
        • 所有控件样式内聚在⼀起, 便于维护和问题排查.

代码⽰例: 使⽤全局样式

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 设置全局样式表
    QString globalStyleSheet = "QWidget { background-color: lightblue; }"
                               "QPushButton { color: white; background-color: green; }";
    app.setStyleSheet(globalStyleSheet);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个垂直布局管理器
    QVBoxLayout layout(&parentWidget);

    // 创建一个 QPushButton 作为父级控件的子元素
    QPushButton *button1 = new QPushButton("Button 1", &parentWidget);
    layout.addWidget(button1);

    // 创建另一个 QPushButton 作为父级控件的子元素
    QPushButton *button2 = new QPushButton("Button 2", &parentWidget);
    layout.addWidget(button2);

    parentWidget.show();

    return app.exec();
}

代码结果: 

        从文件加载样式表

        上述代码都是把样式通过硬编码的⽅式设置的. 这样使 QSS 代码和 C++ 代码耦合在⼀起了, 并不⽅便代码的维护.

        因此更好的做法是把样式放到单独的⽂件中, 然后通过读取⽂件的⽅式来加载样式.

代码⽰例: 从⽂件加载全局样式

/* styles.qss */

/* 设置所有 QWidget 的背景颜色为浅蓝色 */
QWidget 
{
    background-color: lightblue;
}

/* 设置所有 QPushButton 的文字颜色为白色,背景颜色为绿色 */
QPushButton 
{
    color: white;
    background-color: green;
}
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QFile>
#include <QTextStream>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 读取样式表文件
    QFile styleFile(":/styles.qss");  // 文件路径可以根据实际情况修改
    if (!styleFile.open(QFile::ReadOnly | QFile::Text)) 
    {
        qWarning("无法打开样式表文件");
        return -1;
    }

    // 读取样式表内容
    QTextStream textStream(&styleFile);
    QString styleSheet = textStream.readAll();

    // 关闭文件
    styleFile.close();

    // 设置全局样式表
    app.setStyleSheet(styleSheet);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个 QPushButton 作为父级控件的子元素
    QPushButton *button1 = new QPushButton("Button 1", &parentWidget);
    button1->resize(100, 30);
    button1->move(50, 50);

    // 创建另一个 QPushButton 作为父级控件的子元素
    QPushButton *button2 = new QPushButton("Button 2", &parentWidget);
    button2->resize(100, 30);
    button2->move(50, 100);

    parentWidget.show();

    return app.exec();
}

 代码结果:

        使用Qt Designer 编辑样式

        QSS 也可以通过 Qt Designer 直接编辑, 从⽽起到实时预览的效果. 同时也能避免 C++ 和 QSS 代码的耦合.

  选择器

        选择器概况

        QSS 的选择器⽀持以下⼏种:

选择器
⽰例
说明
全局选择器
*
选择所有的 widget.
类型选择器 (type selector)
QPushButton
选择所有的 QPushButton 和 其⼦类的控件.
类选择器 (class selector)
.QPushButton
选择所有的 QPushButton 的控件. 不会选择⼦类.
ID 选择器
#pushButton_2
选择 objectName pushButton_2 的控件.
后代选择器
QDialog QPushButton
选择 QDialog 的所有后代(⼦控件, 孙⼦控件等等)中的 QPushButton.
⼦选择器
QDialog > QPushButton
选择 QDialog 的所有⼦控件中的 QPushButton.
并集选择器
QPushButton,QLineEdit,QComboBox
选择 QPushButton, QLineEdit, QComboBox 这三种控件.
属性选择器
QPushButton[flat="false"]
选择所有 QPushButton 中, flat 属性为 false 的控件.

使⽤类型选择器选中⼦类控件 :

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // 设置全局样式
    a.setStyleSheet("QWidget { color: red; }");
    Widget w;
    w.show();
    return a.exec();
}

 使⽤ id 选择器:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // 设置全局样式
    QString style = "";
    style += "QPushButton { color: yellow; }";
    style += "#pushButton { color: red; }";
    style += "#pushButton_2 { color: green; }";
    a.setStyleSheet(style);
    Widget w;
    w.show();     
    return a.exec();
}

使⽤并集选择器 :

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // 设置全局样式
    a.setStyleSheet("QPushButton, QLabel, QLineEdit { color: red; } ");
    Widget w;
    w.show();
    return a.exec();
}

        子控件选择器

        有些控件内部包含了多个 "⼦控件" . ⽐如 QComboBox 的下拉后的⾯板, ⽐如 QSpinBox 的上下按钮等.

        可以通过⼦控件选择器 :: , 针对上述⼦控件进⾏样式设置.

使用子控件选择器设置 QComboBox 的下拉按钮样式:

#include <QApplication>
#include <QWidget>
#include <QComboBox>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个 QComboBox 控件作为父级控件的子元素
    QComboBox comboBox(&parentWidget);
    comboBox.setGeometry(50, 50, 200, 30);

    // 添加一些选项
    comboBox.addItem("Option 1");
    comboBox.addItem("Option 2");
    comboBox.addItem("Option 3");

    // 设置 QComboBox 的样式表,包括下拉按钮的样式
    comboBox.setStyleSheet("QComboBox::down-arrow {"
                           "    image: url(:/down_arrow.png);"
                           "    width: 20px;"
                           "    height: 20px;"
                           "}");

    parentWidget.show();

    return app.exec();
}

如何修改 QProgressBar 进度条的颜色,以及如何使用子控件选择器对其进行定制: 

#include <QApplication>
#include <QWidget>
#include <QProgressBar>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个垂直布局管理器
    QVBoxLayout layout(&parentWidget);

    // 创建一个 QProgressBar 进度条控件作为父级控件的子元素
    QProgressBar *progressBar = new QProgressBar(&parentWidget);
    progressBar->setRange(0, 100); // 设置进度条范围
    progressBar->setValue(50);     // 设置当前进度
    layout.addWidget(progressBar);

    // 设置 QProgressBar 的样式表,修改进度条颜色和样式
    progressBar->setStyleSheet("QProgressBar {"
                               "    border: 2px solid grey;"
                               "    border-radius: 5px;"
                               "    text-align: center;"
                               "    background-color: #FFFFFF;"
                               "}"
                               "QProgressBar::chunk {"
                               "    background-color: #00FF00;"
                               "    width: 20px;"
                               "}");

    parentWidget.show();

    return app.exec();
}

        伪类选择器

        伪类选择器, 是根据控件所处的某个状态被选择的. 例如按钮被按下, 输⼊框获取到焦点, ⿏标移动到某个控件上等.

• 当状态具备时, 控件被选中, 样式⽣效.
• 当状态不具备时, 控件不被选中, 样式失效.
使⽤ : 的⽅式定义伪类选择器。

常⽤的伪类选择器:

伪类选择器
说明
:hover
⿏标放到控件上
:pressed
⿏标左键按下时
:focus
获取输⼊焦点时
:enabled
元素处于可⽤状态时
:checked
被勾选时
:read-only
元素为只读状态时

        这些状态可以使⽤ ! 来取反. ⽐如 :!hover 就是⿏标离开控件时, :!pressed 就是⿏标松开时,等等. 

示例1:设置按钮的伪类样式(使用样式表)

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个垂直布局管理器
    QVBoxLayout layout(&parentWidget);

    // 创建一个 QPushButton 按钮控件作为父级控件的子元素
    QPushButton *button = new QPushButton("Click me", &parentWidget);
    layout.addWidget(button);

    // 设置 QPushButton 的样式表,使用伪类选择器
    button->setStyleSheet("QPushButton {"
                          "    background-color: blue;"
                          "    color: white;"
                          "}"
                          "QPushButton:hover {"
                          "    background-color: lightblue;"
                          "}"
                          "QPushButton:pressed {"
                          "    background-color: darkblue;"
                          "}");

    parentWidget.show();

    return app.exec();
}

代码结果: 

示例2:使用事件方式实现同样效果

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QEvent>

class CustomButton : public QPushButton
{
public:
    CustomButton(QWidget *parent = nullptr) : QPushButton(parent) {}

protected:
    void enterEvent(QEvent *event) override
    {
        setStyleSheet("background-color: lightblue;");
    }

    void leaveEvent(QEvent *event) override
    {
        setStyleSheet("background-color: blue;");
    }

    void mousePressEvent(QMouseEvent *event) override
    {
        setStyleSheet("background-color: darkblue;");
        QPushButton::mousePressEvent(event);
    }

    void mouseReleaseEvent(QMouseEvent *event) override
    {
        setStyleSheet("background-color: blue;");
        QPushButton::mouseReleaseEvent(event);
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个父级 QWidget
    QWidget parentWidget;
    parentWidget.setWindowTitle("Parent Widget");
    parentWidget.setGeometry(100, 100, 300, 200);

    // 创建一个垂直布局管理器
    QVBoxLayout layout(&parentWidget);

    // 创建一个自定义按钮控件作为父级控件的子元素
    CustomButton *button = new CustomButton(&parentWidget);
    button->setText("Click me");
    layout.addWidget(button);

    parentWidget.show();

    return app.exec();
}

代码结果:

  样式属性

        QSS 中的样式属性⾮常多, 不需要都记住. 核⼼原则还是⽤到了就去查.
        ⼤部分的属性和 CSS 是⾮常相似的.

        盒模型

⼀个遵守盒模型的控件, 由上述⼏个部分构成.
        • Content 矩形区域: 存放控件内容. ⽐如包含的⽂本/图标等.
        • Border 矩形区域: 控件的边框.
        • Padding 矩形区域: 内边距. 边框和内容之间的距离.
        • Margin 矩形区域: 外边距. 边框到控件 geometry 返回的矩形边界的距离
默认情况下, 外边距, 内边距, 边框宽度都是0.

        可以通过⼀些 QSS 属性来设置上述的边距和边框的样式.

QSS 属性
说明
margin
设置四个⽅向的外边距. 复合属性.
padding
设置四个⽅向的内边距. 复合属性.
border-style
设置边框样式
border-width
边框的粗细
border-color
边框的颜⾊
border
复合属性, 相当于 border-style + border-width + border-color

 代码⽰例: 设置边框和内边距、设置外边距

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个主窗口
    QWidget mainWindow;
    mainWindow.setWindowTitle("Qt Style Sheets 示例");

    // 创建一个按钮
    QPushButton button("按钮示例", &mainWindow);

    // 使用布局管理按钮位置
    QHBoxLayout layout;
    layout.addWidget(&button);
    mainWindow.setLayout(&layout);

    // 设置样式
    mainWindow.setStyleSheet(
        "QPushButton {"
        "    border: 2px solid #000000; /* 设置边框 */"
        "    padding: 10px; /* 设置内边距 */"
        "    margin: 20px; /* 设置外边距 */"
        "}");

    mainWindow.show();

    return app.exec();
}

代码结果: 

  控件样式示例

        改变样式表, 使⽤ Qt Designer 设置样式

        按钮

QPushButton 
{
    background-color: #4CAF50; /* 设置背景颜色为绿色 */
    border: none; /* 去掉边框 */
    color: white; /* 文字颜色为白色 */
    padding: 10px 20px; /* 设置内边距 */
    text-align: center; /* 文字居中显示 */
    text-decoration: none; /* 去掉文字下划线 */
    display: inline-block; /* 行内块元素 */
    font-size: 16px; /* 设置字体大小 */
    margin: 4px 2px; /* 设置外边距 */
    cursor: pointer; /* 鼠标移上去显示手型 */
    border-radius: 8px; /* 设置圆角 */
}

        复选框、单选框

QCheckBox::indicator, QRadioButton::indicator 
{
    width: 20px; /* 设置指示器宽度 */
    height: 20px; /* 设置指示器高度 */
}

QCheckBox::indicator:checked, QRadioButton::indicator:checked 
{
    background-color: #2196F3; /* 设置选中时的背景颜色 */
}

        输入框

QLineEdit 
{
    padding: 8px; /* 设置内边距 */
    border: 1px solid #ccc; /* 设置边框 */
    border-radius: 5px; /* 设置圆角 */
}

QLineEdit:hover 
{
    border-color: #4CAF50; /* 鼠标移上去时边框颜色变为绿色 */
}

        列表

QListWidget 
{
    background-color: #f2f2f2; /* 设置背景颜色为灰色 */
    padding: 10px; /* 设置内边距 */
    border: 1px solid #ccc; /* 设置边框 */
    border-radius: 5px; /* 设置圆角 */
}

        菜单栏

QMenuBar 
{
    background-color: #333; /* 设置背景颜色为深灰色 */
    color: white; /* 设置文字颜色为白色 */
}

QMenuBar::item 
{
    spacing: 3px; /* 设置项之间的间距 */
    padding: 1px 4px; /* 设置内边距 */
    background-color: transparent; /* 背景透明 */
    color: white; /* 文字颜色为白色 */
}

QMenuBar::item:selected 
{
    background-color: #4CAF50; /* 选中时的背景颜色为绿色 */
}

        登录界面

QWidget 
{
    background-color: #f2f2f2; /* 设置背景颜色为灰色 */
}

QLineEdit, QPushButton 
{
    border-radius: 3px; /* 设置圆角 */
    padding: 8px; /* 设置内边距 */
    border: 1px solid #ccc; /* 设置边框 */
}

QPushButton 
{
    background-color: #4CAF50; /* 设置背景颜色为绿色 */
    color: white; /* 文字颜色为白色 */
}

QPushButton:hover 
{
    background-color: #45a049; /* 鼠标移上去时背景颜色变深 */
}

绘图

  基本概念

        虽然 Qt 已经内置了很多的控件, 但是不能保证现有控件就可以应对所有场景.

        很多时候我们需要更强的 "⾃定制" 能⼒.

        Qt 提供了画图相关的 API, 可以允许我们在窗⼝上绘制任意的图形形状, 来完成更复杂的界⾯设计.

注意:

        所谓的 "控件" , 本质上也是通过画图的⽅式画上去的.

        画图 API 和 控件 之间的关系, 可以类⽐成机器指令和⾼级语⾔之间的关系.

        控件是对画图 API 的进⼀步封装; 画图 API 是控件的底层实现.

绘图 API 核⼼类

说明
QPainter
"绘画者" 或者 "画家".
⽤来绘图的对象, 提供了⼀系列 drawXXX ⽅法, 可以允许我们绘制各种图 形.
QPaintDevice
"画板".
描述了 QPainter 把图形画到哪个对象上. 像咱们之前⽤过的 QWidget 也是⼀种 QPaintDevice (QWidget 是 QPaintDevice 的⼦类) .
QPen
“画笔”.
描述了QPainter 画出来的线是什么样的.
QBrush
"画刷".
描述了 QPainter 填充⼀个区域是什么样的.

         绘图 API 的使⽤, ⼀般不会在 QWidget 的构造函数中使⽤, ⽽是要放到 paintEvent 事件中.

  绘制各种形状

        绘制线段

        使用painter.drawLine(x1, y1, x2, y2)可以绘制从点 (x1, y1) 到点 (x2, y2) 的直线。

        绘制矩形

        使用painter.drawRect(x, y, width, height)可以绘制一个矩形,左上角坐标为 (x, y),宽为 width,高为 height

        绘制圆形

        使用painter.drawEllipse(x, y, width, height)可以绘制一个椭圆或者近似圆形,其外接矩形的左上角坐标为 (x, y),宽为 width,高为 height

        绘制文本

        使用painter.drawText(x, y, text)可以在指定的位置 (x, y) 绘制文本 text

        设置画笔

        使用painter.setPen(pen)可以设置画笔的颜色、线条宽度、样式等属性。

        设置画刷

        使用painter.setBrush(brush)可以设置画刷的颜色,用于填充形状的内部。

示例代码:

#include <QtWidgets>

class MyWidget : public QWidget
{
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event);

        QPainter painter(this);
        
        // 绘制线段
        painter.setPen(Qt::black);  // 设置画笔颜色为黑色
        painter.drawLine(20, 20, 200, 20);  // 从 (20, 20) 到 (200, 20) 绘制一条线段
        
        // 绘制矩形
        painter.setPen(Qt::blue);  // 设置画笔颜色为蓝色
        painter.drawRect(20, 40, 100, 50);  // 绘制一个矩形,左上角坐标 (20, 40),宽高为 100x50
        
        // 绘制圆形
        painter.setPen(Qt::red);  // 设置画笔颜色为红色
        painter.drawEllipse(20, 100, 80, 80);  // 绘制一个圆形,外接矩形左上角坐标 (20, 100),宽高为 80x80
        
        // 绘制文本
        painter.setPen(Qt::black);  // 设置画笔颜色为黑色
        painter.setFont(QFont("Arial", 12));  // 设置字体和字号
        painter.drawText(20, 200, "Hello, Qt!");  // 在 (20, 200) 处绘制文本
        
        // 设置画笔和画刷
        painter.setPen(Qt::black);  // 设置画笔颜色为黑色
        painter.setBrush(Qt::green);  // 设置画刷颜色为绿色
        painter.drawRect(20, 220, 100, 50);  // 绘制一个带有绿色填充的矩形,左上角坐标 (20, 220),宽高为 100x50
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    MyWidget widget;
    widget.resize(300, 300);
    widget.setWindowTitle("Drawing Shapes in Qt");
    widget.show();
    
    return app.exec();
}

代码结果: 

  绘制图片

        使用QPixmap pixmap(":/images/cat.jpg")加载一个图片,路径可以是文件系统路径或者Qt资源文件路径。

        绘制简单图片

        使用painter.drawPixmap(x, y, pixmap)在指定位置 (x, y) 绘制原始大小的图片。

        缩放图片

        使用pixmap.scaled(width, height, aspectRatioMode)可以缩放图片到指定的宽度和高度,aspectRatioMode参数指定保持长宽比的方式。

        旋转图片

        使用pixmap.transformed(QTransform().rotate(angle))可以旋转图片,angle为旋转的角度。

使用QPixmap实现代码示例:

#include <QtWidgets>

class MyWidget : public QWidget
{
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event);

        QPainter painter(this);

        // 加载图片
        QPixmap pixmap(":/images/cat.jpg");  // 替换为你自己的图片路径或者资源文件路径

        // 绘制简单图片
        painter.drawPixmap(20, 20, pixmap);  // 在 (20, 20) 处绘制原始大小的图片

        // 缩放图片
        QPixmap scaledPixmap = pixmap.scaled(200, 150, Qt::KeepAspectRatio);  // 缩放图片到 200x150 大小,保持长宽比
        painter.drawPixmap(240, 20, scaledPixmap);  // 在 (240, 20) 处绘制缩放后的图片

        // 旋转图片
        QPixmap rotatedPixmap = pixmap.transformed(QTransform().rotate(30.0));  // 旋转图片30度
        painter.drawPixmap(20, 200, rotatedPixmap);  // 在 (20, 200) 处绘制旋转后的图片
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyWidget widget;
    widget.resize(500, 400);
    widget.setWindowTitle("Pixmap Drawing in Qt");
    widget.show();

    return app.exec();
}

代码结果: 

  特殊的画图设备

        前⾯的代码中我们是使⽤ QWidget 作为绘图设备. 在 Qt 中还存在下列三个⽐较特殊的绘图设备. 此处我们也简要介绍.

• QPixmap ⽤于在显⽰器上显⽰图⽚.
• QImage ⽤于对图⽚进⾏像素级修改.
• QPicture ⽤于对 QPainter 的⼀系列操作进⾏存档.

        QPixmap

  • 定义:QPixmap是一个用于处理图像显示的类,它以设备无关的方式存储图像数据,通常用于在屏幕上绘制图像。
  • 特点:QPixmap支持设备无关的图像操作,可以在不同平台上使用相同的接口来处理图像。它可以从文件、内存或绘制操作中创建,并且可以用作GUI界面中的图像资源。
  • 用途:常用于在Qt应用程序中绘制、显示图像,例如在标签、按钮等控件中显示图像。
#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个QPixmap对象并加载图片
    QPixmap pixmap("path/to/image.png");

    // 创建一个标签并显示图片
    QLabel label;
    label.setPixmap(pixmap);
    label.show();

    return app.exec();
}

        QImage

  • 定义:QImage是一个用于处理图像数据的类,它提供了对像素级别的直接访问,支持丰富的图像处理和转换功能。
  • 特点:QImage存储像素数据,并提供了对像素级别的访问和编辑。它可以从文件加载图像,也可以通过像素级别的操作进行创建和编辑。
  • 用途:适合需要对图像进行详细处理、转换、编辑的场景,例如图像处理应用、算法实现等。
#include <QApplication>
#include <QImage>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个QImage对象并加载图片
    QImage image("path/to/image.png");

    // 修改图片像素,这里简单地将图片变为灰度
    for (int y = 0; y < image.height(); ++y) {
        for (int x = 0; x < image.width(); ++x) {
            QRgb pixel = image.pixel(x, y);
            int gray = qGray(pixel);
            image.setPixel(x, y, qRgb(gray, gray, gray));
        }
    }

    // 创建一个标签并显示图片
    QLabel label;
    label.setPixmap(QPixmap::fromImage(image));
    label.show();

    return app.exec();
}

        QPicture

  • 定义:QPicture是一个用于记录和重现绘图操作的类,它存储了绘图操作的命令序列而非像素数据。
  • 特点:QPicture可以记录绘制操作(如绘制线条、文本、图形等),并且可以在需要时进行重放。它不直接处理像素级别的图像数据,而是记录绘制操作的历史。
  • 用途:通常用于需要重放绘图命令的场景,例如图形绘制的撤销和重做、打印预览等。
#include <QApplication>
#include <QPainter>
#include <QPicture>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 创建一个QPicture对象并记录绘图操作
    QPicture picture;
    QPainter painter;
    painter.begin(&picture);
    painter.setPen(Qt::red);
    painter.drawRect(10, 10, 100, 100);
    painter.drawLine(20, 20, 80, 80);
    painter.end();

    // 创建一个标签并显示QPicture中记录的绘图操作
    QLabel label;
    painter.begin(&label);
    painter.drawPicture(0, 0, picture);
    painter.end();
    label.show();

    return app.exec();
}

总结:

  • QPixmap用于显示和处理图像,提供了简单的设备无关接口。
  • QImage用于直接处理图像数据,支持更多的图像操作和转换。
  • QPicture用于记录和重放绘图命令,适合于需要复杂绘图历史记录和重现的场景。

原文地址:https://blog.csdn.net/weixin_66330442/article/details/140147532

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!