自定义QListWidget的多重选择

时间:2012-05-10 06:15:01

标签: qt qlistwidget multipleselection custom-sections

我有基于拆分器视图的​​Qt应用程序:左侧是包含可以选择的文件的QListWidget;选定文件的内容以适当的格式显示在分割器的右侧。这部分工作正常。

我现在需要添加比较功能:如果在QListWidget中选择了一个项目,则其内容显示在右侧;如果选择了另一个项目而不是我想显示差异结果。 (事情比这更复杂,因为不是所有的项目都可以差异化。)

我想要做的是保持一个选择功能,但是也只启用 CTRL +鼠标点击进行第二次选择。我尝试使用QAbstractItemView :: ExtendedSelection,然后过滤掉Shift和鼠标拖动,但没有运气的方法:虽然我可以用keyPressEvent()捕获Shift键,但我无法阻止选择(我希望只是放弃事件就足够了);至于拖动,我使用mouseMoveEvent()希望在状态更改为DragSelectingState时丢弃事件但是也不起作用。

然后我考虑坚持单一选择,但右键单击第二项打开上下文菜单 - 右键单击​​确实发出itemSelectionChanged()信号,我还没弄清楚该怎么办,因为我没有知道右键单击了哪个项目。

打开任何其他不涉及添加其他UI元素的广告素材建议 - 我无法使用任何额外的按钮,组合框等。

1 个答案:

答案 0 :(得分:0)

仍然没有弄清楚如何将QListWidget中的选择限制为只有一个或两个,但右键单击第二个项目上的上下文菜单。

只需将选择模式设置为QAbstractItemView :: SingleSelection,然后重新实现mousePressEvent()和contextMenuEvent()。

class MyListView : public QListWidget
{
  Q_OBJECT

  public:
    ListView();
    virtual ~ListView() {}

    /** Add item to the list. 
        @param itemName Item's display name.
        @param itemHandle Value to return if item selected.
    */
    void AddItem(const QString itemName, const quint32 itemHandle);

  private slots:
    void slot_ItemSelectionChanged(void);
    void slot_Option1(void);
    void slot_Option1(void);

  signals:
    void signal_ItemSelectionChanged(const qint32 itemHandle);

  private:
    void mousePressEvent(QMouseEvent* mousePressEvent);
    void contextMenuEvent(QContextMenuEvent* menuEvent);

    QListWidgetItem *m_selectedItem;        ///< Pointer to the currently selected item.
    QListWidgetItem *m_rightClickedItem;    ///< Pointer to right-clicked item in the list.
    QAction* m_menuOption1;                 ///< Menu option 1.
    QAction* m_menuOption2;                 ///< Menu option 2.
    QMenu* m_myListContextMenu;             ///< Menu with all List View menu actions.
};

MyListView::MyListView()
{
  setSelectionMode(QAbstractItemView::SingleSelection);

  // create my context menu with 2 options
  m_menuOption1 = new QAction(tr("option 1"), this);
  m_menuOption1 ->setEnabled(true);

  m_menuOption2 = new QAction(tr("option 2"), this);
  m_menuOption2 ->setEnabled(true);

  m_myListContextMenu = new QMenu(this);
  m_myListContextMenu ->addAction(m_menuOption1);
  m_myListContextMenu ->addAction(m_menuOption2);

  bool allConnected = true;
  // process primary selection
  allConnected &= connect(this, SIGNAL(itemSelectionChanged(void)), this, SLOT(slot_ItemSelectionChanged(void)));
  // process menu option 1
  allConnected &= connect(m_menuOption1, SIGNAL(triggered()), this, SLOT(slot_Option1()));
  // process menu option 2
  allConnected &= connect(m_menuOption2, SIGNAL(triggered()), this, SLOT(slot_Option2()));

  if (!allConnected )
  {
    assert(0);
  }
}

void ListView::slot_ItemSelectionChanged(void)
{
  if (currentItem() != m_selectedItem)
  {
    m_selectedItem = currentItem();
    emit signal_ItemSelectionChanged(m_selectedItem->type());
  }
} // end of method slot_ItemSelectionChanged()

void MyListView::contextMenuEvent(QContextMenuEvent* menuEvent)
{
  m_rightClickedItem = itemAt(menuEvent->pos());

  // do my prep stuff here specific to right-clicked item 
  // in case one of menu options gets selected

  m_listMenu->exec(menuEvent->globalPos());
} // end of method contextMenuEvent()

void MyListView::mousePressEvent(QMouseEvent* mousePressEvent)
{
  // drop right mouse button event as it would otherwise cause a change of selection
  if (!(mousePressEvent->buttons() & Qt::RightButton))
  {
    QListWidget::mousePressEvent(mousePressEvent);
  }
} // end of method mousePressEvent()