最近开发的一个项目中,需要用OLED屏幕显示设备参数、控制菜单等,手里没有现成的屏幕,想到采用QT 程序编写一个上位机程序,用来模拟OLED屏的显示;原理很简单,每一个像素是一个点用0和1标识,0标识黑色,1标识白色;128*64的OLED,也就是每行128个像素,一共64行。
1. 新建一个类OledForm,继承QWidget, 头文件定义如下:
#define OLED_WIDTH 128 //水平像素个数
#define OLED_HEIGHT 64 //垂直像素个数
class OledForm : public QWidget
{
Q_OBJECT
public:
explicit OledForm(QWidget *parent = nullptr);
~OledForm();
static OledForm *oled; //静态变量,在构造函数中赋值,指向这个类的实例
void OLED_DrawPoint(quint8 x,quint8 y,quint8 t);//设置指定像素的值,单色屏因此t的值为0或者1
uint8_t OLED_GetPoint(quint8 x,quint8 y){return _dram[y][x];}//获取指定像素的值
protected:
void paintEvent(QPaintEvent *event) override;//重绘事件
void resizeEvent(QResizeEvent *resizeEvent) override;//窗口大小重置事件
void mousePressEvent(QMouseEvent *event);//鼠标按下事件
void mouseReleaseEvent(QMouseEvent *event);//鼠标抬起事件
void mouseMoveEvent(QMouseEvent *event);//鼠标移动事件
QPoint press_point,move_point;//保存按下或者移动时,鼠标的坐标位置
uint8_t _dram[OLED_HEIGHT][OLED_WIDTH];//二维数组,保存屏幕像素点的值,0或者1
int point_size;//像素大小
int point_space;//每个像素的间隔
int _width,_height;//窗口的宽和高,
double factor;//缩窗口放系数
int rect_w,rect_h;
bool is_draw_rect;
signals:
void reportSelectRect(QRect rect);
private:
void DrawRect(QPainter *painter,int x,int y);
Ui::OledForm *ui;
};
2.实现头文件中所定义的函数
#include "oledform.h"
#include "ui_oledform.h"
#include <QPainter>
#include <QtDebug>
#include <QMouseEvent>
OledForm * OledForm::oled = nullptr;
OledForm::OledForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::OledForm),
is_draw_rect(false)
{
ui->setupUi(this);
_width = geometry().width();
_height = geometry().height();
for(int x = 0; x <OLED_WIDTH; x++){
for(int y = 0; y < OLED_HEIGHT; y++){
_dram[y][x] = 0;
}
}
point_size = 10;
point_space = 1;
oled = this;
_height = OLED_HEIGHT * (point_space+point_size);
_width = OLED_WIDTH * (point_space+point_size);
if(geometry().height() /_height > geometry().width()/_width){
factor = (double)geometry().width()/(double)_width;
}else{
factor = (double)geometry().height() /(double)_height;
}
//setGeometry(0,0,OLED_WIDTH * (point_space+point_size),OLED_HEIGHT * (point_space+point_size));
}
OledForm::~OledForm()
{
delete ui;
}
void OledForm::DrawRect(QPainter *painter,int x,int y)
{
painter->setBrush(QBrush(Qt::blue));
painter->drawRect(x * (point_space+point_size),y * (point_space + point_size),point_size ,point_size );
}
void OledForm::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.save();
painter.setRenderHint(QPainter::Antialiasing);
double f ;
if(width()/height() < 2){
f = (double)height()/(double)_height;
}else{
f = (double)width()/(double)_width;
}
painter.fillRect(0, 0,width(),height(), QBrush(Qt::lightGray));
painter.scale( (double)factor*f, (double)factor*f);
for(int x = 0; x <OLED_WIDTH; x++){
for(int y = 0; y < OLED_HEIGHT; y++){
if(_dram[y][x])
DrawRect(&painter,x,y);
}
}
painter.restore();
if(is_draw_rect){
painter.drawRect(press_point.x(),press_point.y(),rect_w,rect_h);
}
{
painter.drawLine(move_point.x(),0,move_point.x(),height());
painter.drawLine(0,move_point.y(),width(),move_point.y());
}
}
void OledForm::mousePressEvent(QMouseEvent *event)
{
QPoint point = event->pos();
qDebug()<<point;
double f ;
if(width()/height() < 2){
f = (double)height()/(double)_height;
}else{
f = (double)width()/(double)_width;
}
move_point = event->pos();
press_point = event->pos();
update();
//qDebug()<<"x:" << point.x()/((point_space+point_size)*((double)factor*f));
// qDebug()<<"y:" << point.y()/((point_space+point_size)*((double)factor*f));
}
void OledForm::mouseReleaseEvent(QMouseEvent *event)
{
double f ;
int x,y, t_widht,t_height;
is_draw_rect = false;
if(width()/height() < 2){
f = (double)height()/(double)_height;
}else{
f = (double)width()/(double)_width;
}
x = press_point.x()/((point_space+point_size)*((double)factor*f));
y = press_point.y()/((point_space+point_size)*((double)factor*f));
t_widht = rect_w /((point_space+point_size)*((double)factor*f));
t_height = rect_h /((point_space+point_size)*((double)factor*f));
reportSelectRect(QRect(x,y,t_widht + 1,t_height + 1));
update();
}
void OledForm::mouseMoveEvent(QMouseEvent *event)
{
move_point = event->pos();
if (QApplication::mouseButtons() & Qt::LeftButton) {
QPoint point = event->pos();
rect_w = point.x() - press_point.x() + 1;
rect_h = point.y() - press_point.y() + 1;
move_point = event->pos();
is_draw_rect = true;
//update();
}
update();
{
//move_point = event->pos();
// qDebug()<<move_point;
//update();
}
}
void OledForm::OLED_DrawPoint(quint8 x,quint8 y,quint8 t)
{
_dram[y][x] = t;
}
void OledForm::resizeEvent(QResizeEvent *resizeEvent)
{
}
3.在MainWidow类中,实现对按键的检测功能
void MainWindow::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
key_up_sw_event(nullptr);
break;
case Qt::Key_Down:
key_down_sw_event(nullptr);
break;
case Qt::Key_Left:
key_left_sw_event(nullptr);
break;
case Qt::Key_Right:
key_rigth_sw_event(nullptr);
break;
case Qt::Key_Space:
key_ok_sw_event(nullptr);
default:
QWidget::keyPressEvent(event);
}
}
最终的运行效果如下所示:
完整的工程路径: