简体   繁体   English

如何移动 Gtk::Entry cursor?

[英]How to move the Gtk::Entry cursor?

I'm trying to make a custom Gtk::Entry widget (gtkmm4) that accepts only numbers and shows text as currency.我正在尝试制作一个自定义Gtk::Entry小部件 (gtkmm4),它只接受数字并将文本显示为货币。 Decimal and thousand separators are automatically added to the text.小数点和千位分隔符会自动添加到文本中。 So I derived from Gtk::Entry and connected the signal_changed() with a member function that formats the input:所以我从Gtk::Entry派生并将signal_changed()与格式化输入的成员 function 连接起来:

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 */
    }

};

The problem is: the user presses one key at time, but more than one symbol can be added to the text in specific cases.问题是:用户一次按下一个键,但在特定情况下可以向文本添加多个符号。 It seems that the default behavior of the cursor is to always move 1 place per key pressed, ignoring the extra symbols.似乎 cursor 的默认行为是每次按下一个键总是移动 1 个位置,忽略额外的符号。 This is the result ( | is the cursor):这是结果( |是光标):

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

I need to move the cursor to the correct position. At first seemed trivial, but so far I have tried:我需要将 cursor 移动到正确的 position。起初似乎微不足道,但到目前为止我已经尝试过:

  • Calling set_position(position) at the end of filterInput() .在 filterInput() 结束时调用set_position(position) filterInput()

  • Calling gtk_editable_set_position( GTK_EDITABLE(this->gobj()), position) at the end of filterInput() .在 filterInput() 结束时调用gtk_editable_set_position( GTK_EDITABLE(this->gobj()), position) filterInput()

  • Overriding Entry::on_insert_text(const Glib::ustring& text, int* position) and change the value pointed by the position parameter.覆盖Entry::on_insert_text(const Glib::ustring& text, int* position)并更改position参数指向的值。

  • Calling Editable::on_insert_text(const Glib::ustring& text, int* position) directly at the end of filterInput() , passing a new position value.直接在filterInput()的末尾调用Editable::on_insert_text(const Glib::ustring& text, int* position) ) ,传递一个新的position值。

Nothing happens.什么都没发生。 All these commands seem to be ignored or ignore the position parameter.所有这些命令似乎都被忽略或忽略了 position 参数。 Am I doing something wrong or is this some kind of bug?我做错了什么还是这是某种错误? How can I set the cursor position correctly in a Gtk::Entry widget?如何在Gtk::Entry小部件中正确设置 cursor position?

The position seems not to be updated from the entry's handler. position 似乎没有从条目的处理程序中更新。 I tried other handlers (like insert_text ) and the same issue arises.我尝试了其他处理程序(如insert_text )并出现了同样的问题。 One way to solve this is to, from within you entry's handler, add a function to be executed in the idle loop.解决此问题的一种方法是,从您的条目处理程序中添加一个 function 以在空闲循环中执行。 In that function, you can update the position. Here is the code:在那个 function 中,您可以更新 position。这是代码:

#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);
}

This is a simplified version of you case: all inserted text is transformed to upper case and, if possible, the cursor's position is set to 2. I think you can adapt to your use case from that.这是您案例的简化版本:所有插入的文本都转换为大写,如果可能,光标的 position 设置为 2。我认为您可以从中适应您的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM