[Qt]使用opencv显示摄像头

——————.pro——————————
QT += core gui
QT += core gui widgets # 确保 widgets 模块被包含

CONFIG += link_pkgconfig
PKGCONFIG += opencv4

QT += multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CameraWidget.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CameraWidget.h \
mainwindow.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
————————————-CameraWidget.h————————
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include
#include
#include
#include
#include

class CameraWidget : public QWidget {
Q_OBJECT

public:
explicit CameraWidget(QWidget *parent = nullptr);

private slots:
void updateFrame();

private:
QLabel *label;
cv::VideoCapture capture;
};

#endif // CAMERAWIDGET_H
—————————————–CameraWidget.cpp—————–
#include “CameraWidget.h”
#include
#include
#include
#include
#include
#include

CameraWidget::CameraWidget(QWidget *parent) : QWidget(parent) {
// 创建布局和标签
QVBoxLayout *layout = new QVBoxLayout(this);
label = new QLabel(this);
layout->addWidget(label);
setLayout(layout);

// 打开摄像头
if (!capture.open(0)) {
label->setText(“无法打开摄像头”);
return;
}

// 设置摄像头分辨率和其他属性
capture.set(cv::CAP_PROP_FRAME_WIDTH, 640); // 设置宽度
capture.set(cv::CAP_PROP_FRAME_HEIGHT, 480); // 设置高度
capture.set(cv::CAP_PROP_FPS, 15); // 设置帧率
capture.set(cv::CAP_PROP_EXPOSURE, -4); // 设置曝光(根据需要调整)
capture.set(cv::CAP_PROP_GAIN, 0); // 设置增益(根据需要调整)
QThread::msleep(100); // 暂停以让设置生效

// 检查实际分辨率
int width = capture.get(cv::CAP_PROP_FRAME_WIDTH);
int height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
qDebug() << "当前分辨率:" << width << "x" << height; // 设置定时器定时更新摄像头画面 QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &CameraWidget::updateFrame); timer->start(20); // 每 5 毫秒更新一次
}

void CameraWidget::updateFrame() {
if (!capture.isOpened()) {
qDebug() << "摄像头未打开"; return; } cv::Mat frame; capture >> frame; // 从摄像头获取一帧图像
if (frame.empty()) {
qDebug() << "获取的帧为空"; return; } // 转换为 RGB 格式并显示 cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); QImage image(frame.data, frame.cols, frame.rows, frame.step[0], QImage::Format_RGB888); label->setPixmap(QPixmap::fromImage(image));
}

—————————mainwindow.h———————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

———————–mainwindow.cpp———————————
#include “mainwindow.h”
#include “ui_mainwindow.h”

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

}

MainWindow::~MainWindow()
{
delete ui;
}

—————————-main.cpp————————————–
#include
#include “CameraWidget.h”

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
CameraWidget cameraWidget;
cameraWidget.setWindowTitle(“USB 摄像头画面”);
cameraWidget.resize(640, 480);
cameraWidget.show();
return app.exec();
}

[Qt]使用opencv读取摄像头并显示

—————————-.pro—————————-
QT += core gui
QT += core gui widgets # 确保 widgets 模块被包含

CONFIG += link_pkgconfig
PKGCONFIG += opencv4

QT += multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CameraWidget.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CameraWidget.h \
mainwindow.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

——————-CameraWidget.h————————
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include
#include
#include
#include
#include

class CameraWidget : public QWidget {
Q_OBJECT

public:
explicit CameraWidget(QWidget *parent = nullptr);

private slots:
void updateFrame();

private:
QLabel *label;
cv::VideoCapture capture;
};

#endif // CAMERAWIDGET_H
————————————CameraWidget.cpp————————
#include “CameraWidget.h”

CameraWidget::CameraWidget(QWidget *parent) : QWidget(parent) {
// 创建布局和标签
QVBoxLayout *layout = new QVBoxLayout(this);
label = new QLabel(this);
layout->addWidget(label);
setLayout(layout);

// 打开摄像头
capture.open(0); // 0 表示默认摄像头
if (!capture.isOpened()) {
label->setText(“无法打开摄像头”);
return;
}

// 设置定时器定时更新摄像头画面
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &CameraWidget::updateFrame);
timer->start(10); // 每 30 毫秒更新一次
}

void CameraWidget::updateFrame() {
cv::Mat frame;
capture >> frame; // 从摄像头获取一帧图像
if (frame.empty()) return;

// 转换为 RGB 格式并显示
cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
QImage image(frame.data, frame.cols, frame.rows, frame.step[0], QImage::Format_RGB888);
label->setPixmap(QPixmap::fromImage(image));
}
———————-mainwindow.h——————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
—————————-mainwindow.cpp————————-
#include “mainwindow.h”
#include “ui_mainwindow.h”

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

}

MainWindow::~MainWindow()
{
delete ui;
}

————————–main.cpp—————————————
#include
#include “CameraWidget.h”

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
CameraWidget cameraWidget;
cameraWidget.setWindowTitle(“USB 摄像头画面”);
cameraWidget.resize(640, 480);
cameraWidget.show();
return app.exec();
}

[Qt]点击输入框弹出键盘

———————-*.pro———————————
QT += core gui
QT += virtualkeyboard

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

—————————–mainwindow.h——————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

protected:
bool eventFilter(QObject *obj, QEvent *event) override; // 事件过滤器

private:
Ui::MainWindow *ui;

private slots:
void showKeyboard(); // 点击输入框时显示键盘
};

#endif // MAINWINDOW_H

—————————–mainwindow.cpp——————————–
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

// 安装事件过滤器
ui->lineEdit->installEventFilter(this);
this->setFocus(); // 将焦点设置到主窗口
}

MainWindow::~MainWindow()
{
delete ui;
}

// 实现事件过滤器
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->lineEdit && event->type() == QEvent::FocusIn) {
showKeyboard(); // 点击输入框时显示键盘
}
return QMainWindow::eventFilter(obj, event);
}

void MainWindow::showKeyboard()
{
QGuiApplication::inputMethod()->show(); // 显示虚拟键盘
}

—————————–main.cpp—————————————
#include
#include
#include “mainwindow.h”

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qputenv(“QT_IM_MODULE”, QByteArray(“qtvirtualkeyboard”));
qputenv(“QT_VIRTUALKEYBOARD_LANGUAGE”, QByteArray(“fr_FR”)); // 法语
qputenv(“QT_VIRTUALKEYBOARD_LANGUAGE”, QByteArray(“de_DE”)); // 德语

QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

————————*.ui—————————————————-
添加 lineEdit

[GTK]界面输入框键盘

———————-.pro————————–
INCLUDEPATH += /usr/include/gtk-3.0 \
/usr/include/at-spi2-atk/2.0 \
/usr/include/at-spi-2.0 \
/usr/include/dbus-1.0 \
/usr/lib/x86_64-linux-gnu/dbus-1.0/include \
/usr/include/gtk-3.0 /usr/include/gio-unix-2.0 \
/usr/include/cairo /usr/include/pango-1.0 \
/usr/include/harfbuzz \
/usr/include/pango-1.0 \
/usr/include/fribidi \
/usr/include/harfbuzz \
/usr/include/atk-1.0 \
/usr/include/cairo \
/usr/include/pixman-1 \
/usr/include/uuid \
/usr/include/freetype2 \
/usr/include/gdk-pixbuf-2.0 \
/usr/include/libpng16 \
/usr/include/x86_64-linux-gnu \
/usr/include/libmount \
/usr/include/blkid \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include\
/usr/include/

LIBS += -pthread \
-pthread \
-lgtk-3 \
-lgdk-3 \
-lpangocairo-1.0 \
-lpango-1.0 \
-lharfbuzz \
-latk-1.0 \
-lcairo-gobject \
-lcairo \
-lgdk_pixbuf-2.0 \
-lgio-2.0 \
-lgobject-2.0 \
-lglib-2.0 \
-lserialport

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

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

SOURCES += \
main.cpp

————————-main.cpp————————————-
#include

GtkWidget *inputA;
GtkWidget *inputC;
GtkWidget *stack; // 用于切换界面的 GtkStack

// 将字符添加到输入框C
void on_key_clicked(GtkWidget *widget, gpointer data) {
const gchar *text = gtk_button_get_label(GTK_BUTTON(widget));
const gchar *current_text = gtk_entry_get_text(GTK_ENTRY(data));
gchar *new_text = g_strconcat(current_text, text, NULL);
gtk_entry_set_text(GTK_ENTRY(data), new_text);
g_free(new_text); // 释放内存
}

// 删除字符
void on_backspace_clicked(GtkWidget *widget, gpointer data) {
const gchar *current_text = gtk_entry_get_text(GTK_ENTRY(data));
if (g_utf8_strlen(current_text, -1) > 0) {
gchar *new_text = g_utf8_substring(current_text, 0, g_utf8_strlen(current_text, -1) – 1);
gtk_entry_set_text(GTK_ENTRY(data), new_text);
g_free(new_text);
}
}

// 切换到界面B
void switch_to_B(GtkWidget *widget, gpointer data) {
gtk_stack_set_visible_child_name(GTK_STACK(stack), “界面B”);
}

// 切换回界面A
void switch_to_A(GtkWidget *widget, gpointer data) {
gtk_stack_set_visible_child_name(GTK_STACK(stack), “界面A”);
}

// 创建虚拟键盘
GtkWidget* create_keyboard(GtkWidget *input) {
GtkWidget *keyboard = gtk_grid_new();
gtk_grid_set_column_spacing(GTK_GRID(keyboard), 5);
gtk_grid_set_row_spacing(GTK_GRID(keyboard), 5);

// 定义键盘布局
const char *keys[4][10] = {
{“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”, “0”},
{“Q”, “W”, “E”, “R”, “T”, “Y”, “U”, “I”, “O”, “P”},
{“A”, “S”, “D”, “F”, “G”, “H”, “J”, “K”, “L”, “Backspace”},
{“Z”, “X”, “C”, “V”, “B”, “N”, “M”, “”, “”, “”}
};

// 添加按钮到键盘
for (int row = 0; row < 4; row++) { for (int col = 0; col < 10; col++) { if (keys[row][col][0] != '\0') { GtkWidget *key = gtk_button_new_with_label(keys[row][col]); // 根据按钮名称判断是否为 Backspace if (g_strcmp0(keys[row][col], "Backspace") == 0) { g_signal_connect(key, "clicked", G_CALLBACK(on_backspace_clicked), input); } else { g_signal_connect(key, "clicked", G_CALLBACK(on_key_clicked), input); } gtk_grid_attach(GTK_GRID(keyboard), key, col, row, 1, 1); } } } return keyboard; } // 主界面 int main(int argc, char *argv[]) { gtk_init(&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "合并界面"); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); stack = gtk_stack_new(); // 界面A GtkWidget *boxA = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); inputA = gtk_entry_new(); gtk_widget_set_size_request(inputA, 100, 20); GtkWidget *buttonToB = gtk_button_new_with_label("切换到界面 B"); g_signal_connect(buttonToB, "clicked", G_CALLBACK(switch_to_B), NULL); gtk_box_pack_start(GTK_BOX(boxA), inputA, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(boxA), buttonToB, FALSE, FALSE, 0); gtk_stack_add_named(GTK_STACK(stack), boxA, "界面A"); // 界面B GtkWidget *boxB = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); inputC = gtk_entry_new(); gtk_widget_set_size_request(inputC, 100, 20); GtkWidget *keyboard = create_keyboard(inputC); gtk_box_pack_start(GTK_BOX(boxB), inputC, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(boxB), keyboard, TRUE, TRUE, 0); GtkWidget *buttonToA = gtk_button_new_with_label("切换到界面 A"); g_signal_connect(buttonToA, "clicked", G_CALLBACK(switch_to_A), NULL); gtk_box_pack_start(GTK_BOX(boxB), buttonToA, FALSE, FALSE, 0); gtk_stack_add_named(GTK_STACK(stack), boxB, "界面B"); // 添加 stack 到窗口 gtk_container_add(GTK_CONTAINER(window), stack); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }

[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;
}

[GTK]导入背景图片及图片,图片可拖动

——————————pro———————————-
INCLUDEPATH += /usr/include/gtk-3.0 \
/usr/include/at-spi2-atk/2.0 \
/usr/include/at-spi-2.0 \
/usr/include/dbus-1.0 \
/usr/lib/x86_64-linux-gnu/dbus-1.0/include \
/usr/include/gtk-3.0 /usr/include/gio-unix-2.0 \
/usr/include/cairo /usr/include/pango-1.0 \
/usr/include/harfbuzz \
/usr/include/pango-1.0 \
/usr/include/fribidi \
/usr/include/harfbuzz \
/usr/include/atk-1.0 \
/usr/include/cairo \
/usr/include/pixman-1 \
/usr/include/uuid \
/usr/include/freetype2 \
/usr/include/gdk-pixbuf-2.0 \
/usr/include/libpng16 \
/usr/include/x86_64-linux-gnu \
/usr/include/libmount \
/usr/include/blkid \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include\
/usr/include/

LIBS += -pthread \
-pthread \
-lgtk-3 \
-lgdk-3 \
-lpangocairo-1.0 \
-lpango-1.0 \
-lharfbuzz \
-latk-1.0 \
-lcairo-gobject \
-lcairo \
-lgdk_pixbuf-2.0 \
-lgio-2.0 \
-lgobject-2.0 \
-lglib-2.0 \
-lserialport

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

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

SOURCES += \
main.cpp

—————————–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/yue/xy.jpg”, IMREAD_COLOR);
if (bg_img.empty()) {
g_print(“Failed to load background image\n”);
return -1;
}

// 加载前景图片
fg_img = imread(“/home/yue/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;
}

[GTK]openCV导入图片,并且鼠标可拖动

——————————pro————————————-
INCLUDEPATH += /usr/include/gtk-3.0 \
/usr/include/at-spi2-atk/2.0 \
/usr/include/at-spi-2.0 \
/usr/include/dbus-1.0 \
/usr/lib/x86_64-linux-gnu/dbus-1.0/include \
/usr/include/gtk-3.0 /usr/include/gio-unix-2.0 \
/usr/include/cairo /usr/include/pango-1.0 \
/usr/include/harfbuzz \
/usr/include/pango-1.0 \
/usr/include/fribidi \
/usr/include/harfbuzz \
/usr/include/atk-1.0 \
/usr/include/cairo \
/usr/include/pixman-1 \
/usr/include/uuid \
/usr/include/freetype2 \
/usr/include/gdk-pixbuf-2.0 \
/usr/include/libpng16 \
/usr/include/x86_64-linux-gnu \
/usr/include/libmount \
/usr/include/blkid \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include\
/usr/include/

LIBS += -pthread \
-pthread \
-lgtk-3 \
-lgdk-3 \
-lpangocairo-1.0 \
-lpango-1.0 \
-lharfbuzz \
-latk-1.0 \
-lcairo-gobject \
-lcairo \
-lgdk_pixbuf-2.0 \
-lgio-2.0 \
-lgobject-2.0 \
-lglib-2.0 \
-lserialport

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

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

SOURCES += \
main.cpp

—————–main.cpp——————————————
#include
#include
#include

using namespace cv;

// 窗口中的图片位置
static int img_x = 0;
static int img_y = 0;
static int start_x = 0;
static int start_y = 0;
static bool dragging = false;
static bool in_image = false;
static Mat img;

// 检查鼠标是否在图片范围内
bool is_mouse_in_image(int mouse_x, int mouse_y) {
return (mouse_x >= img_x && mouse_x <= (img_x + img.cols) && mouse_y >= img_y && mouse_y <= (img_y + img.rows)); } // 绘制图片到 GTK 窗口 static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr) { if (img.empty()) return FALSE; // 将 OpenCV Mat 转换为 Cairo 图像 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( (const guchar*)img.data, GDK_COLORSPACE_RGB, false, 8, img.cols, img.rows, img.step, NULL, NULL ); // 在指定位置绘制图像 gdk_cairo_set_source_pixbuf(cr, pixbuf, img_x, img_y); cairo_paint(cr); g_object_unref(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) {
// 计算新的位置
img_x = event->x – start_x;
img_y = event->y – start_y;
gtk_widget_queue_draw(widget); // 触发重绘
} else {
// 更新鼠标是否在图像上
in_image = is_mouse_in_image(event->x, event->y);
}
return FALSE;
}

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

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

// 创建 GTK 窗口
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *drawing_area = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), drawing_area);
gtk_widget_set_size_request(drawing_area, 800, 600); // 设置绘图区的大小

// 连接绘制事件
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(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

gtk_widget_show_all(window);
gtk_main();

return 0;
}

[GTK]openCV显示图片

————————–pro——————————————-
INCLUDEPATH += /usr/include/gtk-3.0 \
/usr/include/at-spi2-atk/2.0 \
/usr/include/at-spi-2.0 \
/usr/include/dbus-1.0 \
/usr/lib/x86_64-linux-gnu/dbus-1.0/include \
/usr/include/gtk-3.0 /usr/include/gio-unix-2.0 \
/usr/include/cairo /usr/include/pango-1.0 \
/usr/include/harfbuzz \
/usr/include/pango-1.0 \
/usr/include/fribidi \
/usr/include/harfbuzz \
/usr/include/atk-1.0 \
/usr/include/cairo \
/usr/include/pixman-1 \
/usr/include/uuid \
/usr/include/freetype2 \
/usr/include/gdk-pixbuf-2.0 \
/usr/include/libpng16 \
/usr/include/x86_64-linux-gnu \
/usr/include/libmount \
/usr/include/blkid \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include\
/usr/include/

LIBS += -pthread \
-pthread \
-lgtk-3 \
-lgdk-3 \
-lpangocairo-1.0 \
-lpango-1.0 \
-lharfbuzz \
-latk-1.0 \
-lcairo-gobject \
-lcairo \
-lgdk_pixbuf-2.0 \
-lgio-2.0 \
-lgobject-2.0 \
-lglib-2.0 \
-lserialport

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

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

SOURCES += \
main.cpp

—————————main.cpp————————————
#include
#include
#include

// Function to convert OpenCV Mat to GdkPixbuf
GdkPixbuf* mat_to_pixbuf(const cv::Mat& mat) {
int width = mat.cols;
int height = mat.rows;
int stride = width * 3; // Assuming 3 channels (RGB)

// Create a GdkPixbuf with the same size as the OpenCV Mat
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(
mat.data,
GDK_COLORSPACE_RGB,
false,
8,
width,
height,
stride,
NULL,
NULL
);

return pixbuf;
}

// Callback function to load and display an image
void on_load_image(GtkButton *button, gpointer user_data) {
GtkWidget *image_widget = GTK_WIDGET(user_data);

// Load image using OpenCV
cv::Mat img = cv::imread(“/home/yue/monkey.png”); // Change to your image file

if (img.empty()) {
g_print(“Failed to load image.\n”);
return;
}

// Convert OpenCV Mat to GdkPixbuf
GdkPixbuf *pixbuf = mat_to_pixbuf(img);

// Set the image in the GTK image widget
gtk_image_set_from_pixbuf(GTK_IMAGE(image_widget), pixbuf);

// Unreference the GdkPixbuf when done
g_object_unref(pixbuf);
}

// Main function
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *image;
GtkWidget *button;

// Initialize GTK
gtk_init(&argc, &argv);

// Create a new GTK window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), “GTK + OpenCV Example”);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);

// Set up a signal handler to exit the program when the window is closed
g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

// Create a vertical box to hold widgets
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add(GTK_CONTAINER(window), vbox);

// Create an image widget
image = gtk_image_new();
gtk_box_pack_start(GTK_BOX(vbox), image, TRUE, TRUE, 0);

// Create a button to load the image
button = gtk_button_new_with_label(“Load Image”);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);

// Connect the button click signal to the callback function
g_signal_connect(button, “clicked”, G_CALLBACK(on_load_image), image);

// Show all widgets in the window
gtk_widget_show_all(window);

// Enter the GTK main loop
gtk_main();

return 0;
}

[GTK]简单下拉菜单程序

——————–pro——————————-
INCLUDEPATH += /usr/include/gtk-3.0 \
/usr/include/at-spi2-atk/2.0 \
/usr/include/at-spi-2.0 \
/usr/include/dbus-1.0 \
/usr/lib/x86_64-linux-gnu/dbus-1.0/include \
/usr/include/gtk-3.0 /usr/include/gio-unix-2.0 \
/usr/include/cairo /usr/include/pango-1.0 \
/usr/include/harfbuzz \
/usr/include/pango-1.0 \
/usr/include/fribidi \
/usr/include/harfbuzz \
/usr/include/atk-1.0 \
/usr/include/cairo \
/usr/include/pixman-1 \
/usr/include/uuid \
/usr/include/freetype2 \
/usr/include/gdk-pixbuf-2.0 \
/usr/include/libpng16 \
/usr/include/x86_64-linux-gnu \
/usr/include/libmount \
/usr/include/blkid \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include\
/usr/include/

LIBS += -pthread \
-pthread \
-lgtk-3 \
-lgdk-3 \
-lpangocairo-1.0 \
-lpango-1.0 \
-lharfbuzz \
-latk-1.0 \
-lcairo-gobject \
-lcairo \
-lgdk_pixbuf-2.0 \
-lgio-2.0 \
-lgobject-2.0 \
-lglib-2.0 \
-lserialport
SOURCES += \
main.cpp

———————–main.cpp————————————–
#include

// Callback function for when the selected item in the combo box changes
void on_combobox_changed(GtkComboBox *combobox, gpointer user_data) {
gchar *selected_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combobox));
if (selected_text) {
g_print(“Selected item: %s\n”, selected_text);
g_free(selected_text); // Free the string after use
}
}

// Main function
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *combobox;
GtkWidget *label;

// Initialize GTK
gtk_init(&argc, &argv);

// Create a new GTK window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), “GTK ComboBox Example”);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

// Set up a signal handler to exit the program when the window is closed
g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

// Create a vertical box to hold widgets
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add(GTK_CONTAINER(window), vbox);

// Create a label
label = gtk_label_new(“Select an item from the combo box:”);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);

// Create a combo box with text items
combobox = gtk_combo_box_text_new();
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), “Option 1”);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), “Option 2”);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), “Option 3”);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), “Option 4”);
gtk_box_pack_start(GTK_BOX(vbox), combobox, FALSE, FALSE, 5);

// Connect the “changed” signal to the callback function
g_signal_connect(combobox, “changed”, G_CALLBACK(on_combobox_changed), NULL);

// Show all widgets in the window
gtk_widget_show_all(window);

// Enter the GTK main loop
gtk_main();

return 0;
}

[GTK]切换界面

——————————pro—————————————–
INCLUDEPATH += /usr/include/gtk-3.0 \
/usr/include/at-spi2-atk/2.0 \
/usr/include/at-spi-2.0 \
/usr/include/dbus-1.0 \
/usr/lib/x86_64-linux-gnu/dbus-1.0/include \
/usr/include/gtk-3.0 /usr/include/gio-unix-2.0 \
/usr/include/cairo /usr/include/pango-1.0 \
/usr/include/harfbuzz \
/usr/include/pango-1.0 \
/usr/include/fribidi \
/usr/include/harfbuzz \
/usr/include/atk-1.0 \
/usr/include/cairo \
/usr/include/pixman-1 \
/usr/include/uuid \
/usr/include/freetype2 \
/usr/include/gdk-pixbuf-2.0 \
/usr/include/libpng16 \
/usr/include/x86_64-linux-gnu \
/usr/include/libmount \
/usr/include/blkid \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include\
/usr/include/

LIBS += -pthread \
-pthread \
-lgtk-3 \
-lgdk-3 \
-lpangocairo-1.0 \
-lpango-1.0 \
-lharfbuzz \
-latk-1.0 \
-lcairo-gobject \
-lcairo \
-lgdk_pixbuf-2.0 \
-lgio-2.0 \
-lgobject-2.0 \
-lglib-2.0 \
-lserialport
SOURCES += \
main.cpp
———————————main.cpp——————————–
#include

// 函数声明
void on_button1_clicked(GtkButton *button, GtkStack *stack);
void on_button2_clicked(GtkButton *button, GtkStack *stack);

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

// 创建主窗口
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), “GTK 切换界面示例”);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

// 创建主容器
GtkWidget *main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add(GTK_CONTAINER(window), main_box);

// 创建一个 GtkStack
GtkWidget *stack = gtk_stack_new();
gtk_box_pack_start(GTK_BOX(main_box), stack, TRUE, TRUE, 0);

// 创建界面1
GtkWidget *page1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
GtkWidget *button1 = gtk_button_new_with_label(“切换到界面2”);
g_signal_connect(button1, “clicked”, G_CALLBACK(on_button1_clicked), stack);
gtk_box_pack_start(GTK_BOX(page1), button1, TRUE, TRUE, 0);
gtk_stack_add_named(GTK_STACK(stack), page1, “page1”);

// 创建界面2
GtkWidget *page2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
GtkWidget *button2 = gtk_button_new_with_label(“切换到界面1”);
g_signal_connect(button2, “clicked”, G_CALLBACK(on_button2_clicked), stack);
gtk_box_pack_start(GTK_BOX(page2), button2, TRUE, TRUE, 0);
gtk_stack_add_named(GTK_STACK(stack), page2, “page2”);

// 创建 GtkStackSwitcher
GtkWidget *stack_switcher = gtk_stack_switcher_new();
gtk_box_pack_start(GTK_BOX(main_box), stack_switcher, FALSE, FALSE, 0);

// 将 GtkStackSwitcher 与 GtkStack 关联
gtk_stack_switcher_set_stack(GTK_STACK_SWITCHER(stack_switcher), GTK_STACK(stack));

// 显示所有组件
gtk_widget_show_all(window);

// 运行 GTK 主循环
gtk_main();

return 0;
}

// 切换到界面2的回调函数
void on_button1_clicked(GtkButton *button, GtkStack *stack) {
gtk_stack_set_visible_child_name(GTK_STACK(stack), “page2”);
}

// 切换到界面1的回调函数
void on_button2_clicked(GtkButton *button, GtkStack *stack) {
gtk_stack_set_visible_child_name(GTK_STACK(stack), “page1”);
}