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()等。

案例分析:实现下图功能

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

代码示例:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include 

#include 
#include 

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 

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)开发中,用于绘制自定义的控件、图表和各种特定的图形效果等。

案例分析:实现下图功能

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

代码示例:增加一个PainterArea类

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

painterarea.h

#ifndef PAINTERAREA_H
#define PAINTERAREA_H

#include 

// QPen 钢笔(画笔)是基本的图形对象,绘制直线、曲线、多边形等形状
#include 

// QBrush 画刷是基本的图形对象,主要用于填充,比如矩形、多边形等形状
#include 

#include 

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 

#include "painterarea.h"
#include 
#include 
#include 

#include 


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 

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,也就是绘图区,如下图所示:Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结_第4张图片

代码示例:增加一个DrawWidget类

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

drawwidget.h

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H

#include 

#include 
#include  // 鼠标事件
#include  // 绘制事件
#include  // 实时获取窗口操作等大小
#include 
#include  // 显示图像
#include 
#include 
#include 

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 

#include 
#include 
#include 
#include 

#include "drawwidget.h"

#include 
#include 
#include 


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 

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(Qt::SolidLine)); // 实线
    comboboxlabelstyle->addItem("DashLine",static_cast(Qt::DashLine)); //
    comboboxlabelstyle->addItem("DashDotDotLine",static_cast(Qt::DashDotDotLine));
    comboboxlabelstyle->addItem("DotLine",static_cast(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(Qt::black),this);
    if(color.isValid())
    {
        drawWidget->setColor(color);
        QPixmap ps(20,20);
        ps.fill(color);
    }
}

你可能感兴趣的:(QT,qt,c++,开发语言)