从QGraphicsScene中删除一个QGraphicsItem/QGraphicsObject ?

时间:2023-02-01 13:46:28

I have created Qt GUI application. It consists of QGraphicsScene, and items (QGraphicsItems) are added to them by pressing or triggering pushbuttons. Each item added to the scene are members of different classes derived from QGraphicsItem. Now, my challenge is to delete an added item off the scene through one of the following mechanisms:

我创建了Qt GUI应用程序。它由QGraphicsScene组成,并通过按压或触发按钮将项目(QGraphicsItems)添加到它们中。添加到场景中的每个条目都是来自QGraphicsItem的不同类的成员。现在,我的挑战是通过以下机制之一删除一个添加的项目:

1) Right click an added item, create a context menu, and then use scene->removeItem(addedItem);

1)右键单击添加项,创建上下文菜单,然后使用场景->removeItem(addedItem);

2) Double click the item which deletes the item

2)双击删除项目的项目。

3) Select an item using the flag ItemIsSelectable, and then delete the item by pressing the delete key on the keyboard

3)选择一个使用标记的项目,然后按下键盘上的删除键来删除该项目。

But having said that, as a newbie to Qt, I'm unable to do number 1 since the context menu doesn't show up when right clicked. In the case of number 2, I used signals and slots, a single emitted whenever an item is double clicked, and a slot in the mainWindow absorbs the signal and removes the item. But this way, the programs fails to compile because of the error "duplicate symbol found" when I add a Q_OBJECT macro to the header file of the item's class.

但是我说过,作为Qt的新手,我不能做第一件事,因为上下文菜单在右键单击时不会出现。在数字2的情况下,我使用了信号和插槽,当一个项目被双击时,一个单发射,而主窗口的一个插槽吸收信号并移除该项目。但是这样,程序无法编译,因为当我将Q_OBJECT宏添加到项目类的头文件时,会出现错误“重复的符号”。

So my final option is to select an item on the screen and propane the keyboard signal to delete the item by pressing delete. How can be this done? Please give me advice if any of the above methods can be easily done in case I might be doing it completely wrong.

因此,我的最终选择是在屏幕上选择一个项目,并通过按delete键来删除键盘信号以删除该项。这是怎么做到的呢?请给我一些建议,如果上面的方法可以很容易做,以防我可能做的完全错误。

P.S. : I know there a lot of queries regarding deleting QGraphicsItem off QGraphicsScene, but none of them document a solid answer.

我知道在QGraphicsScene上删除QGraphicsItem有很多问题,但是没有一个可以给出一个可靠的答案。

2 个解决方案

#1


1  

... I'm unable to do number 1 since the context menu doesn't show up when right clicked.

…由于上下文菜单在右键单击时不会出现,所以我无法执行第1项。

There are two possible methods to accomplish this:

有两种可能的方法来实现这一点:

  1. Create a QWidget based menu, attached to the QGraphicsView.
  2. 创建一个基于QWidget的菜单,附加到QGraphicsView。
  3. Create your own menu item, derived from a QGraphicsItem.
  4. 创建您自己的菜单项,从一个QGraphicsItem派生。

Whilst the 2nd method will take more time, it's probably a better system in my opinion, as it will feel more integrated with the item you're deleting in the scene. The first method is also possible and if it's not working, then you could post an example question on SO.

虽然第二种方法需要花费更多的时间,但在我看来,它可能是一个更好的系统,因为它会让你感觉与你在场景中删除的条目更加融合。第一个方法也是可能的,如果它不工作,那么你可以在上面发布一个示例问题。

2, I used signals and slots, ... because of the error "duplicate symbol found" when I add a Q_OBJECT macro to the header file

我用信号和插槽……因为当我在头文件中添加Q_OBJECT宏时,出现了错误的“重复符号”。

It sounds like you're trying to add the signal / slot functionality to a class derived from QGraphicsItem. You don't need to do this. Qt provides the QGraphicsObject class, which you can derive from, instead of QGraphicsItem, if you want signals and slots on items in a QGraphicsScene.

这听起来好像你在尝试将信号/槽功能添加到一个来自QGraphicsItem的类中。你不需要这样做。Qt提供了QGraphicsObject类,您可以从QGraphicsItem派生出QGraphicsObject类,如果您想要在QGraphicsScene中的条目上显示信号和插槽。

propane the keyboard signal to delete the item by pressing delete.

丙烷的键盘信号通过按下删除键来删除。

I assume you mean to 'propagate' keyboard signals. By overriding the QGraphicsScene and its keyPressEvent or keyReleaseEvent, you can get a list of selected items and delete them from the scene. Here's a skeleton example: -

我猜你是想“传播”键盘信号。通过覆盖QGraphicsScene和它的keyPressEvent或keyReleaseEvent,您可以获得所选项目的列表并将它们从场景中删除。这里有一个骨架例子:-。

class MyScene : public QGraphicsScene
{
    protected:
        void keyReleaseEvent(QKeyEvent * keyEvent);
};

void MyScene::keyReleaseEvent(QKeyEvent * keyEvent)
{
    if(keyEvent->key() == Qt::Key_Backspace)
    {
        QList<QGraphicsItem*> selectedItems = selectedItems(); // get list of selected items
        foreach(QGraphicsItem* item, selectedItems)
        {
            removeItem(item);
            delete item;
        }
    }
}

#2


0  

You're seeking a lot of answers, Not so much how to handle QGraphicsItem or QGraphicsScene.

您正在寻找许多答案,而不是如何处理QGraphicsItem或QGraphicsScene。

1) Right click an added item, create a context menu, and then use scene->removeItem(addedItem); here.

1)右键单击添加项,创建上下文菜单,然后使用场景->removeItem(addedItem);在这里。

2) Double click the item, which deletes the item - you'll need to handle double clicks, and hit-testing the QGraphicsItems, you'll have to implement mouseDoubleClickEvent(QMouseEvent *e) and pass e's pos() to this to determine if a QGraphicsItem was clicked or not.

2)双击该项目,删除该项目——您需要处理双击,并对QGraphicsItems进行测试,您将必须实现mouseDoubleClickEvent(QMouseEvent *e),并通过e的pos(),以确定是否单击了QGraphicsItem。

3) Select an item using the flag ItemIsSelectable and then delete the item by pressing the delete key on the keyboard - I'm not sure about the ItemIsSelectable flag. However, you'll need #2. And to learn how to handle keyboard input, by overriding this:

3)选择一个使用标记的物品,然后按下键盘上的delete键来删除该物品,我不确定是否有它的标志。然而,你需要# 2。并且学习如何处理键盘输入,通过重写这个:

void QWidget::keyPressEvent( QKeyEvent *k ){
     switch ( tolower(k->ascii()) ) {
         case '\x08':        \\backspace                       

             break;
         case '\x7F':         \\delete

             break;
     }
 }

There's also the Qt::key enumeration, which has Key_Backspace, and Key_Delete. It can be tested against the QKeyEvent::Key()'s return if you don't like dealing with ASCII character codes.

还有Qt::key enumeration,它有Key_Backspace和Key_Delete。如果您不喜欢处理ASCII字符代码,则可以针对QKeyEvent::Key()返回。

#1


1  

... I'm unable to do number 1 since the context menu doesn't show up when right clicked.

…由于上下文菜单在右键单击时不会出现,所以我无法执行第1项。

There are two possible methods to accomplish this:

有两种可能的方法来实现这一点:

  1. Create a QWidget based menu, attached to the QGraphicsView.
  2. 创建一个基于QWidget的菜单,附加到QGraphicsView。
  3. Create your own menu item, derived from a QGraphicsItem.
  4. 创建您自己的菜单项,从一个QGraphicsItem派生。

Whilst the 2nd method will take more time, it's probably a better system in my opinion, as it will feel more integrated with the item you're deleting in the scene. The first method is also possible and if it's not working, then you could post an example question on SO.

虽然第二种方法需要花费更多的时间,但在我看来,它可能是一个更好的系统,因为它会让你感觉与你在场景中删除的条目更加融合。第一个方法也是可能的,如果它不工作,那么你可以在上面发布一个示例问题。

2, I used signals and slots, ... because of the error "duplicate symbol found" when I add a Q_OBJECT macro to the header file

我用信号和插槽……因为当我在头文件中添加Q_OBJECT宏时,出现了错误的“重复符号”。

It sounds like you're trying to add the signal / slot functionality to a class derived from QGraphicsItem. You don't need to do this. Qt provides the QGraphicsObject class, which you can derive from, instead of QGraphicsItem, if you want signals and slots on items in a QGraphicsScene.

这听起来好像你在尝试将信号/槽功能添加到一个来自QGraphicsItem的类中。你不需要这样做。Qt提供了QGraphicsObject类,您可以从QGraphicsItem派生出QGraphicsObject类,如果您想要在QGraphicsScene中的条目上显示信号和插槽。

propane the keyboard signal to delete the item by pressing delete.

丙烷的键盘信号通过按下删除键来删除。

I assume you mean to 'propagate' keyboard signals. By overriding the QGraphicsScene and its keyPressEvent or keyReleaseEvent, you can get a list of selected items and delete them from the scene. Here's a skeleton example: -

我猜你是想“传播”键盘信号。通过覆盖QGraphicsScene和它的keyPressEvent或keyReleaseEvent,您可以获得所选项目的列表并将它们从场景中删除。这里有一个骨架例子:-。

class MyScene : public QGraphicsScene
{
    protected:
        void keyReleaseEvent(QKeyEvent * keyEvent);
};

void MyScene::keyReleaseEvent(QKeyEvent * keyEvent)
{
    if(keyEvent->key() == Qt::Key_Backspace)
    {
        QList<QGraphicsItem*> selectedItems = selectedItems(); // get list of selected items
        foreach(QGraphicsItem* item, selectedItems)
        {
            removeItem(item);
            delete item;
        }
    }
}

#2


0  

You're seeking a lot of answers, Not so much how to handle QGraphicsItem or QGraphicsScene.

您正在寻找许多答案,而不是如何处理QGraphicsItem或QGraphicsScene。

1) Right click an added item, create a context menu, and then use scene->removeItem(addedItem); here.

1)右键单击添加项,创建上下文菜单,然后使用场景->removeItem(addedItem);在这里。

2) Double click the item, which deletes the item - you'll need to handle double clicks, and hit-testing the QGraphicsItems, you'll have to implement mouseDoubleClickEvent(QMouseEvent *e) and pass e's pos() to this to determine if a QGraphicsItem was clicked or not.

2)双击该项目,删除该项目——您需要处理双击,并对QGraphicsItems进行测试,您将必须实现mouseDoubleClickEvent(QMouseEvent *e),并通过e的pos(),以确定是否单击了QGraphicsItem。

3) Select an item using the flag ItemIsSelectable and then delete the item by pressing the delete key on the keyboard - I'm not sure about the ItemIsSelectable flag. However, you'll need #2. And to learn how to handle keyboard input, by overriding this:

3)选择一个使用标记的物品,然后按下键盘上的delete键来删除该物品,我不确定是否有它的标志。然而,你需要# 2。并且学习如何处理键盘输入,通过重写这个:

void QWidget::keyPressEvent( QKeyEvent *k ){
     switch ( tolower(k->ascii()) ) {
         case '\x08':        \\backspace                       

             break;
         case '\x7F':         \\delete

             break;
     }
 }

There's also the Qt::key enumeration, which has Key_Backspace, and Key_Delete. It can be tested against the QKeyEvent::Key()'s return if you don't like dealing with ASCII character codes.

还有Qt::key enumeration,它有Key_Backspace和Key_Delete。如果您不喜欢处理ASCII字符代码,则可以针对QKeyEvent::Key()返回。