[英]How to pass multiple widgets in a GTK+ single button click event in C
因此,我的 GTK 應用程序的二維數組中有許多條目,如下所示:
GtkWidget *entries[10][10];
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++){
entries[i][j] = gtk_entry_new();
}
}
還有一個按鈕:
GtkWidget *btn;
btn = gtk_button_new_with_label("Calculate");
我希望,當用戶單擊按鈕時,條目中的所有值都將傳遞給回調 function 以便對數據進行一些操作。
我有:
g_signal_connect(btn, "clicked", G_CALLBACK(calculate), entries);
還有一個名為calculate()的function:
void calculate(GtkWidget *btn, gpointer data){
double **values = (double **) data;
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++){
printf("%f ", gtk_entry_get_text(GTK_ENTRY(values[i][j])));
}
printf("\n");
}
}
它的名字暗示將要進行計算。 事實上,我打算開發代碼來做到這一點,但在此之前我需要獲取條目中的數據。
為什么我沒有成功獲取數據?
我改變了g_signal_connect(btn, "clicked", G_CALLBACK(calculate), entries);
到g_signal_connect(btn, "clicked", G_CALLBACK(calculate), &entries[0][0]);
現在計算的 function 是:
void calculate(GtkWidget* btn, gpointer *data){
GtkWidget **values = (GtkWidget **) data;
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++){
printf("%s\n", gtk_entry_get_text(GTK_ENTRY(*(values+i) + j)));
}
}
}
我使用gtk_entry_get_text(GTK_ENTRY(*values))
成功獲取了第一個條目的文本,但是如何獲取其他條目的文本?
您正在弄亂傳遞給回調 function 的參數類型:
GtkWidget *entries[10][10];
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++){
entries[i][j] = gtk_entry_new();
}
}
...
g_signal_connect(btn, "clicked", G_CALLBACK(calculate), entries);
這定義了一個 10*10 指針的數組。
但是然后您告訴編譯器將 is 視為指向指針的指針:
void calculate(GtkWidget *btn, gpointer data){
double **values = (double **) data;
這表明 memory 布局非常不同。 二維數組與指向指針的指針不同。 除此之外,您的數組本身還包含指針。
你需要的是這樣的:
void calculate(GtkWidget *btn, gpointer data){
GtkWidget*(*values)[10] = (GtkWidget*(*)[10])data;
...
這應該可以解決您正確處理條目的問題。
除此之外,您可能會遇到另一個問題。 如果在調用回調 function 時數組entries
不再有效,則您有非法的 memory 訪問導致未定義的行為。
您必須使該數組 static 或全局數組。 或者您必須確保執行初始化的 function 在應用程序終止之前永遠不會返回。
我不是 C Gtk+ 用戶,但我能夠使其在 Gtkmm 3.24(我更熟悉)下工作。 這是我的程序,應該可以翻譯成 C 語言:
#include <array>
#include <iostream>
#include <string>
#include <gtkmm.h>
class MainWindow : public Gtk::ApplicationWindow
{
public:
MainWindow();
private:
Gtk::Grid m_layout;
Gtk::Button m_button;
std::array<Gtk::Entry, 4> m_entries;
};
MainWindow::MainWindow()
: m_button{"Print entries content"}
{
// Configuring entries:
size_t count = 0u;
for(auto& entry : m_entries)
{
entry.set_text("Entry #" + std::to_string(count));
++count;
}
// Configuring the button handler:
m_button.signal_clicked().connect(
[this]()
{
for(const auto& entry : m_entries)
{
std::cout << "Entry text : " << entry.get_text() << std::endl;
}
}
);
// Configuring window layout:
m_layout.attach(m_entries[0], 0, 0, 1, 1);
m_layout.attach(m_entries[1], 1, 0, 1, 1);
m_layout.attach(m_entries[2], 0, 1, 1, 1);
m_layout.attach(m_entries[3], 1, 1, 1, 1);
m_layout.attach(m_button, 0, 2, 2, 1);
// Adding the layout to the window:
add(m_layout);
}
int main(int argc, char *argv[])
{
std::cout << "Gtk(mm) version : " << gtk_get_major_version() << "."
<< gtk_get_minor_version() << "."
<< gtk_get_micro_version() << std::endl;
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow window;
window.show_all();
return app->run(window);
}
順便說一句,請注意這是我理解您的問題的(最小)簡化版本。
查看您的代碼,我看到了這一行:
double **values = (double **) data;
但是,當您連接時,您有:
g_signal_connect(btn, "clicked", G_CALLBACK(calculate), entries);
根據我從GtkButton
clicked 信號處理程序的理解, data
的類型應該匹配entries
,它是GtkEntry
的表。 為什么,然后將其轉換為(double **)
?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.