2012-05-10 93 views
1

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

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

我想什么做的是有一个单一的选择能力不变,但随后也使只有 CTRL +鼠标点击第二选择。我尝试使用QAbstractItemView :: ExtendedSelection,然后筛选出Shift和鼠标拖动,但没有这种方法运气:虽然我可以捕获Shift键keyPressEvent()我无法阻止选择(我希望只是放弃事件就足够了);至于拖我用mouseMoveEvent()希望在状态改变为DragSelectingState时删除事件,但也没有工作。

然后,我认为坚持单选,但打开右键单击第二项上下文菜单 - 而右键单击确实发出itemSelectionChanged()信号,我还没有想出如何处理这个,因为我不'不知道哪个项目被右键单击。

打开任何其他创造性的建议不涉及添加额外的UI元素 - 我不能有任何多余的按键,组合框等

回答

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()