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

news2025/1/11 8:11:59

目录

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用于记录和重放绘图命令,适合于需要复杂绘图历史记录和重现的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1889240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索哈希函数:数据完整性的守护者

引言 银行在处理数以百万计的交易时&#xff0c;如何确保每一笔交易都没有出错&#xff1f;快递公司如何跟踪成千上万的包裹&#xff0c;确保每个包裹在运输过程中没有丢失或被替换&#xff1f;医院和诊所为庞大的患者提供有效的医疗保健服务&#xff0c;如何确保每个患者的医疗…

Arthas实战(1)- 运行Arthas

1. 下载Arthas 下载到服务器&#xff1a; wget https://github.com/alibaba/arthas/releases/download/arthas-all-3.7.1/arthas-bin.zip解压 Arthas unzip arthas-bin.zip -d arthas删除压缩包 rm -f arthas-bin.zip 2. 启动Arthas 运行 Arthas java -jar arthas/arthas-bo…

vivado联合modelsim仿真

一. 编译Vivado仿真库 打开Vivado&#xff0c;Tools -> Compile Simulation Libraries 二. 设置仿真工具和库路径 因为新建工程的默认仿真工具是Vivado Simulator&#xff0c;所以要使用Modelsim仿真&#xff0c;每个新工程都要设置一次&#xff0c;方法如下&#xff1a; …

【测试】五子棋项目测试报告

目录 一、项目概述及测试目标 二、项目功能 三、测试类型 1&#xff09;功能测试 ​编辑 2&#xff09;自动化测试 四、测试总结 一、项目概述及测试目标 本项目是一个基于Web的五子棋实时对战应用&#xff0c;旨在提供用户之间的多人实时游戏体验。项目采用前…

阿里巴巴图标库iconfont的使用方式

文章目录 什么是 iconfong创建一个自己的项目如何使用Unicode 使用方法Font class 使用方式Symbol 使用方式还有一种使用方式 在线链接&#xff08;不推荐&#xff0c;但可用于测试&#xff09; 什么是 iconfong Iconfont 是一种图标字体服务。它将各种图标设计转换为字体格式…

pgrouting使用

pgRouting是一个为PostgreSQL和PostGIS提供路由功能的开源库&#xff0c;它支持复杂的图论算法&#xff0c;用于在地理网络中进行最短路径搜索。以下是pgRouting的一些应用实例。 注意事项&#xff1a; 1、路网表中的id、source、target必须是int类型&#xff0c;否则创建拓扑…

Docker(二):Docker image Docker Container

本文将介绍 Docker 映像和容器以及 docker 文件之间的差异与联系&#xff0c;本文还将解释如何以及何时使用它们。 什么是 Dockerfile&#xff1f; 它是一个简单的文本文件&#xff0c;包含命令或过程的集合。我们运行的这些命令和准则作用于配置为创建新的 Docker 镜像的基本…

【linux学习---1】点亮一个LED---驱动一个GPIO

文章目录 1、原理图找对应引脚2、IO复用3、IO配置4、GPIO配置5、GPIO时钟使能6、总结 1、原理图找对应引脚 从上图 可以看出&#xff0c; 蜂鸣器 接到了 BEEP 上&#xff0c; BEEP 就是 GPIO5_IO05 2、IO复用 查找IMX6UL参考手册 和 STM32一样&#xff0c;如果某个 IO 要作为…

[不可抗拒的吸引]韩漫日漫无删减完整版,免费在线观看漫画

[不可抗拒的吸引]韩漫日漫无删减完整版&#xff0c;免费在线观看漫画 不能多说&#xff0c;怕审-核不过&#xff0c;自己看图吧。 食用方法&#xff1a; https://blog.csdn.net/qq_42098517/article/details/140079915 https://gitee.com/zzwuweijun/manhua/blob/master/READ…

入门Axure:快速掌握原型设计技能

2002 年&#xff0c;维克托和马丁在旧金山湾区的一家初创公司工作&#xff0c;发现自己一再被软件开发生命周期的限制所困扰&#xff0c;而且产品团队在编写规范之前很难评估他们的解决方案&#xff0c;开发人员经常不理解&#xff08;或不阅读&#xff09;给出的规范&#xff…

springboot城市菜园共享系统00524

目 录 摘要 1 绪论 1.1 研究背景与意义 1.2 国内外研究现状和发展趋势 1.3论文结构与章节安排 2 城市菜园共享系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.…

Guitar Pro怎么把和弦图放在谱子上方 Guitar Pro怎么设置和弦

在音乐中&#xff0c;和弦是音乐的基本单位。而吉他和弦是指在吉他上按压弦与弹奏弦的组合&#xff0c;我们可以在乐谱中通过和弦图来表现吉他的按压点位&#xff0c;以及弹奏的弦。下面我们看看Guitar Pro怎么把和弦图放在谱子上方&#xff0c;Guitar Pro怎么设置和弦的相关内…

Python+pytest接口自动化之token关联登录的实现

在PC端登录公司的后台管理系统或在手机上登录某个APP时&#xff0c;经常会发现登录成功后&#xff0c;返回参数中会包含token&#xff0c;它的值为一段较长的字符串&#xff0c;而后续去请求的请求头中都需要带上这个token作为参数&#xff0c;否则就提示需要先登录。 这其实就…

【Python】从文本字符串中提取数字、电话号码、日期、网址的方法汇总(全!)

我们在做数据清洗的时候&#xff0c;有时候会遇到将一堆文本中提取我们需要的内容&#xff0c;最常见的是&#xff0c;从一大段文本中提取出数字、电话号码、日期、网址等。而在Python中&#xff0c;正则表达式re&#xff0c;则可以满足我们从文本中提取数字、电话号码和日期等…

测试Andrew NG的语言翻译Agent

我正在测试 Andrew Ng 的语言翻译 A​​I 代理系统及其在逆变换下的稳定性。 给定源语言的文本&#xff0c;我们应用翻译函数 f&#xff0c;然后应用 f 的逆。它应该是不变的&#xff1a; 但是&#xff0c;数学与语言翻译有什么关系&#xff1f; 在完美的系统中&#xff0c;从…

德翔海运核心盈利指标大幅下滑,大额分红56亿不缺钱仍募资补流

《港湾商业观察》黄懿 5月30日&#xff0c;航运公司德翔海运&#xff08;TS Lines&#xff0c;下称“德翔海运”&#xff09;再一次向港交所递交招股书&#xff0c;计划在主板挂牌上市&#xff0c;由摩根大通和招商证券国际担任联席保荐人。 据悉&#xff0c;2022年至2023年&…

【js】数组元素拼接、数组元素类型转换

一、数组元素拼接 二、数组元素类型转换 1、字符串数组 转换成 数字型数组 [1, 2, 3].map(Number) // [1,2,3] 2、数字型数组 转换成 字符串数组 [1, 2, 3].map(String) // [1, 2, 3]

Java语法 小白入门参考资料 数组

数组的基本概念 数组&#xff1a;可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。 比如现实中的车库&#xff1a; 在java中&#xff0c;包含6个整形类型元素的数组&#xff0c;就相当于上图中连在一起的6个车位&#xff0c;从上图中可以看到&#xff1a; 数组…

【C++】开源:量化金融计算库QuantLib配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍量化交易库QuantLib配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#…

【linux】网络基础(3)——tcp协议

文章目录 TCP协议概括TCP头部格式TCP连接管理建立连接&#xff08;三次握手&#xff09;数据传输确认应答机制捎带应答 滑动窗口丢包问题 拥塞控制延时应达 终止连接&#xff08;四次挥手&#xff09; TCP协议概括 TCP是一个面向连接的协议&#xff0c;在传输数据之前需要建立连…