【问题标题】:Changing the selected item colour in a GtkTreeview using python使用 python 在 GtkTreeview 中更改所选项目的颜色
【发布时间】:2011-03-07 04:02:32
【问题描述】:

我有一个包含 pygtk.treeview 的对话框,用于按优先级列出任务。每行都有基于该优先级设置的背景颜色,例如,最高优先级的背景为浅红色。

行选择颜色不是那么容易改变的。我可以使用treeview.modify_base(gtk.STATE_SELECTED, "#C4C4C4") 进行设置,但没有一种颜色与用于增强优先级概念的颜色搭配得很好。

我的想法是将选择颜色更改为用作普通行背景颜色的稍暗版本,因此在上面的示例中,这将是更深的红色。我尝试调用上面的函数来响应treeselection 的changed 信号,它可以工作,但是闪烁很严重。

另一个想法是将选择更改为透明并在其周围放置一个边框,但据我所知,这是不可能的。

  1. 如何以上述方式更改选择颜色而不出现闪烁?
  2. 我可以通过只在行周围设置边框来更改显示选择吗?

注意:我知道这违反了用户选择的主题。我觉得我有一个很好的理由。用颜色表示优先级可以立即识别。选择颜色隐藏了这一点。如果您有其他建议,我愿意接受,但需要保持用户能够轻松识别优先级。

【问题讨论】:

  • +1 仅在有充分理由时才尝试覆盖用户的主题。

标签: python user-interface gtk pygtk gtktreeview


【解决方案1】:

您可以使用here 描述的方法——我已经对其进行了简短的测试,它可以在不闪烁的情况下完成工作。基本上,诀窍是使用单元格渲染器的“标记”属性。但是有一个问题:如果你想用这个方法改变 background 颜色,只有“实际”文本后面的背景被改变,而不是整行。但是,如果您想更改 text 颜色(使用

我有以下 CellDataFunc(这是 C#,但我希望它仍然有用):

private void CellDataFunc(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) {
    Item item = (Item) model.GetValue (iter, 0);
    if(cell is CellRendererText) {
        int id = (int)column.GetData("colId");
        string text = "";
        switch(id) {
            case 0: text = item.Name;  break;
            case 1: text = item.Size; break;
            case 2: text = item.Time.ToString();  break;                
        }
        //(cell as Gtk.CellRendererText).Text = text;
        if(item.Highlight) {
            (cell as Gtk.CellRendererText).Markup = 
                            "<span background=\"red\">"+text+"</span>";
        } else {
            (cell as Gtk.CellRendererText).Markup = text;
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以在最左侧添加一个单独的 pixbuf 单元格(例如,与小图标大小相同)以指示选择。选定的行可以用用于背景的颜色的更“纯”(饱和)版本填充它。例如。如果您使用粉红色背景作为高优先级,则可以使用红色作为选择指示器。或者你可以使用一个图标。

    用颜色填充方法来实现:

    1. 按照 Tobias 的建议禁用内置突出显示(“使 STATE_SELECTED 颜色与 STATE_NORMAL 相同”)。
    2. 基于gtk.gdk.Pixbuf 创建一个小部件,允许您创建一个纯色区域,可能使用fill 方法。
    3. 为您的“选择”单元格使用CellRendererPixbuf

    然后,您可以在选择更改时为“选择单元格”着色或取消着色以指示选择了哪一行,或显示图标(例如股票代码)。

    请注意,我还没有实现这个,这只是一个想法。它与通常的 GTK 选择指示明显不同,因此(显然)使用您的判断来判断它是否可用。

    【讨论】:

    • 他还可以使用 pixbuf 来指示优先级,而不是摆弄行颜色。大多数 Mac 应用程序将两者结合起来:选择会覆盖背景,但一列中的点除外。
    • 我完全没有想到这一点:PI 记得我曾经使用的一个邮件阅读器在一列中几乎没有“向上”、“向下”、“向上”和“向下”箭头符号指明优先级。
    • 我也想过用pixbuf来显示颜色。这可能是最好的选择,因为我希望选择不会覆盖图像。
    【解决方案3】:

    不知道闪烁是什么意思。边框需要继承 TreeView。

    我会让 STATE_SELECTED 颜色与 STATE_NORMAL 相同以禁用内置突出显示。然后在每一列上设置一个 data_func 并根据它是否在选择中更改单元格渲染器上的一些颜色。

    您可能已经出于优先考虑这样做了,所以只需将颜色与某行相乘以突出显示一行。

    【讨论】:

    • 当我将 STATE_SELECTED 设置为 STATE_NORMAL 颜色时,它不会禁用它,而是将颜色设置为相同,在本例中为白色。
    • 抱歉,没试过。我认为那时不存在透明色。
    【解决方案4】:

    问题已过时,但其他人可能有用... 对于完全禁用选择并在树中制作悬停效果: 1. 在树中禁用系统选择:

      _treeView.Selection.Mode = SelectionMode.None;
    
    1. 处理 MotionNotifyEvent 事件:

      [ConnectBefore]
      private void TreeViewOnMotionNotifyEvent(object o, MotionNotifyEventArgs args)
      {
          TreePath treePath;
          TreeIter iter;
      
          int x = Convert.ToInt32(args.Event.X);
          int y = Convert.ToInt32(args.Event.Y);
      
          _treeView.GetPathAtPos(x, y, out treePath);
          _treeView.Model.GetIter(out iter, treePath);
      
          BindObject fieldModel = CellUtil.GetModelValue(_treeView.Model, iter, 1) as BindObject;
      
          HoverLine = _vievModel.BindObjectCollection.IndexOf(fieldModel);
      }
      
    2. 在 SetCellDataFunc 方法中:

      BindObject fieldModel = CellUtil.GetModelValue(treeModel, iter, 1) as BindObject;
      int rowCount = _vievModel.BindObjectCollection.IndexOf(fieldModel);
      
      if (HoverLine == rowCount)
      {
              cellRenderer.CellBackgroundGdk = ThemeUtility.GdkOddSelectionColor; //Your selection color
      }
      else
      {
              cellRenderer.CellBackgroundGdk = ThemeUtility.SystemSelectionColor; //Your system selection color
      }
      ...
      

    【讨论】:

      【解决方案5】:

      调用 ModifyBase 和 ModifyText 对我有用。仅调用 ModifyBase 会将文本颜色更改为白色

      GTK C# 中的示例:

      treeViewList.ModifyBase(StateType.Selected, treeViewList.Style.Base(StateType.Normal)); treeViewList.ModifyText(StateType.Selected, treeViewList.Style.Text(StateType.Normal));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-06-19
        • 1970-01-01
        • 2020-08-29
        • 2023-03-28
        • 2021-11-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多