QTableView 和 Horizo​​ntalHeader()->restoreState()

Posted

技术标签:

【中文标题】QTableView 和 Horizo​​ntalHeader()->restoreState()【英文标题】:QTableView and horizontalHeader()->restoreState() 【发布时间】:2009-07-22 04:13:00 【问题描述】:

我无法缩小这个错误的范围,但是我似乎有以下问题:

saveState()horizontalHeader() 重启应用 修改模型使其少一列 restoreState() 现在,由于某种原因,headerview 的状态完全混乱了。我无法显示或隐藏任何新列,也无法恢复合理的状态

我知道,这不是很详细,但我希望其他人以前也遇到过这个问题。

【问题讨论】:

如果你有 PyQt4,我可以在这里重现问题:codepad.org/SUl44mvp 依次执行每个按钮。 嗯,上面的代码没有重现确切的问题。 【参考方案1】:

对于 QMainWindow,save/restoreState 采用版本号。 QTableView's restoreState() 没有,所以你需要自己管理这个案例。

如果您想在模型不匹配的情况下恢复状态,您有以下选择:

在保存时将状态与模型中存在的列列表一起存储,这样您就可以避免在列不匹配时从数据中恢复,并恢复为默认大小写 实现您自己的 save/restoreState 函数来处理这种情况(呃) 添加一个代理模型,该模型为正在恢复的状态提供虚假/虚拟列,然后删除这些列。

【讨论】:

【参考方案2】:

我个人从不在任何 Qt 小部件中使用 saveState()/restoreState(),因为它们只是返回一个二进制 blob。我希望我的配置文件是人类可读的,具有简单的类型。这也消除了这些问题。

此外,QHeaderView 有一个顽皮的问题,即restoreState()(或等效项)只有在模型已经设置好之后才对我有用,然后再过一段时间。我最终连接到QHeaderView::sectionCountChanged() 信号并在从它调用的插槽中设置状态。

【讨论】:

当然,我很乐意,但我很确定 QHeaderView 没有公开足够的信息让我做与 saveState 一样的事情 :-(【参考方案3】:

这是我使用 Boost Serialization 制作的解决方案。

它或多或少地处理新的和删除的列。适用于我的用例。

  // Because QHeaderView sucks
  struct QHeaderViewState
  
    explicit QHeaderViewState(ssci::CustomTreeView const & view):
      m_headers(view.header()->count())
    
      QHeaderView const & headers(*view.header());
      // Stored in *visual index* order
      for(int vi = 0; vi < headers.count();++vi)
      
        int           li     = headers.logicalIndex(vi);
        HeaderState & header = m_headers[vi];

        header.hidden               = headers.isSectionHidden(li);
        header.size                 = headers.sectionSize(li);
        header.logical_index        = li;
        header.visual_index         = vi;
        header.name                 = view.model()->headerData(li,Qt::Horizontal).toString();
        header.view                 = &view;
      
      m_sort_indicator_shown   = headers.isSortIndicatorShown();
      if(m_sort_indicator_shown)
      
        m_sort_indicator_section = headers.sortIndicatorSection();
        m_sort_order             = headers.sortIndicatorOrder();
      
    

    QHeaderViewState()

    template<typename Archive>
    void serialize(Archive & ar, unsigned int)
    
      ar & m_headers;
      ar & m_sort_indicator_shown;
      if(m_sort_indicator_shown)
      
        ar & m_sort_indicator_section;
        ar & m_sort_order;
      
    

    void
    restoreState(ssci::CustomTreeView & view) const
    
      QHeaderView & headers(*view.header());

      const int max_columns = std::min(headers.count(),
                                       static_cast<int>(m_headers.size()));      

      std::vector<HeaderState> header_state(m_headers);
      std::map<QString,HeaderState *> map;
      for(std::size_t ii = 0; ii < header_state.size(); ++ii)
        map[header_state[ii].name] = &header_state[ii];

      // First set all sections to be hidden and update logical
      // indexes
      for(int li = 0; li < headers.count(); ++li)
      
        headers.setSectionHidden(li,true);
        std::map<QString,HeaderState *>::iterator it =
          map.find(view.model()->headerData(li,Qt::Horizontal).toString());
        if(it != map.end())
          it->second->logical_index = li;
      

      // Now restore
      for(int vi = 0; vi < max_columns; ++vi)
      
        HeaderState const & header = header_state[vi];
        const int li = header.logical_index;
        SSCI_ASSERT_BUG(vi == header.visual_index);
        headers.setSectionHidden(li,header.hidden);
        headers.resizeSection(li,header.size);
        headers.moveSection(headers.visualIndex(li),vi);
      
      if(m_sort_indicator_shown)
        headers.setSortIndicator(m_sort_indicator_section,
                                 m_sort_order);
    

    struct HeaderState
    
      initialize<bool,false>  hidden;
      initialize<int,0>       size;
      initialize<int,0>       logical_index;
      initialize<int,0>       visual_index;
      QString                 name;
      CustomTreeView const  *view;

      HeaderState():view(0)

      template<typename Archive>
      void serialize(Archive & ar, unsigned int)
      
        ar & hidden & size & logical_index & visual_index & name;
      
    ;

    std::vector<HeaderState> m_headers;
    bool                     m_sort_indicator_shown;
    int                      m_sort_indicator_section;
    Qt::SortOrder            m_sort_order; // iff m_sort_indicator_shown
  ;

【讨论】:

【参考方案4】:

如果您更改模型,我希望它会损坏!这些函数直接保存和恢复私有类成员变量,无需任何健全性检查。尝试恢复状态,然后更改模型。

【讨论】:

我也试过了,但是当我更改模型时,所有以前的标题视图状态都消失了! 我希望是这样。一个模型的视图应该如何自动适应不同的模型? Qt 库知道新部分之间的关​​系。【参考方案5】:

在遇到相同问题后,我正在尝试为 Qt 5.6.2 解决此问题。看 this link for a Qt patch under review,这使得 restoreState() 处理保存状态下的节数(例如列)与当前视图中的节数不匹配的情况。

【讨论】:

始终欢迎提供指向潜在解决方案的链接,但请add context around the link,以便您的其他用户知道它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。考虑到仅仅是指向外部站点的链接是Why and how are some answers deleted? 的一个可能原因。

以上是关于QTableView 和 Horizo​​ntalHeader()->restoreState()的主要内容,如果未能解决你的问题,请参考以下文章

因为用户同时依赖于 intl ^0.16.1 和 Horizo​​ntal_calendar_widget ^1.0.2,版本解决失败 [关闭]

HTML jQuery Horizo​​ntal Accordion

我啥时候应该使用 layout_centerHorizo​​ntal=true 和gravity="center_horizo​​natal" 和foregroundGravity

Django 管理员的 filter_horizo​​ntal (& filter_vertical) 不工作

React Native中带有粘性标题的Sectionlist Horizo​​ntal?

Vertical RecyclerView 中的 Horizo​​ntal RecyclerViews 丢失位置/状态