使用按钮助记符不会更新第二个微调按钮值

Posted

技术标签:

【中文标题】使用按钮助记符不会更新第二个微调按钮值【英文标题】:Using button mnemonic doesn't update second spinbutton value 【发布时间】:2021-01-13 08:25:00 【问题描述】:

我制作了一个示例Gtk::Spinbutton 对话框程序,用户可以在其中修改宽度/高度值并查看主Gtk::Window 上输出的更改(文本)

我添加了两个按钮; 取消OK,打开助记符set_use_underline()

出于测试目的,我假设用户正在修改这两个值。当我使用鼠标单击“确定”按钮时,该程序运行良好。两个值都会更新。但是当 OK 按钮助记符 (Alt + O) 用于接受更改时,高度或宽度值都不会正确更新。例如,在宽度字段我输入1366,在高度字段我输入768,然后我点击Alt + O 来激活OK 按钮操作,宽度更新但高度不更新。相反,保留之前的高度值,在程序开始时为1

核心类

声明
#ifndef WIDTHHEIGHT_H
#define WIDTHHEIGHT_H

class WidthHeight

    int width, height;

public:
    void set_width_core(int width = 1);
    int  get_width_core();
    void set_height_core(int height = 1);
    int  get_height_core();
;

#endif // WIDTHHEIGHT_H

定义
#include "widthheight.h"

void WidthHeight::set_width_core(int width)

    this->width = width;


int WidthHeight::get_width_core()

    return width;


void WidthHeight::set_height_core(int height)

    this->height = height;


int WidthHeight::get_height_core()

    return height;

对话框类

声明
#ifndef WIDTHHEIGHTDIALOG_H
#define WIDTHHEIGHTDIALOG_H

#include <gtkmm/adjustment.h>
#include <gtkmm/dialog.h>
#include <gtkmm/label.h>
#include <gtkmm/spinbutton.h>

class WidthHeight;
class ExampleWindow;

class WidthHeightDialog : public Gtk::Dialog

    WidthHeight &core;
    ExampleWindow &window;
    Gtk::Label width, height;
    Glib::RefPtr<Gtk::Adjustment> w_adjustment, h_adjustment;
    Gtk::SpinButton *w_entry, *h_entry;

    enum response_id 
        REJECT,
        ACCEPT
    ;

    void on_action_signal_response(int);

public:
    WidthHeightDialog(WidthHeight &, ExampleWindow &);
;

#endif // WIDTHHEIGHTDIALOG_H

定义
#include <iostream>

#include "widthheightdialog.h"
#include "widthheight.h"
#include "examplewindow.h"

void WidthHeightDialog::on_action_signal_response(int id)

    switch (id)
    
    case Gtk::RESPONSE_CLOSE:
    case response_id::REJECT:
        std::cout << "Canceled\n";
        break;
    case response_id::ACCEPT:
        std::cout << "OKayed\n";
        break;
    

    core.set_width_core(w_entry->get_value_as_int());
    core.set_height_core(h_entry->get_value_as_int());
    window.refresh_label();
    std::cout << "Width: " << w_entry->get_value_as_int() << std::endl;
    std::cout << "Height: " << h_entry->get_value_as_int() << std::endl;

    hide();


WidthHeightDialog::WidthHeightDialog(WidthHeight &core, ExampleWindow &window)
    : Dialog("Change Width/Height value")
    , core(core)
    , window(window)
    , width("Width:")
    , height("Height:")
    , w_adjustment(Gtk::Adjustment::create(1, 1, 100000))
    , h_adjustment(Gtk::Adjustment::create(1, 1, 100000))
    , w_entry(manage(new Gtk::SpinButton(w_adjustment, 1, 0)))
    , h_entry(manage(new Gtk::SpinButton(h_adjustment, 1, 0)))

    auto box = get_content_area();
    box->add(width);
    box->add(*w_entry);
    box->add(height);
    box->add(*h_entry);

    box->show_all();

    add_button("_Cancel", response_id::REJECT)->set_use_underline();
    add_button("_OK"    , response_id::ACCEPT)->set_use_underline();

    signal_response().connect(sigc::mem_fun(*this, &WidthHeightDialog::on_action_signal_response));


窗口类

声明
#ifndef EXAMPLEWINDOW_H
#define EXAMPLEWINDOW_H

#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <gtkmm/window.h>

#include "widthheight.h"
#include "widthheightdialog.h"

class ExampleWindow : public Gtk::Window

    Gtk::Box vbox;
    Gtk::Label label;
    Gtk::Button button;
    WidthHeight core;
    WidthHeightDialog dialog;

    void on_button_clicked();

public:
    ExampleWindow();
    void refresh_label();
;

#endif // EXAMPLEWINDOW_H

定义
#include "examplewindow.h"

void ExampleWindow::on_button_clicked()

    dialog.show();

    dialog.present();


ExampleWindow::ExampleWindow()
    : vbox(Gtk::ORIENTATION_VERTICAL)
    , label("\n\tOutput printed on console...\t\n")
    , button("Change Width/Height value")
    , dialog(core, *this)

    set_title("Example");

    add(vbox);

    core.set_width_core();
    core.set_height_core();
    refresh_label();

    vbox.pack_start(label);
    label.set_line_wrap(true);
    label.set_selectable(true);

    vbox.pack_start(button);
    button.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_clicked));

    dialog.set_transient_for(*this);

    show_all_children();

    button.grab_focus();


void ExampleWindow::refresh_label()

    std::string width = "\n Width: " + std::to_string(core.get_width_core()) + "\n";
    std::string height = "Height: " + std::to_string(core.get_height_core()) + "\n";

    label.set_text(width + height);


主要

#include <gtkmm/application.h>

#include "examplewindow.h"

int main()

    auto app = Gtk::Application::create("org.gtkmm.example");

    ExampleWindow window;

    return app->run(window);

【问题讨论】:

您的工作示例非常有帮助。但是,请考虑确保包含的标头具有正确的大小写,否则在某些系统上(例如:Linux,文件名区分大小写)将无法构建。 【参考方案1】:

旋转框似乎存在更新问题。例如,尝试以下操作:

    启动应用程序。 修改宽度,然后修改高度。 在宽度编辑框内单击。 点击Alt+O

在这种情况下,您将看到两个值都已更新(就像单击时一样)。我相信当您单击时,会发生同样的事情,但使用按钮。单击它相当于第 3 步(即,将焦点放在另一个小部件上),这似乎会自动更新旋转框。

要解决这个问题,您可以使用Gtk::SpinButton::update() 方法强制更新旋转框。在你的情况下,你会:

void WidthHeightDialog::on_action_signal_response(int id)

    switch (id)
    
    case Gtk::RESPONSE_CLOSE:
    case response_id::REJECT:
        std::cout << "Canceled\n";
        break;
    case response_id::ACCEPT:
        std::cout << "OKayed\n";
        break;
    

    w_entry->update();  // Forces an update
    h_entry->update();  // Forces an update

    core.set_width_core(w_entry->get_value_as_int());
    core.set_height_core(h_entry->get_value_as_int());
    window.refresh_label();
    std::cout << "Width: " << w_entry->get_value_as_int() << std::endl;
    std::cout << "Height: " << h_entry->get_value_as_int() << std::endl;

    hide();

这将确保对于两个旋转框,即使用户没有将焦点放在另一个小部件上(并因此触发最后修改的旋转框的自动更新),更新仍然会发生。

【讨论】:

以上是关于使用按钮助记符不会更新第二个微调按钮值的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net 按钮不会触发,但会在第二个触发

如何将未来列表设置为列表并更新 ListView

NSUserDefault 同步后退按钮 swift

Flutter:如何根据选择的第一个下拉按钮值设置第二个下拉按钮(多级相关按钮)的值?

iOS 13 中第二个视图控制器的导航栏按钮对齐错误

React Native Context 不会跨文件和屏幕更新