如何移动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

我需要将光标移动到正确的位置。起初似乎微不足道,但到目前为止我已经尝试过:

没有任何反应。所有这些命令似乎都被忽略或忽略了位置参数。我做错了什么还是这是某种错误?如何在 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。我认为您可以从中适应您的用例。