diff --git a/assets/image/2024-07-05-09-44-30.png b/assets/image/2024-07-05-09-44-30.png new file mode 100644 index 0000000..7281a0d Binary files /dev/null and b/assets/image/2024-07-05-09-44-30.png differ diff --git a/examples/qt5clock/.gitignore b/examples/qt5clock/.gitignore new file mode 100644 index 0000000..f42d6b5 --- /dev/null +++ b/examples/qt5clock/.gitignore @@ -0,0 +1,7 @@ + +dist +build +.config.mk +.flash.conf.json + +moc_* \ No newline at end of file diff --git a/examples/qt5clock/README.md b/examples/qt5clock/README.md new file mode 100644 index 0000000..651bfa3 --- /dev/null +++ b/examples/qt5clock/README.md @@ -0,0 +1,54 @@ +# CM4Stack_QtDemo +Qt demo for CM4STACK + +![](https://github.com/m5stack/M5Stack_Linux_Libs/blob/master/assets/image/2024-07-05-09-44-30.png?raw=true) + +### Dependency + +```bash +sudo apt update +sudo apt install qtbase5-dev qt5-qmake qtbase5-dev-tools qml qtdeclarative5-dev pkg-config +sudo apt install build-essential cmake +``` + +### Get code + +```bash +git clone https://github.com/Forairaaaaa/CM4Stack_QtDemo.git +cd CM4Stack_QtDemo +``` + +### Build + +```bash +mkdir build && cd build +cmake .. && make +``` + +### Run + +```bash +./cm4QtDemo +``` + +### Display on specified framebuffer + +```bash +# export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb1 +export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb$(cat /proc/fb | grep fb_st7789v | awk '{print $1}') +./cm4QtDemo +``` + +Demo will display on `/dev/fb1`, learn more: https://doc.qt.io/qt-6/embedded-linux.html + +You can unset this config: + +```bash +unset QT_QPA_PLATFORM +``` + +## Compilation Engineering +Because the QT project has a very large number of dependencies, it is very difficult to do cross-compilation alone, so this example can no longer be developed using cross-compilation. +When verifying on the host, you can directly compile using scons and then run it. If you want to deploy it to CoreMP135, there are two ways to compile. +The first method: compile directly on CoreMP135, the advantage is immediate use after compilation, but the disadvantage is that the compilation speed is very slow. +The second method: mount the image of CoreMP135 to a Linux system, use chroot to leverage the host's computing power for compilation. The advantage is fast compilation speed, but the disadvantage is that compilation testing is more complex. \ No newline at end of file diff --git a/examples/qt5clock/SConstruct b/examples/qt5clock/SConstruct new file mode 100644 index 0000000..076d65c --- /dev/null +++ b/examples/qt5clock/SConstruct @@ -0,0 +1,4 @@ +from pathlib import Path +import os +with open(str(Path(os.getcwd())/'..'/'..'/'tools'/'scons'/'project.py')) as f: + exec(f.read()) diff --git a/examples/qt5clock/config_defaults.mk b/examples/qt5clock/config_defaults.mk new file mode 100644 index 0000000..59293dc --- /dev/null +++ b/examples/qt5clock/config_defaults.mk @@ -0,0 +1,6 @@ +# unix +# CONFIG_TOOLCHAIN_PATH="/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin" +# win +# CONFIG_TOOLCHAIN_PATH="..\\gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf\\bin" + +# CONFIG_TOOLCHAIN_PREFIX="arm-linux-gnueabihf-" diff --git a/examples/qt5clock/main/Kconfig b/examples/qt5clock/main/Kconfig new file mode 100644 index 0000000..e69de29 diff --git a/examples/qt5clock/main/SConstruct b/examples/qt5clock/main/SConstruct new file mode 100644 index 0000000..aa9c91f --- /dev/null +++ b/examples/qt5clock/main/SConstruct @@ -0,0 +1,44 @@ +# project_root/src/SConscript +import os +# Import the environment from the SConstruct file +Import('env') +with open(env['PROJECT_TOOL_S']) as f: + exec(f.read()) + +if not env['HOST_OS'].startswith('posix'): + env.Fatal("This project can only be compiled in Linux.") + +os.system('moc `pkg-config --cflags-only-other Qt5Widgets Qt5Gui Qt5Core` -o src/moc_ClockWidget.cpp src/ClockWidget.h') +os.system('pkg-config --cflags Qt5Widgets Qt5Gui Qt5Core > ../build/config/defintion.txt') +os.system('pkg-config --libs Qt5Widgets Qt5Gui Qt5Core > ../build/config/link.txt') + +SRCS = Glob('src/*.c*') +INCLUDE = [ADir('include'), ADir('src')] +PRIVATE_INCLUDE = [] +REQUIREMENTS = ['pthread'] +STATIC_LIB = [] +DYNAMIC_LIB = [] +DEFINITIONS = ['-fPIC'] +DEFINITIONS_PRIVATE = [] +LDFLAGS = [] +LINK_SEARCH_PATH = [] + +with open('../build/config/defintion.txt' , 'r') as f: + DEFINITIONS += f.read().strip().split() + +with open('../build/config/link.txt' , 'r') as f: + LDFLAGS += f.read().strip().split() + +env['COMPONENTS'].append({'target':env['PROJECT_NAME'], + 'SRCS':SRCS, + 'INCLUDE':INCLUDE, + 'PRIVATE_INCLUDE':PRIVATE_INCLUDE, + 'REQUIREMENTS':REQUIREMENTS, + 'STATIC_LIB':STATIC_LIB, + 'DYNAMIC_LIB':DYNAMIC_LIB, + 'DEFINITIONS':DEFINITIONS, + 'DEFINITIONS_PRIVATE':DEFINITIONS_PRIVATE, + 'LDFLAGS':LDFLAGS, + 'LINK_SEARCH_PATH':LINK_SEARCH_PATH, + 'REGISTER':'project' + }) \ No newline at end of file diff --git a/examples/qt5clock/main/include/main.h b/examples/qt5clock/main/include/main.h new file mode 100644 index 0000000..45dcbb0 --- /dev/null +++ b/examples/qt5clock/main/include/main.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/examples/qt5clock/main/src/ClockWidget.cpp b/examples/qt5clock/main/src/ClockWidget.cpp new file mode 100644 index 0000000..baed091 --- /dev/null +++ b/examples/qt5clock/main/src/ClockWidget.cpp @@ -0,0 +1,67 @@ +#include "ClockWidget.h" +#include +#include + +ClockWidget::ClockWidget(QWidget *parent) + : QWidget(parent), timer(new QTimer(this)) +{ + connect(timer, &QTimer::timeout, this, &ClockWidget::updateClock); + timer->start(1000); + updateClock(); +} + +void ClockWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + int side = qMin(width(), height()); + painter.translate(width() / 2, height() / 2); + painter.scale(side / 200.0, side / 200.0); + + painter.setPen(Qt::NoPen); + painter.setBrush(Qt::black); + painter.drawEllipse(-100, -100, 200, 200); + + painter.setPen(Qt::white); + QFont font = painter.font(); + font.setPointSize(8); + painter.setFont(font); + + for (int i = 0; i < 12; ++i) { + painter.save(); + painter.rotate(30.0 * i); + + painter.drawLine(0, -90, 0, -100); + + painter.drawText(-10, -90, 20, 20, Qt::AlignCenter, QString::number(i)); + + painter.restore(); + } + + painter.save(); + painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); + painter.drawLine(0, 0, 0, -50); + painter.restore(); + + painter.save(); + painter.rotate(6.0 * (time.minute() + time.second() / 60.0)); + painter.drawLine(0, 0, 0, -70); + painter.restore(); + + painter.setPen(Qt::red); + painter.save(); + painter.rotate(6.0 * time.second()); + painter.drawLine(0, 0, 0, -90); + painter.restore(); +} + + + +void ClockWidget::updateClock() +{ + time = QTime::currentTime(); + update(); +} diff --git a/examples/qt5clock/main/src/ClockWidget.h b/examples/qt5clock/main/src/ClockWidget.h new file mode 100644 index 0000000..9ad9f26 --- /dev/null +++ b/examples/qt5clock/main/src/ClockWidget.h @@ -0,0 +1,25 @@ +#ifndef CLOCKWIDGET_H +#define CLOCKWIDGET_H + +#include +#include +#include + +class ClockWidget : public QWidget +{ + Q_OBJECT + +public: + ClockWidget(QWidget *parent = nullptr); +protected: + void paintEvent(QPaintEvent *event) override; + +private slots: + void updateClock(); + +private: + QTimer *timer; + QTime time; +}; + +#endif // CLOCKWIDGET_H diff --git a/examples/qt5clock/main/src/main.cpp b/examples/qt5clock/main/src/main.cpp new file mode 100644 index 0000000..3f1605d --- /dev/null +++ b/examples/qt5clock/main/src/main.cpp @@ -0,0 +1,10 @@ +#include +#include "ClockWidget.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + ClockWidget clock; + clock.show(); + return app.exec(); +}