[Orangepi]GTK显示背景图片、图片可拖动

—————————.pro———————————–

TEMPLATE = app
CONFIG += console c++11
CONFIG -= qt

# 交叉编译工具链配置
# 请根据你的交叉编译工具链调整这些设置
QMAKE_CC = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-gcc

QMAKE_CXX = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-g++
QMAKE_LINK = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-g++
QMAKE_AR = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-ar
QMAKE_OBJCOPY = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-objcopy
QMAKE_STRIP = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-strip

# GTK 配置
PKGCONFIG = /home/yue/buildroot/buildroot-2022.05/output/host/bin/pkg-config
PKGCONFIG_PATH =/home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/pkgconfig
PKG_CONFIG_PATH =/home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/pkgconfig

PKGCONFIG += gtk+-3.0
PKGCONFIG += gdk-3.0
PKGCONFIG += gdk-pixbuf-2.0
PKGCONFIG += glib-2.0
PKGCONFIG += pango
PKGCONFIG += harfbuzz
PKGCONFIG += cairo
PKGCONFIG += atk
PKGCONFIG += gobject-2.0

QMAKE_LFLAGS = -L /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/lib64

# 头文件和库路径(请根据实际路径调整)
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/gtk-3.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/glib-2.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/glib-2.0/include
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/pango-1.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/harfbuzz
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/cairo
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/gdk-pixbuf-2.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/atk-1.0

#在如下目录中,l代表lib缩写?
LIBS += -L /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib \
-lgdk_pixbuf-2.0 \
-lgdk-3 \
-lgtk-3 \
-lglib-2.0 \
-lpango-1.0 \
-lharfbuzz \
-lcairo-gobject \
-lcairo \
-latk-1.0 \
-lgobject-2.0 \
-latk-1.0

INCLUDEPATH += /home/yue/openCV/install-arm-gtk/include\
/home/yue/openCV/install-arm-gtk/include/opencv4 \
/home/yue/openCV/install-arm-gtk/include/opencv2

LIBS += /home/yue/openCV/install-arm-gtk/lib/libopencv_highgui.so \
/home/yue/openCV/install-arm-gtk/lib/libopencv_core.so \
/home/yue/openCV/install-arm-gtk/lib/libopencv_imgproc.so \
/home/yue/openCV/install-arm-gtk/lib/libopencv_imgcodecs.so

# 源文件
SOURCES += main.cpp

# 输出文件
TARGET = gtk_example
—————————————–main.cpp———————————————–
#include
#include
#include
#include // For std::min and std::max

using namespace cv;

// 窗口中的图片位置和缩放比例
static int img_x = 100;
static int img_y = 100;
static double scale = 1.0;
static int start_x = 0;
static int start_y = 0;
static bool dragging = false;
static bool in_image = false;
static Mat bg_img;
static Mat fg_img;

// 检查鼠标是否在图片范围内
bool is_mouse_in_image(int mouse_x, int mouse_y) {
return (mouse_x >= img_x && mouse_x <= (img_x + fg_img.cols * scale) && mouse_y >= img_y && mouse_y <= (img_y + fg_img.rows * scale)); } // 绘制图片到 GTK 窗口 static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr) { if (bg_img.empty() || fg_img.empty()) return FALSE; // 将背景图像转换为 Cairo 图像 GdkPixbuf *bg_pixbuf = gdk_pixbuf_new_from_data( (const guchar*)bg_img.data, GDK_COLORSPACE_RGB, false, 8, bg_img.cols, bg_img.rows, bg_img.step, NULL, NULL ); // 将前景图像转换为 Cairo 图像 GdkPixbuf *fg_pixbuf = gdk_pixbuf_new_from_data( (const guchar*)fg_img.data, GDK_COLORSPACE_RGB, false, 8, fg_img.cols, fg_img.rows, fg_img.step, NULL, NULL ); // 绘制背景图像 gdk_cairo_set_source_pixbuf(cr, bg_pixbuf, 0, 0); cairo_paint(cr); // 绘制前景图像,应用缩放比例 cairo_translate(cr, img_x, img_y); cairo_scale(cr, scale, scale); gdk_cairo_set_source_pixbuf(cr, fg_pixbuf, 0, 0); cairo_paint(cr); g_object_unref(bg_pixbuf); g_object_unref(fg_pixbuf); return FALSE; } // 处理鼠标按下事件 static gboolean on_button_press_event(GtkWidget *widget, GdkEventButton *event) { if (event->button == GDK_BUTTON_PRIMARY) {
if (in_image) {
dragging = true;
start_x = event->x – img_x;
start_y = event->y – img_y;
}
}
return FALSE;
}

// 处理鼠标释放事件
static gboolean on_button_release_event(GtkWidget *widget, GdkEventButton *event) {
if (event->button == GDK_BUTTON_PRIMARY) {
dragging = false;
}
return FALSE;
}

// 处理鼠标移动事件
static gboolean on_motion_notify_event(GtkWidget *widget, GdkEventMotion *event) {
if (dragging) {
// 计算新的位置
int new_img_x = event->x – start_x;
int new_img_y = event->y – start_y;

// 限制图片B在背景图片A的范围内
new_img_x = std::max(0, std::min(new_img_x, bg_img.cols – static_cast(fg_img.cols * scale)));
new_img_y = std::max(0, std::min(new_img_y, bg_img.rows – static_cast(fg_img.rows * scale)));

img_x = new_img_x;
img_y = new_img_y;

gtk_widget_queue_draw(widget); // 触发重绘
} else {
in_image = is_mouse_in_image(event->x, event->y);
}
return FALSE;
}

// 缩放图片B
static void on_zoom_in(GtkWidget *widget, gpointer data) {
scale += 0.1;
gtk_widget_queue_draw(GTK_WIDGET(data));
}

static void on_zoom_out(GtkWidget *widget, gpointer data) {
scale = std::max(0.1, scale – 0.1);
gtk_widget_queue_draw(GTK_WIDGET(data));
}

int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);

// 加载背景图片
bg_img = imread(“/home/orangepi/xy.jpg”, IMREAD_COLOR);
if (bg_img.empty()) {
g_print(“Failed to load background image\n”);
return -1;
}

// 加载前景图片
fg_img = imread(“/home/orangepi/monkey.png”, IMREAD_COLOR);
if (fg_img.empty()) {
g_print(“Failed to load foreground image\n”);
return -1;
}

// 创建 GTK 窗口
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
GtkWidget *drawing_area = gtk_drawing_area_new();
GtkWidget *zoom_in_button = gtk_button_new_with_label(“Zoom In”);
GtkWidget *zoom_out_button = gtk_button_new_with_label(“Zoom Out”);

gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), zoom_in_button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), zoom_out_button, FALSE, FALSE, 0);

gtk_widget_set_size_request(drawing_area, bg_img.cols, bg_img.rows);

// 连接绘制事件
g_signal_connect(G_OBJECT(drawing_area), “draw”, G_CALLBACK(on_draw_event), NULL);

// 连接鼠标事件
g_signal_connect(G_OBJECT(drawing_area), “button-press-event”, G_CALLBACK(on_button_press_event), NULL);
g_signal_connect(G_OBJECT(drawing_area), “button-release-event”, G_CALLBACK(on_button_release_event), NULL);
g_signal_connect(G_OBJECT(drawing_area), “motion-notify-event”, G_CALLBACK(on_motion_notify_event), NULL);

gtk_widget_add_events(drawing_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);

// 连接缩放按钮事件
g_signal_connect(G_OBJECT(zoom_in_button), “clicked”, G_CALLBACK(on_zoom_in), drawing_area);
g_signal_connect(G_OBJECT(zoom_out_button), “clicked”, G_CALLBACK(on_zoom_out), drawing_area);

g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

gtk_widget_show_all(window);
gtk_main();

return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注