这是我的 C++ 和 GTK-4 代码。我正在尝试制作一个简单的计时器应用程序,当我们锁定屏幕并基于此停止计时器时,它可以监听全局和本地键盘快捷键,在
Linux Pop! OS 22
中工作
#include <gtk-4.0/gtk/gtk.h>
#include <gtk-4.0/gdk/gdk.h>
#include <chrono>
#include <iostream>
#include <string>
using namespace std;
guint timerID = 0;
chrono::steady_clock::time_point timePoint;
GtkWidget *label;
void startTimer()
{
if (timerID != 0)
{
gtk_label_set_text(GTK_LABEL(label), "Timer is already running");
}
else
{
gtk_label_set_text(GTK_LABEL(label), "Timer Started");
timePoint = chrono::steady_clock::now();
timerID = g_timeout_add(
1000,
[](gpointer userData) -> gboolean
{
auto now = chrono::steady_clock::now();
auto diff = chrono::duration_cast<chrono::seconds>(now - timePoint);
gtk_label_set_text(GTK_LABEL(label), (to_string(diff.count()) + " seconds now!").c_str());
return G_SOURCE_CONTINUE;
},
nullptr);
}
}
void stopTimer()
{
if (timerID != 0)
{
g_source_remove(timerID);
timerID = 0;
gtk_label_set_text(GTK_LABEL(label), "Timer is not running");
}
else
{
gtk_label_set_text(GTK_LABEL(label), "Timer is not running");
}
}
static gboolean onKeyPress(GtkWidget *widget, GdkEventKey *event, gpointer userData)
{
if (GDK_CONTROL_MASK && gdk_key_event_get_keyval(event) == GDK_KEY_Escape)
{
g_print("Ctrl + ESC key pressed\n");
}
return TRUE;
}
void applyStyle(GtkWidget *widget, const char *style)
{
GtkStyleContext *context = gtk_widget_get_style_context(widget);
GtkCssProvider *provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider, style, -1);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref(provider);
}
static void activate(GtkApplication *app, gpointer userData)
{
GtkWidget *window;
GtkWidget *box;
GtkWidget *button;
GtkWidget *grid;
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Timer");
gtk_window_set_default_size(GTK_WINDOW(window), 800, 350);
g_signal_connect(window, "key-press-event", G_CALLBACK(onKeyPress), nullptr);
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
gtk_window_set_child(GTK_WINDOW(window), box);
// button = gtk_button_new_with_label("Start");
// g_signal_connect(button, "clicked", G_CALLBACK(printHelloWorld), nullptr);
// g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_window_close), nullptr);
// gtk_box_append(GTK_BOX(box), button);
grid = gtk_grid_new();
gtk_grid_set_row_spacing(GTK_GRID(grid), 10);
gtk_grid_set_column_spacing(GTK_GRID(grid), 10);
// gtk_window_set_child(GTK_WINDOW(window), grid);
gtk_box_append(GTK_BOX(box), grid);
label = gtk_label_new("Timer is not running");
gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 2, 1);
button = gtk_button_new_with_label("Start");
applyStyle(button, "button { background: green; color: white; } button:active { background: darkgreen; }");
g_signal_connect(button, "clicked", G_CALLBACK(startTimer), nullptr);
gtk_grid_attach(GTK_GRID(grid), button, 0, 1, 1, 1);
button = gtk_button_new_with_label("Stop");
applyStyle(button, "button { background: firebrick; color: white; } button:active { background: darkred; }");
g_signal_connect(button, "clicked", G_CALLBACK(stopTimer), nullptr);
gtk_grid_attach(GTK_GRID(grid), button, 1, 1, 1, 1);
gtk_window_present(GTK_WINDOW(window));
}
int main(int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new("org.nhrdev.timer", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), nullptr);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
尝试在应用程序上添加
key-press-event
侦听器,但 VS Code 显示此错误,甚至编译器也
这是我的
c_cpp_properties.json
{
"configurations": [
{
"name": "Linux",
"compilerPath": "/usr/bin/g++-12",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/gtk-4.0",
"/usr/include/gtk-4.0/gdk",
"/usr/include/glib-2.0",
"/usr/lib/x86_64-linux-gnu/glib-2.0/include",
"/usr/include/pango-1.0",
"/usr/include/harfbuzz",
"/usr/include/cairo",
"/usr/include/atk-1.0",
"/usr/include/gdk-pixbuf-2.0",
"/usr/include/graphene-1.0",
"/usr/lib/x86_64-linux-gnu/graphene-1.0/include"
],
"defines": [],
"cppStandard": "gnu++23",
"intelliSenseMode": "linux-gcc-x64",
"browse": {
"path": [
"/usr/include"
]
}
}
],
"version": 4
}
我试图从Chat-GPT、Bard找到解决方案,但没有人能提供任何可行的解决方案
g_signal_connect(window, "按键事件", G_CALLBACK(onKeyPress), nullptr);
这不是创建控制器的方法。您的 G_CALLBACK(onKeyPress) 是正确的,但 "key-press-event" 不是直接信号,它来自控制器。要创建您需要的控制器:
使用 GtkEventController* gtk_event_controller_key_new (void) 创建事件
将创建的事件(不是您的小部件)连接到您的 G_CALLBACK。
使用
将创建的事件添加到包含该事件的小部件中gtk_widget_add_controller ( GtkWidget* 小部件, GtkEventController* 控制器 )