ComboBox se vstupním polem
ComboBox může obsahovat widget Entry pro zadávání libovolného textu. Stačí zadat true do parametru has_entry v konstruktoru.
- 11.6.1. Textový sloupec
- 11.6.2. Vstupní pole
- 11.6.3. Reagování na změny
- 11.6.4. Úplný příklad
- 11.6.5. Jednoduchý textový příklad
11.6.1. Textový sloupec
So that the Entry can interact with the drop-down list of choices, you must specify which of your model columns is the text column, with set_entry_text_column(). For instance:
m_combo.set_entry_text_column(m_columns.m_col_name);
Když vyberete položku z robalovací nabídky, umístí se hodnota z tohoto sloupce do Entry.
11.6.2. Vstupní pole
Protože uživatel může zadat libovolný text, aktivní model řádku není dostačující, abychom zjistili, jaký text uživatel zadal. Proto byste měli za tímto účelem získat widget Entry pomocí metody ComboBox::get_entry() a zavolat get_text().
11.6.3. Reagování na změny
When the user enters arbitrary text, it may not be enough to connect to the changed signal, which is emitted for every typed character. It is not emitted when the user presses the Enter key. Pressing the Enter key or moving the keyboard focus to another widget may signal that the user has finished entering text. To be notified of these events, connect to the Entry's activate and focus_out_event signals, like so
auto entry = m_Combo.get_entry(); if (entry) { // Alternatively you can connect to m_Combo.signal_changed(). entry->signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_changed) ); entry->signal_activate().connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_activate) ); entry->signal_focus_out_event().connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_focus_out_event) ); }
Události X jsou podrobněji popsané v dodatku v oddílu Signály událostí X.
11.6.4. Úplný příklad
File: examplewindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm/window.h> #include <gtkmm/combobox.h> #include <gtkmm/liststore.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: void on_combo_changed(); void on_entry_changed(); void on_entry_has_focus_changed(); //Signal connection: sigc::connection m_ConnectionHasFocusChanged; bool m_entry_had_focus {false}; //Tree model columns: class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() { add(m_col_id); add(m_col_name); } Gtk::TreeModelColumn<Glib::ustring> m_col_id; //The data to choose - this must be text. Gtk::TreeModelColumn<Glib::ustring> m_col_name; }; ModelColumns m_Columns; //Child widgets: Gtk::ComboBox m_Combo; Glib::RefPtr<Gtk::ListStore> m_refTreeModel; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }
File: examplewindow.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> ExampleWindow::ExampleWindow() : m_Combo(true /* has_entry */) { set_title("ComboBox example"); //Create the Tree model: //m_refTreeModel = Gtk::TreeStore::create(m_Columns); m_refTreeModel = Gtk::ListStore::create(m_Columns); m_Combo.set_model(m_refTreeModel); //Fill the ComboBox's Tree Model: auto row = *(m_refTreeModel->append()); row[m_Columns.m_col_id] = "1"; row[m_Columns.m_col_name] = "Billy Bob"; /* auto childrow = *(m_refTreeModel->append(row.children())); childrow[m_Columns.m_col_id] = 11; childrow[m_Columns.m_col_name] = "Billy Bob Junior"; childrow = *(m_refTreeModel->append(row.children())); childrow[m_Columns.m_col_id] = 12; childrow[m_Columns.m_col_name] = "Sue Bob"; */ row = *(m_refTreeModel->append()); row[m_Columns.m_col_id] = "2"; row[m_Columns.m_col_name] = "Joey Jojo"; row = *(m_refTreeModel->append()); row[m_Columns.m_col_id] = "3"; row[m_Columns.m_col_name] = "Rob McRoberts"; /* childrow = *(m_refTreeModel->append(row.children())); childrow[m_Columns.m_col_id] = 31; childrow[m_Columns.m_col_name] = "Xavier McRoberts"; */ //Add the model columns to the Combo (which is a kind of view), //rendering them in the default way: //This is automatically rendered when we use set_entry_text_column(). //m_Combo.pack_start(m_Columns.m_col_id, Gtk::PackOptions::EXPAND_WIDGET); m_Combo.pack_start(m_Columns.m_col_name); m_Combo.set_entry_text_column(m_Columns.m_col_id); m_Combo.set_active(1); //Add the ComboBox to the window. set_child(m_Combo); //Connect signal handlers: m_Combo.signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_combo_changed)); auto entry = m_Combo.get_entry(); if (entry) { entry->signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_changed) ); m_ConnectionHasFocusChanged = entry->property_has_focus().signal_changed(). connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_has_focus_changed)); } else std::cout << "No Entry ???" << std::endl; } ExampleWindow::~ExampleWindow() { // The has_focus changed signal may be emitted while m_Combo is being destructed. // The signal handler can generate critical messages, if it's called when // m_Combo has been partly destructed. m_ConnectionHasFocusChanged.disconnect(); } void ExampleWindow::on_combo_changed() { auto entry = m_Combo.get_entry(); if (entry) { std::cout << "on_combo_changed(): Row=" << m_Combo.get_active_row_number() << ", ID=" << entry->get_text() << std::endl; } } void ExampleWindow::on_entry_changed() { auto entry = m_Combo.get_entry(); if (entry) { std::cout << "on_entry_changed(): Row=" << m_Combo.get_active_row_number() << ", ID=" << entry->get_text() << std::endl; } } void ExampleWindow::on_entry_has_focus_changed() { auto entry = m_Combo.get_entry(); if (entry) { const bool entry_has_focus = entry->has_focus(); if (m_entry_had_focus && !entry_has_focus) { // entry->has_focus() has changed from true to false; entry has lost focus. std::cout << "on_entry_has_focus_changed() to not focused: Row=" << m_Combo.get_active_row_number() << ", ID=" << entry->get_text() << std::endl; } m_entry_had_focus = entry_has_focus; } }
11.6.5. Jednoduchý textový příklad
File: examplewindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm/window.h> #include <gtkmm/comboboxtext.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: void on_combo_changed(); void on_entry_changed(); void on_entry_has_focus_changed(); //Signal connection: sigc::connection m_ConnectionHasFocusChanged; bool m_entry_had_focus {false}; //Child widgets: Gtk::ComboBoxText m_Combo; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }
File: examplewindow.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> ExampleWindow::ExampleWindow() : m_Combo(true /* has_entry */) { set_title("ComboBoxText example"); //Fill the combo: m_Combo.append("something"); m_Combo.append("something else"); m_Combo.append("something or other"); m_Combo.set_active(0); set_child(m_Combo); //Connect signal handlers: m_Combo.signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_combo_changed) ); auto entry = m_Combo.get_entry(); if (entry) { entry->signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_changed)); m_ConnectionHasFocusChanged = entry->property_has_focus().signal_changed(). connect(sigc::mem_fun(*this, &ExampleWindow::on_entry_has_focus_changed)); } else std::cout << "No Entry ???" << std::endl; m_Combo.property_has_frame() = false; } ExampleWindow::~ExampleWindow() { // The has_focus changed signal may be emitted while m_Combo is being destructed. // The signal handler can generate critical messages, if it's called when // m_Combo has been partly destructed. m_ConnectionHasFocusChanged.disconnect(); } void ExampleWindow::on_combo_changed() { std::cout << "on_combo_changed(): Row=" << m_Combo.get_active_row_number() << ", Text=" << m_Combo.get_active_text() << std::endl; } void ExampleWindow::on_entry_changed() { std::cout << "on_entry_changed(): Row=" << m_Combo.get_active_row_number() << ", Text=" << m_Combo.get_active_text() << std::endl; } void ExampleWindow::on_entry_has_focus_changed() { auto entry = m_Combo.get_entry(); if (entry) { const bool entry_has_focus = entry->has_focus(); if (m_entry_had_focus && !entry_has_focus) { // entry->has_focus() has changed from true to false; entry has lost focus. std::cout << "on_entry_has_focus_changed() to not focused: Row=" << m_Combo.get_active_row_number() << ", ID=" << entry->get_text() << std::endl; } m_entry_had_focus = entry_has_focus; } }