我正在尝试制作一个仅接受数字并将文本显示为货币的自定义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 个位置,忽略额外的符号。这是结果(|
是光标):
当前文本 | 键入的键 | 结果 | 所需的结果 |
---|---|---|---|
| (空) | 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 |
该位置似乎没有从条目的处理程序中更新。我尝试了其他处理程序(如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。我认为您可以从中适应您的用例。