应用新样式时如何更新小部件

How to update widget when new style is applied

我正在使用一个列表进行扩展,该列表包含一个带有文本项 (St.label) 的复选框,在切换时会改变样式。

我正在监听切换事件,当项目被切换时,我在我的 Stlabel 上使用 set_style_class_name() 为我的文本设置了新样式。但是对象的样式不会改变。我找到的唯一解决方案是销毁并重新制作列表中的所有项目,并在对象的初始化中设置不同的 class。

我怎样才能更新已检查的项目?

这里是我正在使用的项目,我在触发 toggle() 函数的复选框上放置了一个侦听器,在这个函数中我正在更新 class,这应该删除 'text-checked' class 所以文本不应该有 'text-decoration:line-through' 属性。

const PopupMenu = imports.ui.popupMenu;
const Lang = imports.lang;
const { Atk, Clutter, St, GObject } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const CheckboxLib = Me.imports.src.checkbox;

var PopupCheckBoxMenuItem = GObject.registerClass({
    Signals: {
      'toggled': { param_types: [GObject.TYPE_BOOLEAN] },
      'deleted': { param_types: [GObject.TYPE_BOOLEAN] }
    },
}, class PopupCheckBoxMenuItem extends PopupMenu.PopupBaseMenuItem {
    _init(text, active, params) {
        super._init(params);
        this.label = new St.Label({
          text: text,
          y_align:Clutter.ActorAlign.CENTER,
          x_expand: true,
          style_class: active ? "text-checked" : ""
        });
        this.tags = new St.Label({
          text: "API",
          y_align:Clutter.ActorAlign.CENTER,
          style_class: "tag-item"
        });
        this.icon = new St.Button({
          style_class: 'remove-task',
          can_focus: true,
        });

        this.icon.connect('clicked', Lang.bind(this,function(){
          this.emit('deleted', this._checkbox.state);
        }));

        this.icon.add_actor(new St.Icon({
          icon_name: 'window-close-symbolic',
          style_class: 'icon-remove-task'
        }));
        this._checkbox = new CheckboxLib.CheckBox(active);

        this._checkbox.connect('clicked', Lang.bind(this,function(){
          this.toggle();
                }));

        this.accessible_role = Atk.Role.CHECK_MENU_ITEM;
        this.checkAccessibleState();

        this._statusBin = new St.Bin({
            x_align: Clutter.ActorAlign.START,
            x_expand: false,
        });
        this.add_child(this._statusBin);

        this.label_actor = this.label;
        this.add_child(this.tags);
        this.add_child(this.label);

        this.add_child(this.icon);

        this._statusLabel = new St.Label({
            text: '',
            style_class: 'popup-status-menu-item',
        });
        this._statusBin.child = this._checkbox;
    }

    setStatus(text) {
        if (text != null) {
            this._statusLabel.text = text;
            this._statusBin.child = this._statusLabel;
            this.reactive = false;
            this.accessible_role = Atk.Role.MENU_ITEM;
        } else {
            this._statusBin.child = this._checkbox;
            this.reactive = true;
            this.accessible_role = Atk.Role.CHECK_MENU_ITEM;
        }
        this.checkAccessibleState();
    }

    activate(event) {
        super.activate(event);
    }

    toggle() {
        this._checkbox.toggle();
        this.emit('toggled', this._checkbox.state);
        //Updating class
        this.label.set_style_class_name("new_class");
        this.label.real_style_changed();
        this.checkAccessibleState();
    }

    get state() {
        return this._checkbox.state;
    }

    get delete_icon() {
        return this.icon;
    }

    setToggleState(state) {
        this._checkbox.state = state;
        this.checkAccessibleState();
    }

    checkAccessibleState() {
        switch (this.accessible_role) {
        case Atk.Role.CHECK_MENU_ITEM:
            if (this._checkbox.state)
                this.add_accessible_state(Atk.StateType.CHECKED);
            else
                this.remove_accessible_state(Atk.StateType.CHECKED);
            break;
        default:
            this.remove_accessible_state(Atk.StateType.CHECKED);
        }
    }
});

最直接的好像是St.Widget.style_changed()。这似乎是强制将样式状态标记为脏并触发重绘(St.Label是一个子类,所以只需调用myLabel.style_changed())。

不过,正确的路线可能是 St.Widget.ensure_style()

我没有看得太深,但问题可能是小部件没有被标记为样式已更改,或者更改可能没有传播到 children 或其他东西。

问题是 属性 我在 css class 中更改了。

由于未知原因,当我设置仅带有文本装饰 属性 的 class 时,样式更改似乎不会重绘,但如果我添加颜色更改,即使它即使没有 St.Widget.style_changed().

也是一样的颜色

因此,如果我 this.label.set_style_class_name("text-checked"); 来更改我的 class,如果我的 css class 如下:

.text-checked
{
    text-decoration: line-through !important;
}

但是这项工作:

.text-checked
{
    text-decoration: line-through !important;
    color: black;
}

一定是 Gjs 组件的样式更改事件如何工作的问题。

问题在这里打开:https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2811