如何移动Gtk::Entry光标?
How to move the Gtk::Entry cursor?
我正在尝试制作一个自定义 Gtk::Entry
小部件 (gtkmm4),它只接受数字并将文本显示为货币。小数点和千位分隔符会自动添加到文本中。所以我从 Gtk::Entry
派生并将 signal_changed()
与格式化输入的成员函数连接起来:
class CurrencyEntry : public Gtk::Entry{
public:
CurrencyEntry() {
set_placeholder_text("0.00");
connectionChange = signal_changed().connect(
sigc::mem_fun(*this, &CurrencyEntry::filterInput)
);
}
protected:
sigc::connection connectionChange;
Glib::ustring oldText;
void filterInput(){
auto currentText = get_text();
/* format currentText */
connectionChange.block();
set_text(currentText);
connectionChange.unblock();
/* move the cursor */
}
};
问题是:用户一次按一个键,但在特定情况下可以在文本中添加多个符号。似乎光标的默认行为是每次按下一个键总是移动 1 个位置,忽略额外的符号。这是结果(|
是光标):
Current Text
Typed Key
Result
Desired Result
|
(empty)
1
0|.01
0.01|
123.45|
6
1,234.5|6
1,234.56|
98|0,123.45|
7
9,8|70,123.45
9,87|0,123.45
我需要将光标移动到正确的位置。起初似乎微不足道,但到目前为止我已经尝试过:
在 filterInput()
结束时调用 set_position(position)
。
在 filterInput()
结束时调用 gtk_editable_set_position( GTK_EDITABLE(this->gobj()), position)
。
覆盖 Entry::on_insert_text(const Glib::ustring& text, int* position)
并更改 position
参数指向的值。
在filterInput()
的末尾直接调用Editable::on_insert_text(const Glib::ustring& text, int* position)
,传递一个新的position
值。
没有任何反应。所有这些命令似乎都被忽略或忽略了位置参数。我做错了什么还是这是某种错误?如何在 Gtk::Entry
小部件中正确设置光标位置?
该位置似乎没有从条目的处理程序中更新。我尝试了其他处理程序(如 insert_text
),但出现了同样的问题。解决这个问题的一种方法是,从您的条目处理程序中,添加一个要在空闲循环中执行的函数。在该功能中,您可以更新位置。这是代码:
#include <algorithm>
#include <iostream>
#include <string>
#include <gtkmm.h>
class CurrencyEntry : public Gtk::Entry
{
public:
CurrencyEntry()
{
m_connection = signal_changed().connect(
[this]()
{
// Get the current edit box content:
std::string str = get_text();
// Make it upper case:
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
// Set the updated text. The connection is blocked to avoid
// recursion:
m_connection.block();
set_text(str);
m_connection.unblock();
// Update the position in the idle loop:
Glib::signal_idle().connect(
[this]()
{
set_position(2);
return false;
});
});
}
private:
sigc::connection m_connection;
};
class MainWindow : public Gtk::ApplicationWindow
{
public:
MainWindow();
private:
CurrencyEntry m_entry;
};
MainWindow::MainWindow()
{
add(m_entry);
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow window;
window.show_all();
return app->run(window);
}
这是您案例的简化版本:所有插入的文本都转换为大写,如果可能,光标位置设置为 2。我认为您可以从中适应您的用例。
我正在尝试制作一个自定义 Gtk::Entry
小部件 (gtkmm4),它只接受数字并将文本显示为货币。小数点和千位分隔符会自动添加到文本中。所以我从 Gtk::Entry
派生并将 signal_changed()
与格式化输入的成员函数连接起来:
class CurrencyEntry : public Gtk::Entry{
public:
CurrencyEntry() {
set_placeholder_text("0.00");
connectionChange = signal_changed().connect(
sigc::mem_fun(*this, &CurrencyEntry::filterInput)
);
}
protected:
sigc::connection connectionChange;
Glib::ustring oldText;
void filterInput(){
auto currentText = get_text();
/* format currentText */
connectionChange.block();
set_text(currentText);
connectionChange.unblock();
/* move the cursor */
}
};
问题是:用户一次按一个键,但在特定情况下可以在文本中添加多个符号。似乎光标的默认行为是每次按下一个键总是移动 1 个位置,忽略额外的符号。这是结果(|
是光标):
Current Text | Typed Key | Result | Desired Result |
---|---|---|---|
| (empty) |
1 |
0|.01 |
0.01| |
123.45| |
6 |
1,234.5|6 |
1,234.56| |
98|0,123.45| |
7 |
9,8|70,123.45 |
9,87|0,123.45 |
我需要将光标移动到正确的位置。起初似乎微不足道,但到目前为止我已经尝试过:
在
filterInput()
结束时调用set_position(position)
。在
filterInput()
结束时调用gtk_editable_set_position( GTK_EDITABLE(this->gobj()), position)
。覆盖
Entry::on_insert_text(const Glib::ustring& text, int* position)
并更改position
参数指向的值。在
filterInput()
的末尾直接调用Editable::on_insert_text(const Glib::ustring& text, int* position)
,传递一个新的position
值。
没有任何反应。所有这些命令似乎都被忽略或忽略了位置参数。我做错了什么还是这是某种错误?如何在 Gtk::Entry
小部件中正确设置光标位置?
该位置似乎没有从条目的处理程序中更新。我尝试了其他处理程序(如 insert_text
),但出现了同样的问题。解决这个问题的一种方法是,从您的条目处理程序中,添加一个要在空闲循环中执行的函数。在该功能中,您可以更新位置。这是代码:
#include <algorithm>
#include <iostream>
#include <string>
#include <gtkmm.h>
class CurrencyEntry : public Gtk::Entry
{
public:
CurrencyEntry()
{
m_connection = signal_changed().connect(
[this]()
{
// Get the current edit box content:
std::string str = get_text();
// Make it upper case:
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
// Set the updated text. The connection is blocked to avoid
// recursion:
m_connection.block();
set_text(str);
m_connection.unblock();
// Update the position in the idle loop:
Glib::signal_idle().connect(
[this]()
{
set_position(2);
return false;
});
});
}
private:
sigc::connection m_connection;
};
class MainWindow : public Gtk::ApplicationWindow
{
public:
MainWindow();
private:
CurrencyEntry m_entry;
};
MainWindow::MainWindow()
{
add(m_entry);
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow window;
window.show_all();
return app->run(window);
}
这是您案例的简化版本:所有插入的文本都转换为大写,如果可能,光标位置设置为 2。我认为您可以从中适应您的用例。