macOS Ventura 13.2.1下Gtkmm4的Gtk::ComboBoxText鼠标选值失效求助
问题:Gtk::ComboBoxText无法通过鼠标点击选中下拉项
我在程序中添加了一个简单的Gtk::ComboBoxText组件,但无法通过鼠标点击下拉选项来选中对应值,仅能通过键盘方向键和回车键切换选中项。以下是相关代码示例(examplewindow.cc):
#include <list> #include <utility> #include <cstdio> #include <iostream> #include <fstream> #include <string> #include <vector> #include <sstream> #include <gtkmm.h> #include <soci.h> #include <soci-sqlite3.h> #include "examplewindow.h" ExampleWindow::ExampleWindow() : m_VBox(Gtk::Orientation::VERTICAL), m_Button_Quit("Quit"), m_Button_File("Choose File"), m_Button_Accept("Accept") { set_title("Gtk::TreeView (ListStore) example"); set_default_size(400, 200); m_VBox.set_margin(5); set_child(m_VBox); //Add the TreeView, inside a ScrolledWindow, with the button underneath: m_ScrolledWindow.set_child(m_TreeView); //Only show the scrollbars when they are necessary: m_ScrolledWindow.set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC); m_ScrolledWindow.set_expand(); m_ComboBoxText.append("Option 1"); m_ComboBoxText.append("Option 2"); m_ComboBoxText.append("Option 3"); m_ComboBoxText.set_active_text("Option 1"); m_ComboBoxText.signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_combo_changed) ); m_VBox.append(m_ComboBoxText); m_VBox.append(m_ScrolledWindow); m_VBox.append(m_ButtonBox); m_ButtonBox.append(m_Button_File); m_ButtonBox.set_margin(5); m_Button_File.set_hexpand(true); m_Button_File.set_halign(Gtk::Align::BASELINE); m_Button_File.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_file_dialog) ); m_ButtonBox.append(m_Entry); m_Entry.set_width_chars(20); m_Entry.set_hexpand(true); m_Entry.set_halign(Gtk::Align::FILL); m_Entry.signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_changed)); m_ButtonBox.append(m_Button_Accept); m_Button_Accept.set_hexpand(true); m_Button_Accept.set_halign(Gtk::Align::BASELINE); m_Button_Accept.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_accept) ); m_ButtonBox.append(m_Button_Quit); m_ButtonBox.set_margin(5); m_Button_Quit.set_hexpand(true); m_Button_Quit.set_halign(Gtk::Align::BASELINE); m_Button_Quit.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_quit) ); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_quit() { set_visible(false); } void ExampleWindow::on_file_dialog() { m_fileChooser = Gtk::FileChooserNative::create("Please choose a folder", *this, Gtk::FileChooser::Action::OPEN, "Choose", "Cancel"); m_fileChooser->signal_response().connect( [this](int p_responseID) { this->on_browse_button_clicked(p_responseID); } ); m_fileChooser->show(); } void ExampleWindow::on_button_accept() { std::vector<std::vector<std::string>> content; std::string db_name = m_path; //std::remove(db_name.c_str()); if (db_name.empty()) { return; } std::cout << db_name << std::endl; soci::session sql(soci::sqlite3, db_name); soci::rowset<soci::row> rs = (sql.prepare << "SELECT * FROM users"); // iteration through the resultset: int i = 0; for (soci::rowset<soci::row>::const_iterator it = rs.begin(); it != rs.end(); ++it) { soci::row const& row = *it; std::vector<std::string> row_content; for(std::size_t j = 0; j != row.size(); ++j) { const soci::column_properties & props = row.get_properties(j); switch(props.get_data_type()) { case soci::dt_string: row_content.push_back(row.get<std::string>(j)); break; case soci::dt_double: row_content.push_back(std::to_string(row.get<double>(j))); break; case soci::dt_integer: row_content.push_back(std::to_string(row.get<int>(j))); break; case soci::dt_long_long: row_content.push_back(std::to_string(row.get<long long>(j))); break; case soci::dt_unsigned_long_long: row_content.push_back(std::to_string(row.get<unsigned long long>(j))); break; case soci::dt_date: break; case soci::dt_xml: break; case soci::dt_blob: break; } } content.push_back(row_content); i++; } if (m_refTreeModel) { m_TreeView.remove_all_columns(); } m_Columns = new ModelColumns(content.at(0).size()); //Create the Tree model: m_refTreeModel = Gtk::ListStore::create(*m_Columns); m_TreeView.set_model(m_refTreeModel); for(int i=0;i<content.size();i++) { auto row = *(m_refTreeModel->append()); for(int j=0;j<content[i].size();j++) { row[*(m_Columns->col_vect.at(j))] = content[i][j]; } } for (int k = 0; k < content.at(0).size(); k++) { m_TreeView.append_column("Column " + std::to_string(k), *(m_Columns->col_vect.at(k))); } } void ExampleWindow::on_entry_changed() { m_path = m_Entry.get_text(); } void ExampleWindow::on_combo_changed() { std::string m_ComboText= m_ComboBoxText.get_active_text(); std::cout << "Hola" << std::endl; m_ComboBoxText.set_active_text(m_ComboText); } void ExampleWindow::on_browse_button_clicked(int p_responseID) { switch(p_responseID) { case GTK_RESPONSE_ACCEPT: { m_path = m_fileChooser->get_file()->get_path(); m_Entry.set_text(m_path); break; } case GTK_RESPONSE_CANCEL: { std::cout << "Cancel clicked : " << p_responseID << std::endl; break; } default: { std::cout << "Unexpected button clicked: " << p_responseID << std::endl; break; } } }
解决方案
问题出在on_combo_changed回调函数里:你在获取当前选中文本后,又调用了m_ComboBoxText.set_active_text(m_ComboText);。这行代码会触发新一轮的signal_changed信号,同时强制重置组件的选中状态——鼠标刚选中新选项,就被这行代码强行覆盖,导致看起来点击操作没有生效。
只需删除这行多余的代码即可解决问题,修改后的回调函数如下:
void ExampleWindow::on_combo_changed() { std::string m_ComboText= m_ComboBoxText.get_active_text(); std::cout << "Hola" << std::endl; // 移除这行不必要的调用,避免干扰选中状态 // m_ComboBoxText.set_active_text(m_ComboText); }
当你通过鼠标点击选中下拉项时,Gtk框架已经自动完成了选中状态的更新,signal_changed信号只是通知你状态发生了变化,此时你只需要在回调中处理选中后的业务逻辑(比如打印日志、更新其他组件等),不需要手动再次设置选中文本。
内容的提问来源于stack exchange,提问作者Alberto García
相关产品推荐
相关产品推荐

