Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结

简介: Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结

一、Qt 窗口API函数基础知识

在Qt窗口编程中,常用的API函数有:


  1. QWidget类的API函数:包括setWindowTitle()、resize()、move()、show()、hide()、setFixedSize()、setWindowFlags()等。
  2. QMainWindow类的API函数:包括setCentralWidget()、menuBar()、statusBar()、addToolBar()、setWindowTitle()等。
  3. QDialog类的API函数:包括setModal()、exec()、rejected()、accepted()等。
  4. QMessageBox类的API函数:包括information()、question()、warning()、critical()等。
  5. QFileDialog类的API函数:包括getOpenFileName()、getSaveFileName()、getExistingDirectory()等。
  6. QInputDialog类的API函数:包括getText()、getInt()、getItem()等。
  7. QDesktopWidget类的API函数:包括screen()、screenGeometry()、availableGeometry()等。
  8. QPalette类的API函数:包括setColor()、setBrush()、setPixmap()等。
  9. QPainter类的API函数:包括drawText()、drawPixmap()、drawLine()、drawRect()等。
  10. QGraphicsScene类的API函数:包括addLine()、addEllipse()、addRect()、addPixmap()等。


案例分析:实现下图功能

代码示例:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
 
#include <QLabel>
#include <QGridLayout>
 
class Dialog : public QDialog
{
    Q_OBJECT
 
public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();
 
 
private:
    QGridLayout *glayout;  // 布局
 
    QLabel *labelgeometry; // 显示函数名称
    QLabel *labelgeometryvalue; // 显示geometry函数获取值
 
    QLabel *labelwidth;
    QLabel *labelwidthvalue;
    QLabel *labelheight;
    QLabel *labelheightvalue;
 
    QLabel *labelrect;
    QLabel *labelrectvalue;
 
    QLabel *labelsize;
    QLabel *labelsizevalue;
 
    // 窗口大小变化事件,通过此函数获取实时窗口的大小
    void resizeEvent(QResizeEvent *);
 
    // 窗口移动事件,通过此函数获取实时窗口的位置
    void moveEvent(QMoveEvent *);
 
public:
    // 更新Label标签的值
    void UpdateLabelFunc();
 
 
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
 
Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,150);
    setWindowTitle("Qt窗口常用的API位置函数测试");
 
    // 布局
    glayout=new QGridLayout(this);
 
    labelgeometry=new QLabel("函数geomery():");
    labelgeometryvalue=new QLabel;
 
    labelwidth=new QLabel("函数width():");
    labelwidthvalue=new QLabel;
    labelheight=new QLabel("函数height():");
    labelheightvalue=new QLabel;
 
    labelrect=new QLabel("函数rect():");
    labelrectvalue=new QLabel;
 
    labelsize=new QLabel("函数size():");
    labelsizevalue=new QLabel;
 
 
    glayout->addWidget(labelgeometry,0,0);
    glayout->addWidget(labelgeometryvalue,0,1);
 
    glayout->addWidget(labelwidth,1,0);
    glayout->addWidget(labelwidthvalue,1,1);
    glayout->addWidget(labelheight,2,0);
    glayout->addWidget(labelheightvalue,2,1);
 
    glayout->addWidget(labelrect,3,0);
    glayout->addWidget(labelrectvalue,3,1);
 
    glayout->addWidget(labelsize,4,0);
    glayout->addWidget(labelsizevalue,4,1);
 
    UpdateLabelFunc(); // 调用更新Label标签的值
}
 
Dialog::~Dialog()
{
}
 
 
// 更新Label标签的值
void Dialog::UpdateLabelFunc()
{
    QString strgeometry; // 专门存放geometry()函数的显示结果
    QString str1,str2,str3,str4;
 
    strgeometry=str1.setNum(geometry().x())+","+str2.setNum(geometry().y())+","+
                            str3.setNum(geometry().width())+","+str4.setNum(geometry().height());
    labelgeometryvalue->setText(strgeometry); //将获取的值展示到这个控件
 
    QString strw,strh;
    labelwidthvalue->setText(strw.setNum(width()));
    labelheightvalue->setText(strh.setNum(height()));
 
    QString strrect;
    QString strrect1,strrect2,strrect3,strrect4;
    strrect=strrect1.setNum(rect().x())+","+strrect2.setNum(rect().y())+","+
            strrect3.setNum(width())+","+strrect4.setNum(height());
    labelrectvalue->setText(strrect);
 
    QString strsize;
    QString strsize1,strsize2;
    strsize=strsize1.setNum(size().width())+","+strsize2.setNum(size().height());
    labelsizevalue->setText(strsize);
 
}
 
// 窗口大小变化事件,通过此函数获取实时窗口的大小
void Dialog::resizeEvent(QResizeEvent *)
{
    UpdateLabelFunc();
}
 
// 窗口移动事件,通过此函数获取实时窗口的位置
void Dialog::moveEvent(QMoveEvent *)
{
    UpdateLabelFunc();
}

main.cpp

#include "dialog.h"
 
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}

二、Qt 绘图框架设计 (QPainter 绘制)

QPainter 是 Qt 框架中用于绘制图形元素的一个类。它提供了一组方法,可以在 QWidget 和 QImage 等 QPaintDevice 上绘制图形。QPainter 中的绘图指令包含绘制图形基础元素如点、线、矩形、圆弧,以及填充、描边和变换等操作。


使用 QPainter 前需要先创建一个 QPainter 对象,并指定要绘制的 QPaintDevice。然后,通过对 QPainter 对象调用不同的绘图方法实现所需绘图效果。


QPainter 除了提供基本的绘图操作外,还提供了一些高级的绘图操作,例如抗锯齿、渐变填充、绘制图片、文字、路径和定制化的绘制元素等。这些高级操作可以通过 QPainter 的不同成员函数进行调用。


QPainter 也是 Qt 绘图工具的一个基础,它被广泛应用于 Qt 图形用户界面(GUI)开发中,用于绘制自定义的控件、图表和各种特定的图形效果等。


案例分析:实现下图功能

代码示例:增加一个PainterArea类

painterarea.h

#ifndef PAINTERAREA_H
#define PAINTERAREA_H
 
#include <QWidget>
 
// QPen 钢笔(画笔)是基本的图形对象,绘制直线、曲线、多边形等形状
#include <QPen>
 
// QBrush 画刷是基本的图形对象,主要用于填充,比如矩形、多边形等形状
#include <QBrush>
 
#include <QPainter>
 
class PainterArea : public QWidget
{
    Q_OBJECT
public:
    explicit PainterArea(QWidget *parent = nullptr);
 
    // 绘制直线、长方形(矩形)
    enum shape{Line,Rectangle};
 
    void setShape(shape);  // 此函数实现绘制形状
    void setPen(QPen);
    void setBrush(QBrush);
 
    void paintEvent(QPaintEvent *); // 重绘事件
    void setfillrule(Qt::FillRule); // 填充规则
 
signals:
 
public slots:
private:
    shape shp;
    QPen pen;
    QBrush brsh;
    Qt::FillRule fillrle;
 
};
 
#endif // PAINTERAREA_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
 
#include "painterarea.h"
#include <QLabel>
#include <QComboBox>
#include <QGridLayout>
 
#include <QColorDialog>
 
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
 
 
private:
    PainterArea *labelshapeArea;
 
    QLabel *labelshape;
    QComboBox *comboboxshape;
 
    QGridLayout *glayout;
 
private slots:
    void dispShapeFunc(int);
 
};
#endif // WIDGET_H

main.cpp

#include "widget.h"
 
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

painterarea.cpp

#include "painterarea.h"
 
PainterArea::PainterArea(QWidget *parent) : QWidget(parent)
{
    setPalette(QPalette(Qt::red)); // 调色板来改变背景颜色
 
    setAutoFillBackground(true); // Qt窗口是否需要绘制背景
 
    // 设置最小尺寸
    setMinimumSize(410,410);
 
}
 
void PainterArea::setShape(shape sh)  // 此函数实现绘制形状
{
    shp=sh;
    update();
 
}
 
void PainterArea::setPen(QPen sh)
{
    pen=sh;
    update();
}
 
void PainterArea::setBrush(QBrush sh)
{
    brsh=sh;
    update();
 
}
 
void PainterArea::paintEvent(QPaintEvent *) // 重绘事件
{
    QPainter p(this);
    p.setPen(pen);
    p.setBrush(brsh);
 
    QRect rect(55,110,290,180);
 
    switch (shp) {
    case Line: // 直线
        p.drawLine(rect.topLeft(),rect.bottomRight());
        break;
    case Rectangle: // 矩形
        p.drawRect(rect);
        break;
    default:
        break;
    }
}
 
void PainterArea::setfillrule(Qt::FillRule rle) // 填充规则
{
    fillrle=rle;
    update(); // 重新绘制区域窗体
 
}

widget.cpp

#include "widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    labelshapeArea=new PainterArea;
 
    glayout=new QGridLayout; // 控制面板的布局
 
    setWindowTitle("Qt绘图框架测试:QPainter类");
 
    labelshape=new QLabel("绘制形状:"); //右边有一个下拉列表框
    comboboxshape=new QComboBox;
    comboboxshape->addItem("Line",PainterArea::Line);
    comboboxshape->addItem("Rectangle",PainterArea::Rectangle);
 
    connect(comboboxshape,SIGNAL(activated(int)),this,SLOT(dispShapeFunc(int)));
 
    glayout->addWidget(labelshape,0,0);
    glayout->addWidget(comboboxshape,0,1);
 
    QHBoxLayout *mainlayout=new QHBoxLayout(this); // 整体布局
    mainlayout->addWidget(labelshapeArea); // 向布局添加控件
    mainlayout->addLayout(glayout); // 向整体布局添加布局
 
    // 如下语句大家自己添加
    dispShapeFunc(comboboxshape->currentIndex());//显示默认的图形
}
 
Widget::~Widget()
{
 
}
 
 
void Widget::dispShapeFunc(int v)
{
    PainterArea::shape sp=PainterArea::shape(comboboxshape->itemData(v,Qt::UserRole).toInt());
    labelshapeArea->setShape(sp);
}

三、Qt 双缓冲机制

Qt双缓冲机制是一种优化技术,用于减少图形闪烁和提高图形性能,特别是在需要频繁重绘的情况下。


简单来说,双缓冲机制就是在一个缓冲区中进行图形绘制,然后将绘制好的图形复制到屏幕中显示,这样能够有效地减少图形闪烁的问题,并且提高了绘图的速度和效率。


在Qt中,双缓冲机制可以通过使用QPixmap或QImage来实现。具体的实现过程可以分为以下几个步骤:


  1. 创建一个QPixmap或QImage对象。
  2. 在该对象上进行绘图操作。
  3. 将绘制好的图像复制到屏幕中显示。

案例分析:绘图工具,可以选择线型、线宽及颜色等基本要素。QMainWindow 对象作为主窗口,QToolBar 对象作为工具栏,QWidget 对象作为主窗口的中央窗体 CentralWidget,也就是绘图区,如下图所示:

代码示例:增加一个DrawWidget类

drawwidget.h

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H
 
#include <QWidget>
 
#include <QtGui>
#include <QMouseEvent> // 鼠标事件
#include <QPaintEvent> // 绘制事件
#include <QResizeEvent> // 实时获取窗口操作等大小
#include <QColor>
#include <QPixmap> // 显示图像
#include <QPainter>
#include <QPalette>
#include <QPen>
 
class DrawWidget : public QWidget
{
    Q_OBJECT
public:
    explicit DrawWidget(QWidget *parent = nullptr);
 
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);
    void resizeEvent(QResizeEvent *);
 
signals:
 
public slots:
    void setStyle(int); // 设置线风格
    void setWidth(int); // 设置线宽度
    void setColor(QColor); // 设置线颜色
    void clearFunc(); // 清除函数
 
private:
    QPixmap *pix; // 在屏幕上显示图像而设计和优化
    QPoint startpos;
    QPoint endPos;
    int style,widthss;
    QColor color;
    
};
 
#endif // DRAWWIDGET_H

mainwindow.h        

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
 
#include <QLabel>
#include <QComboBox>
#include <QToolButton>
#include <QSpinBox>
 
#include "drawwidget.h"
 
#include <QGridLayout>
#include <QColorDialog>
#include <QToolBar>
 
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
 
    void CreateToolBarFunc(); // 创建工具条
 
private:
    DrawWidget *drawWidget;
 
    QGridLayout *glayout;
 
    QLabel *labelstyle;
    QComboBox *comboboxlabelstyle;
 
    QLabel *labelwidth;
    QSpinBox *spinboxlabelwidth;
 
    QToolButton *colorbutton;
    QToolButton *clearbutton;
 
 
private slots:
    void dispstyle();
    void dispcolor();
};
#endif // MAINWINDOW_H

drawwidget.cpp

#include "drawwidget.h"
 
DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
{
    setAutoFillBackground(true);
    setPalette(QPalette(Qt::white));
    pix=new QPixmap(size());
    pix->fill(Qt::white);
 
    // 设置绘制区窗口最小尺寸
    setMinimumSize(600,400);
 
}
 
void DrawWidget::setStyle(int s) // 设置线风格
{
    style=s;
 
}
 
void DrawWidget::setWidth(int w) // 设置线宽度
{
    widthss=w;
 
}
 
void DrawWidget::setColor(QColor c) // 设置线颜色
{
    color=c;
 
}
 
void DrawWidget::clearFunc() // 清除函数
{
    QPixmap *cPix=new QPixmap(size());
    cPix->fill(Qt::white);
    pix=cPix;
    update();
}
 
void DrawWidget::mousePressEvent(QMouseEvent *e)
{
    startpos=e->pos();
 
}
 
void DrawWidget::mouseMoveEvent(QMouseEvent *e)
{
    QPainter *painter=new QPainter;
    QPen pen;
    pen.setStyle((Qt::PenStyle)style);
    pen.setWidth(widthss);
    pen.setColor(color);
 
    painter->begin(pix);
    painter->setPen(pen);
    painter->drawLine(startpos,e->pos());
    painter->end();
 
    startpos=e->pos();
    update();
 
}
 
void DrawWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
 
    painter.drawPixmap(QPoint(0,0),*pix);
 
}
 
void DrawWidget::resizeEvent(QResizeEvent *event)
{
    if(height()>pix->height() || width()>pix->width())
    {
        QPixmap *newPix=new QPixmap(size());
        newPix->fill(Qt::white);
 
        QPainter ps(newPix);
 
        ps.drawPixmap(QPoint(0,0),*pix);
        pix=newPix;
    }
 
    QWidget::resizeEvent(event);
 
}

main.cpp

#include "mainwindow.h"
 
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle("图形绘制综合案例分析(双缓冲机制)");
    drawWidget=new DrawWidget;
    setCentralWidget(drawWidget); // 将刚才创建对象作为主窗口的中心窗口
 
    CreateToolBarFunc(); // 调用此函数实现创建工具栏
 
    setMinimumSize(600,400);
 
    dispstyle();
 
    drawWidget->setWidth(spinboxlabelwidth->value()); // 初始化线宽度
    drawWidget->setColor(Qt::black); // 初始化线颜色
 
}
 
MainWindow::~MainWindow()
{
}
 
 
void MainWindow::CreateToolBarFunc() // 创建工具条
{
    QToolBar *toolBar=addToolBar("Tool");
    labelstyle=new QLabel("线型风格:");
    comboboxlabelstyle=new QComboBox;
    comboboxlabelstyle->addItem("SolidLine",static_cast<int>(Qt::SolidLine)); // 实线
    comboboxlabelstyle->addItem("DashLine",static_cast<int>(Qt::DashLine)); //
    comboboxlabelstyle->addItem("DashDotDotLine",static_cast<int>(Qt::DashDotDotLine));
    comboboxlabelstyle->addItem("DotLine",static_cast<int>(Qt::DotLine)); // 虚线
 
    // 为什么不出现虚线?activeated改为activated
    connect(comboboxlabelstyle,SIGNAL(activated(int)),this,SLOT(dispstyle()));
 
    labelwidth=new QLabel("线型宽度:");
    spinboxlabelwidth=new QSpinBox;
    connect(spinboxlabelwidth,SIGNAL(valueChanged(int)),drawWidget,SLOT(setWidth(int)));
 
    colorbutton=new QToolButton;
    QPixmap pixmap(20,20);
    pixmap.fill(Qt::black);
    colorbutton->setIcon(QIcon(pixmap));
    connect(colorbutton,SIGNAL(clicked()),this,SLOT(dispcolor()));
 
    clearbutton=new QToolButton;
    clearbutton->setText("清除绘制");
    connect(clearbutton,SIGNAL(clicked()),drawWidget,SLOT(clearFunc()));
 
    toolBar->addWidget(labelstyle);
    toolBar->addWidget(comboboxlabelstyle);
    toolBar->addWidget(labelwidth);
    toolBar->addWidget(spinboxlabelwidth);
    toolBar->addWidget(colorbutton);
    toolBar->addWidget(clearbutton);
}
 
 
void MainWindow::dispstyle()
{
    drawWidget->setStyle(comboboxlabelstyle->itemData(comboboxlabelstyle->currentIndex(),
                                                      Qt::UserRole).toInt());
}
 
 
void MainWindow::dispcolor()
{
    QColor color=QColorDialog::getColor(static_cast<int>(Qt::black),this);
    if(color.isValid())
    {
        drawWidget->setColor(color);
        QPixmap ps(20,20);
        ps.fill(color);
    }
}
相关文章
|
28天前
|
安全 算法 Java
Java Stream API:原理、应用与深入解析
Java Stream API:原理、应用与深入解析
|
1月前
|
移动开发 前端开发 API
HTML5 Canvas 提供丰富的绘图API,支持绘制图形、文本、渐变和图像,助力游戏开发
【5月更文挑战第13天】HTML5 Canvas 提供丰富的绘图API,支持绘制图形、文本、渐变和图像,助力游戏开发。关键功能包括绘制基本形状、文本渲染、图像处理及渐变图案。在游戏开发中,Canvas用于绘制游戏元素、实现动画效果、精确的物理碰撞检测,并具有跨平台兼容性,为创造多样化视觉体验和互动游戏提供强大工具。随着技术进步,Canvas在游戏领域的应用将持续增长。
26 4
|
15天前
Qt窗口的闪烁QWebEngineView
Qt窗口的闪烁QWebEngineView
|
15天前
|
存储
Qt无边框窗口可拖动
Qt无边框窗口可拖动
|
1月前
|
安全 Java API
Spring工厂API与原理
Spring工厂API与原理
41 10
|
1月前
|
编译器 API
【Qt】- 信号和槽函数
【Qt】- 信号和槽函数
|
1月前
|
XML JSON API
api接口的使用原理是什么?
总之,API接口的使用原理基于协议、规范和约定,允许不同的应用程序或系统之间进行通信和交互。这种通信方式使得开发人员能够轻松地利用外部服务或资源,从而实现更丰富的功能和服务。
19 0
|
1月前
|
XML JSON API
深入了解API:详解应用程序接口的作用和原理
在现代软件开发领域中,API(Application Programming Interface,应用程序接口)扮演着至关重要的角色。无论是在Web开发、移动应用还是大型软件系统中,API都是不可或缺的组成部分。本文将深入探讨API的作用和原理,帮助读者更好地理解和应用API
|
1月前
|
JavaScript API
Vue3 API函数及功能
Vue3 API函数及功能
12 0
|
1月前
|
XML API 数据格式
【Qt 学习笔记】QWidget的enable属性 | API的介绍
【Qt 学习笔记】QWidget的enable属性 | API的介绍
49 0