如何移动GTK ::进入光标?

发布于 2025-01-18 20:35:15 字数 2091 浏览 4 评论 0原文

我正在尝试制作一个自定义 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 个位置,忽略额外的符号。这是结果(| 是光标):

当前文本键入的按键结果所需结果
|(空)10|。 010.01|
123.45|61,234.5|61,234.56|
98|0,123.45|79,8|70,123.459,87|0,123.45 code>

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

  • 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),传递一个新的 位置值。

什么也没发生。所有这些命令似乎都被忽略或忽略位置参数。我做错了什么还是这是某种错误?如何在 Gtk::Entry 小部件中正确设置光标位置?

I'm trying to make a custom Gtk::Entry widget (gtkmm4) that accepts only numbers and shows text as currency. 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:

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. This is the result (| is the cursor):

Current TextTyped KeyResultDesired Result
| (empty)10|.010.01|
123.45|61,234.5|61,234.56|
98|0,123.45|79,8|70,123.459,87|0,123.45

I need to move the cursor to the correct position. At first seemed trivial, but so far I have tried:

  • Calling set_position(position) at the end of filterInput().

  • Calling gtk_editable_set_position( GTK_EDITABLE(this->gobj()), position) at the end of filterInput().

  • Overriding Entry::on_insert_text(const Glib::ustring& text, int* position) and change the value pointed by the position parameter.

  • Calling Editable::on_insert_text(const Glib::ustring& text, int* position) directly at the end of filterInput(), passing a new position value.

Nothing happens. All these commands seem to be ignored or ignore the position parameter. 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

再可℃爱ぅ一点好了 2025-01-25 20:35:15

该职位似乎没有从该条目的处理程序中更新。我尝试了其他处理程序(例如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。我认为您可以从中适应您的用例。

The position seems not to be updated from the entry's handler. I tried other handlers (like insert_text) and the same issue arises. One way to solve this is to, from within you entry's handler, add a function to be executed in the idle loop. In that function, you can update the position. Here is the code:

#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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文