Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
15 / 11 / 4
Регистрация: 03.08.2019
Сообщений: 209
1

2д лего. QGraphicsItemGroup?

19.06.2021, 14:43. Показов 1701. Ответов 5

Author24 — интернет-сервис помощи студентам
Здравствуйте

Программа лего, вид с боку

Я хочу с помощью класса (detail_4) группировать блоки (block_2) в деталь определенной формы, но не могу понять некоторый моменты:
когда создаю QList в mainwindow.cpp, затем scene->createItemGroup(group) - группа создается, но я даже не понимаю как теперь получить указать на данную группу
внутри detail_4 создать группу мне не удается

main.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
#include "mainwindow.h"
 
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


block_2.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef BLOCK_2_H
#define BLOCK_2_H
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>
 
class Block_2 : /*public QObject,*/ public QGraphicsItem
{
    //Q_OBJECT
public: //Передаются размеры Блока:
    Block_2(int W=32, int H=32/*, QObject *parent = 0*/);
    ~Block_2();
 
protected:
    QRectF boundingRect() const;
    void paint(QPainter *painter,
               const QStyleOptionGraphicsItem *option,
                                   QWidget *widget);
 
private:
    int wBlock, hBlock;//Размеры
    QBrush brush;
    QPen pen, selectPen;
    bool blockCaptured {false};//Блок захвачен?
 
    //вставляемости (по направлениям света):
    int N{1}; //North - Север
    int S{-1}; //South - Юг
    int E{0}; //East - Восток
    int W{0}; //West - Запад
 
};
#endif // BLOCK_2_H



block_2.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QCursor>
#include <QKeyEvent>
#include "block_2.h"
 
#include <iostream>
 
Block_2::Block_2(int W, int H/*, QObject *parent*/)
    /*: QObject(parent), QGraphicsItem()*/
{
    this->wBlock = W;
    this->hBlock = H;
 
    pen.setColor(Qt::darkRed);
    pen.setWidth(1);
 
    selectPen.setColor(Qt::black);
    selectPen.setWidth(3);
 
    //brush.setColor(qRgb(230,0,0));
    brush.setColor(Qt::lightGray);
    brush.setStyle(Qt::SolidPattern);
    //brush.setStyle(Qt::Dense3Pattern);
 
    //вставляемости:
    /*
    this->N = 1;
    this->S = -1;
    this->E = 0;
    this->W = 0;
    */
 
    qDebug() << "рисуется блок";
}
 
Block_2::~Block_2() {}
 
 
QRectF Block_2::boundingRect() const
{
    //Область занятая Блоком:
    return QRectF(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
}
 
void Block_2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //Устанавливаем перо:
    if (this->isSelected()) painter->setPen(selectPen);
    else painter->setPen(pen);
 
    painter->setBrush(brush); //устанавливаем кисть
 
//(upd) перенести лэндинг блока в отдельную область?
    //Рисуем Блок в стандартной позиции (центр в (0; 0))
    //painter->drawRect(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
    painter->drawRect(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
    //painter->drawRect(0, 0, wBlock*2, hBlock*2);
 
 
/*
//добавляем сетку (upd)
    painter->setBrush(Qt::black);
    for (int i{0}; i<16; i=i+16)
    {
        painter->drawLine(-i*2+2, -hBlock+2, -i*2+2, hBlock-2); //в минус от центра - вертикальные
        painter->drawLine(i*2-2, -hBlock+2, i*2-2, hBlock-2); //в плюс от центра - вертикальные
 
        painter->drawLine(-wBlock+2, -i+2, wBlock-2, -i+2); //в минус от центра - горизонтальные
        painter->drawLine(-wBlock+2, i-2, wBlock-2, i-2); //в плюс от центра - горизонтальные
    }
*/
 
    Q_UNUSED(option);
    Q_UNUSED(widget);
}



detail_4.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef DETAIL_4_H
#define DETAIL_4_H
#include <QGraphicsItem>
#include <block_2.h>
 
class Detail_4 :public QGraphicsItemGroup
{
public:
    Detail_4(bool geometry[3][3]);
    ~Detail_4();
 
protected:
    //QRectF boundingRect() const;
    /*
    void paint(QPainter *painter,
               const QStyleOptionGraphicsItem *option,
                                   QWidget *widget);
    */
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
 
private:
    QGraphicsItemGroup* group;
 
    bool geometry[3][3];
 
    int wBlock, hBlock;//Размеры
    QBrush brush;
    QPen pen, selectPen;
    bool blockCaptured {false};//Блок захвачен?
 
    //вставляемости (по направлениям света):
    int N{1}; //North - Север
    int S{-1}; //South - Юг
    int E{0}; //East - Восток
    int W{0}; //West - Запад
};
#endif // DETAIL_4_H



detail_4.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "detail_4.h"
 
//где то по 2 раза подключил
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QCursor>
#include <QKeyEvent>
 
Detail_4::Detail_4(bool geometry[3][3])
    : QGraphicsItemGroup()
{
 
    QList <QGraphicsItem*> group_list;
 
    for(int i{}; i<3; i++) //проход строк (по y)
    {
        for(int n{}; n<3; n++) //проход столбов (по x)
        {
            if(geometry[i][n]==1)
            {
                //addToGroup(new Block());
                QGraphicsItem* newBlock = new Block_2();
                newBlock->setPos(n*32, i*32);
                //newBlock->setY(i*50);
                addToGroup(newBlock);
                //scene()->removeItem(newBlock);
                //group_list.append(newBlock);
            }
        }
    }
 
    setFlags(QGraphicsItem::ItemIsMovable);
 
 
}
 
Detail_4::~Detail_4(){};
 
 
void Detail_4::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
   if(event->button() == Qt::LeftButton)
   {
        blockCaptured = true; //Захват
        this->setCursor(QCursor(Qt::ClosedHandCursor));
        this->setFlag(QGraphicsItem::ItemIsSelectable);
          //Снимаем выделение с ранее выделенных:
          QList<QGraphicsItem*> selected = this->scene()->selectedItems();
          foreach (QGraphicsItem* item, selected)
                     item->setSelected(false);
        this->setSelected(true);//Выделяем новый блок
 
          //qDebug() << this;
   }
}
 
void Detail_4::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    //Перенос мышкой:
    if (blockCaptured) //Пересчет из локальных в координаты сцены:
        this->setPos(mapToScene(event->pos()));
 
    qDebug() << "тащим" << this;
 
    QList<QGraphicsItem*> collidingWith = scene()->collidingItems(this);
 
    //qDebug() << "это" << this;
    //qDebug() << "с этим" << collidingWith2;
 
    qDebug() << "тащим " << this;
    qDebug() << "столкновение с " << collidingWith;
 
    //bool check1;
    //check1 = this->collidesWithItem();
}
 
void Detail_4::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    //if (blockCaptured)
    //{
        blockCaptured = false;
           this->setCursor(QCursor(Qt::ArrowCursor));//Восстановили курсор
 
     //}
   Q_UNUSED(event);
}



mainwindow.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QGraphicsScene>
//class Cloud;
 
namespace Ui { class MainWindow; }
 
class MainWindow : public QMainWindow
{  Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private slots:
    void on_pushBtnAdd1_clicked();
    void on_pushBtnAdd2_clicked();
    void on_pushBtnAdd3_clicked();
 
private:
    Ui::MainWindow *ui;
    QGraphicsScene *scene; //Сцена
 
//_потом заменю, пока это ключи
    //int x{0}, y{0};
 
    //Размеры основной части сцены и поля (допустим 20х20):
    //_сцена от центра, поэтому цифры х2 s= размеры
 
    int w{720},h{480}; //размеры сцены
 
    //int mw{5},mh{5}; //маргины (пока как часть сцены (рамки офнуль))
 
    int wBlock{32}, hBlock{32};//Размеры строительных Блоков
 
 
};
#endif // MAINWINDOW_H



mainwindow.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <QList>
#include "mainwindow.h"
#include "ui_mainwindow.h"
//#include "cloud.h"
#include "detail_4.h"
 
#include <QDebug>
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    scene = new QGraphicsScene(this);//Создаем сцену
    scene->setItemIndexMethod(QGraphicsScene::NoIndex); // настраиваем индексацию элементов
 
    //---------------
    //ui->graphicsView->resize(2*(w+mw),2*(h+mh));  /// Устанавливаем размер graphicsView
    ui->graphicsView->resize(w,h);
    ui->graphicsView->setScene(scene);  /// Устанавливаем графическую сцену в graphicsView
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);    /// Устанавливаем сглаживание
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); /// Отключаем скроллбар по вертикали
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); /// Отключаем скроллбар по горизонтали
    //ui->graphicsView->setFixedSize(2*(w+mw),2*(h+mh)); ///Фиксируем размер области отображения
    ui->graphicsView->setFixedSize(w,h);
    ui->graphicsView->setCacheMode(QGraphicsView::CacheBackground); // Кэш фона
 
    ///Установили режим обновления в зоне прямоугольника, охватывающего все элементы:
    ui->graphicsView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
 
    //scene->setSceneRect(-(w+mw),-(h+mh),2*(w+mw),2*(h+mh)); /// Устанавливаем область графической сцены
    scene->setSceneRect(0, 0, w, h);
 
    /*
//добавляем сетку (upd) - конфликты колизии
    for (int i{0}; i<160; i=i+16)
    {
        scene->addLine(-i*2, -h, -i*2, h, QPen(Qt::gray)); //в минус от центра - вертикальные
        scene->addLine(i*2, -h, i*2, h, QPen(Qt::gray)); //в плюс от центра - вертикальные
 
        scene->addLine(-w, -i, w, -i, QPen(Qt::gray)); //в минус от центра - горизонтальные
        scene->addLine(-w, i, w, i, QPen(Qt::gray)); //в плюс от центра - горизонтальные
    }
    */
 
 
     /* Добавляем линии-органичения рабочей территории в графической сцене */
    /*
    scene->addLine(-w,-h, w,-h, QPen(Qt::black)); //верх
    scene->addLine(-w, h, w, h, QPen(Qt::red)); //низ
    scene->addLine(-w,-h,-w, h, QPen(Qt::black)); //лево
    scene->addLine( w,-h, w, h, QPen(Qt::black)); //право
    */
 
 
 
       //---Создаем и добавляем в сцену подвижный элемент - Облако
       //cloud = new Cloud(-w, w ); //Передали границы плавания Облака
       //int wCloud = cloud->getWidth();
       //scene->addItem(cloud); //Добавляем свой элемент - Облако
       //cloud->setPos(-w +wCloud*0.5 + 1, startYCloud);//Начальная позиция
       //y = h - hBlock*0.55  ; x = -w + wBlock*0.55;
       //timer = new QTimer(this);
       //timer->setInterval(500);
       //timer->start();
       // Подключаем сигнал таймера к слоту окна:
       //connect(timer, &QTimer::timeout, this, &MainWindow::slotTicTimer);
 
 
       //scene->selectionArea(false);
}
 
MainWindow::~MainWindow()
{  delete ui;  delete scene; }
 
void MainWindow::on_pushBtnAdd1_clicked()
{
    //Добавление и укладка нового блока:
    QGraphicsItem * newItem = new Block_2(wBlock, hBlock);
 
    newItem->setPos(this->wBlock/2, this->hBlock/2);
    scene->addItem(newItem);//Добавление в сцену
}
 
void MainWindow::on_pushBtnAdd2_clicked()
{
    bool geo[3][3] =
    {
        {0, 0, 0},
        {0, 0, 0},
        {1, 1, 1}
    };
 
    QGraphicsItem * newItem = new Detail_4(geo);
 
    newItem->setPos(20,20);
    newItem->shape();
    scene->addItem(newItem);//Добавление в сцену
 
    qDebug() << newItem;
}
 
void MainWindow::on_pushBtnAdd3_clicked()
{
    QGraphicsItem * newItem = new Block_2(wBlock, hBlock);
    newItem->setPos(this->wBlock, this->hBlock);
 
    QGraphicsItem * newItem2 = new Block_2(wBlock, hBlock);
    newItem->setPos(this->wBlock*2, this->hBlock*2);
 
    QGraphicsItem * newItem3 = new Block_2(wBlock, hBlock);
    newItem->setPos(this->wBlock*4, this->hBlock*4);
 
    QList <QGraphicsItem*> group;
 
    group.append(newItem);
    group.append(newItem2);
    group.append(newItem3);
 
    scene->createItemGroup(group);
 
    qDebug() << group;
}



mainwindow.ui
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushBtnAdd1">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>0</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>block</string>
    </property>
   </widget>
   <widget class="QGraphicsView" name="graphicsView">
    <property name="geometry">
     <rect>
      <x>60</x>
      <y>90</y>
      <width>256</width>
      <height>192</height>
     </rect>
    </property>
   </widget>
   <widget class="QPushButton" name="pushBtnAdd2">
    <property name="geometry">
     <rect>
      <x>130</x>
      <y>0</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>detail</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushBtnAdd3">
    <property name="geometry">
     <rect>
      <x>250</x>
      <y>0</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>group</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>


Добавлено через 2 минуты
Если кто может помогите с написанием класса detail_4. именно этот класс я предполагаю использовать как движимую деталь сцены для "строительства". "физически" деталь состоит из блоков, а пазы для крепления так же остаются у блоков. по сути, деталь - это группа блоков
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.06.2021, 14:43
Ответы с готовыми решениями:

QGraphicsItemGroup
Привет всем. я так понимаю QGraphicsItemGroup это группировка всех элементов в одно, но когда я...

Наследник QGraphicsItemGroup: возможно ли?
Пыталась создать свой класс на основе QGraphicsItemGroup - выдает ошибки. Что то не нравится ему с...

Создание лего
День добрый, только начал изучать Юнити, хочу сделать игру на подобии лего как майнкрафт, то есть...

программа для роботов Лего на С++
Составить программу на С++ для роботов Лего, чтобы при загрузки программы в NXT она работала....

5
15 / 11 / 4
Регистрация: 03.08.2019
Сообщений: 209
19.06.2021, 21:40  [ТС] 2
в моем представлении деталь состоит из блоков:

block.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef BLOCK_2_H
#define BLOCK_2_H
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>
 
class Block_2 : /*public QObject,*/ public QGraphicsItem
{
    //Q_OBJECT
public: //Передаются размеры Блока:
    Block_2(int W=32, int H=32/*, QObject *parent = 0*/);
    ~Block_2();
 
protected:
    QRectF boundingRect() const;
    void paint(QPainter *painter,
               const QStyleOptionGraphicsItem *option,
                                   QWidget *widget);
 
private:
    int wBlock, hBlock;//Размеры
    QBrush brush;
    QPen pen, selectPen;
    bool blockCaptured {false};//Блок захвачен?
 
    //вставляемости (по направлениям света):
    int N{1}; //North - Север
    int S{-1}; //South - Юг
    int E{0}; //East - Восток
    int W{0}; //West - Запад
 
};
#endif // BLOCK_2_H


block.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QCursor>
#include <QKeyEvent>
#include "block_2.h"
#include <QDebug>
 
#include <iostream>
 
Block_2::Block_2(int W, int H/*, QObject *parent*/)
    /*: QObject(parent), QGraphicsItem()*/
{
    this->wBlock = W;
    this->hBlock = H;
 
    pen.setColor(Qt::darkRed);
    pen.setWidth(1);
 
    //selectPen.setColor(Qt::black);
    //selectPen.setWidth(3);
 
    //brush.setColor(qRgb(230,0,0));
    brush.setColor(Qt::lightGray);
    brush.setStyle(Qt::SolidPattern);
    //brush.setStyle(Qt::Dense3Pattern);
 
    //вставляемости:
    /*
    this->N = 1;
    this->S = -1;
    this->E = 0;
    this->W = 0;
    */
 
    qDebug() << "рисуется блок";
}
 
Block_2::~Block_2() {}
 
 
QRectF Block_2::boundingRect() const
{
    //Область занятая Блоком:
    return QRectF(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
}
 
void Block_2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //Устанавливаем перо:
    if (this->isSelected()) painter->setPen(selectPen);
    else painter->setPen(pen);
 
    painter->setBrush(brush); //устанавливаем кисть
 
//(upd) перенести лэндинг блока в отдельную область?
    //Рисуем Блок в стандартной позиции (центр в (0; 0))
    //painter->drawRect(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
    painter->drawRect(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
    //painter->drawRect(0, 0, wBlock*2, hBlock*2);
 
 
/*
//добавляем сетку (upd)
    painter->setBrush(Qt::black);
    for (int i{0}; i<16; i=i+16)
    {
        painter->drawLine(-i*2+2, -hBlock+2, -i*2+2, hBlock-2); //в минус от центра - вертикальные
        painter->drawLine(i*2-2, -hBlock+2, i*2-2, hBlock-2); //в плюс от центра - вертикальные
 
        painter->drawLine(-wBlock+2, -i+2, wBlock-2, -i+2); //в минус от центра - горизонтальные
        painter->drawLine(-wBlock+2, i-2, wBlock-2, i-2); //в плюс от центра - горизонтальные
    }
*/
 
    Q_UNUSED(option);
    Q_UNUSED(widget);
}


я бы хотел чтобы с кнопки:

часть mainwindow.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
void MainWindow::on_pushBtnAdd3_5_clicked()
{
    bool geo3[3] =
    {1, 1, 1};
    Detail_6(geo3, scene);
 
}

мы формировали деталь:

detail.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef DETAIL_6_H
#define DETAIL_6_H
 
 
#include <QGraphicsItem>
 
#include <QPainter>
#include <QDebug>
 
class Detail_6: public QGraphicsItemGroup
{
public:
    Detail_6(bool geometry[3], QGraphicsScene* _scene);
    ~Detail_6();
 
protected:
    //QRectF boundingRect() const;
    /*
    void paint(QPainter *painter,
               const QStyleOptionGraphicsItem *option,
                                   QWidget *widget);
    */
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
 
private:
    bool geometry[3];
 
    /*
    int wBlock, hBlock;//Размеры
    QBrush brush;
    QPen pen, selectPen;
    bool blockCaptured {false};//Блок захвачен?
*/
 
 
};
 
#endif // DETAIL_6_H

detail.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "detail_6.h"
#include "block_2.h"
 
#include "block.h"
 
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QCursor>
#include <QKeyEvent>
 
Detail_6::Detail_6(bool geometry[3], QGraphicsScene* _scene)
    //:QGraphicsItemGroup()
{
    QList <QGraphicsItem*> group_list;
    for(int n{}; n<3; n++) //проход столбов (по x)
    {
        if(geometry[n]==1)
        {
            //addToGroup(new Block());
            QGraphicsItem* newBlock = new Block_2();
            newBlock->setX(n*32);
            //newBlock->setY(i*50);
            //addToGroup(newBlock);
            group_list.append(newBlock);
        }
    }
    QGraphicsItemGroup* group;
 
    group = _scene->createItemGroup(group_list);
    group->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
    group->setPos(50, 50);
    qDebug() << "формируется деталь" << group;
}
 
Detail_6::~Detail_6(){};
 
 
/*
QRectF Detail_4::boundingRect() const
{
    //Область занятая Блоком:
    return QRectF(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
}
*/
 
/*
void Detail_4::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //Устанавливаем перо:
    if (this->isSelected()) painter->setPen(selectPen);
    else painter->setPen(pen);
 
    painter->setBrush(brush); //устанавливаем кисть
 
//(upd) перенести лэндинг блока в отдельную область?
    //Рисуем Блок в стандартной позиции (центр в (0; 0))
    //painter->drawRect(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
    painter->drawRect(-wBlock*0.5,-hBlock*0.5,wBlock,hBlock);
    //painter->drawRect(0, 0, wBlock*2, hBlock*2);
 
 
    qDebug() << "рисуется деталь";
 
    Q_UNUSED(option);
    Q_UNUSED(widget);
}
*/
 
void Detail_6::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
   if(event->button() == Qt::LeftButton)
   {
        //blockCaptured = true; //Захват
        this->setCursor(QCursor(Qt::ClosedHandCursor));
        this->setFlag(QGraphicsItem::ItemIsSelectable);
          //Снимаем выделение с ранее выделенных:
          QList<QGraphicsItem*> selected = this->scene()->selectedItems();
          foreach (QGraphicsItem* item, selected)
                     item->setSelected(false);
        this->setSelected(true);//Выделяем новый блок
 
          qDebug() << this<< "fdsf";
 
 
 
   }
}
 
void Detail_6::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
 
    qDebug() << event->pos();
 
    //Перенос мышкой:
    //if (blockCaptured) //Пересчет из локальных в координаты сцены:
        this->setPos(mapToScene(event->pos()));
 
 
 
    qDebug() << "тащим" << this;
 
    QList<QGraphicsItem*> collidingWith = scene()->collidingItems(this);
 
    //qDebug() << "это" << this;
    //qDebug() << "с этим" << collidingWith2;
 
    qDebug() << "тащим " << this;
    qDebug() << "столкновение с " << collidingWith;
 
    //bool check1;
    //check1 = this->collidesWithItem();
}
 
void Detail_6::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    //if (blockCaptured)
    //{
        //blockCaptured = false;
           this->setCursor(QCursor(Qt::ArrowCursor));//Восстановили курсор
 
     //}
   Q_UNUSED(event);
}


помогите пожалуйста разобраться, правильно ли я вообще формирую деталь? в конструкторе detail я добавляю группу блоков в сцену, но выглядит это как то неестественно, что-ли
и каким образом я могу переопределить "мышиные события" для detail? сейчас ни mousePress ни mouseMove не работают
0
1081 / 685 / 184
Регистрация: 30.03.2021
Сообщений: 2,138
20.06.2021, 03:50 3
Цитата Сообщение от Serg1234321 Посмотреть сообщение
внутри detail_4 создать группу мне не удается
QGraphicsItemGroup* group; это надо в .h файл в класс детали переместить и тогда
C++ (Qt)
1
2
Detail_4 *detail = new Detail_4(geometry, scene);
QGraphicsItemGroup *group = detail.group; //указатель на группу
Цитата Сообщение от Serg1234321 Посмотреть сообщение
в конструкторе detail я добавляю группу блоков в сцену, но выглядит это как то неестественно, что-ли
таки да, если у меня это взяли то сорри-наговнокодил я, а по другому не выходило
получается если в конструкторе Detail
group = _scene->createItemGroup(group_list); создаем группу на сцене
это не имеет никакого отношения к событиям мыши обьекта класса Detail, поэтому я пробовал переопределить их в кастомном
классе порожденном от QGraphicsItemGroup, класс детали наследовать от QGraphicsItem, и в нем добавлять на сцену группу с переопределенными ивентами мыши, но это тоже не сработало.

думаю можно попробовать создавать группу не в конструкторе детали а непосредственно при ее создании
QList <QGraphicsItem*> group_list; переносим в .h как поле класса

все это убираем
QGraphicsItemGroup* group;
group = _scene->createItemGroup(group_list);
group->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
group->setPos(50, 50);
там где создается деталь
C++ (Qt)
1
2
3
4
5
6
7
8
 
bool geometry[3][3]={...};
Detail *detail = new Detail(geometry); // в конструкторе только геометрия
 
detail = static_cast<Detail*>(scene->createItemGroup(detail->group_List));
 
detail ->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
detail ->setPos(50, 50);
попробуйте, я позжее потестю, мб ивенты мыши так заработают

Еще у меня вопрос-зачем Вы под каждую деталь и блок создаете свой класс?
не проще ли будет иметь один универсальный класс? а особенности блока или
детали передавать в конструкторе. Например для детали
Detail(bool geometry[3][3], bool isMovable, bool someProperty);
и в зависимости от этих параметров формировать деталь, но в едином классе

а если так неудобно, то можно иметь базовый класс baseDetail где реализованы
общие моменты для всех деталей и наследование от нужных классов, и уже от
него создавать детали с отличиями
C++ (Qt)
1
2
3
class Detail_1 :public baseDetail{
...
}
0
1081 / 685 / 184
Регистрация: 30.03.2021
Сообщений: 2,138
20.06.2021, 11:56 4
Цитата Сообщение от sdf45 Посмотреть сообщение
думаю можно попробовать создавать группу не в конструкторе детали а непосредственно при ее создании
попробовал этот вариант-еще хуже прежнего , теперь группа даже не распознается по щелчку в пределах ее boundingRect тем способом который прикладываю ниже, но если убрать такое распознавание то группу можно
двигать, она как бы находится на самом нижнем уровне, под всеми своими дочерними итемами-и если их растащить в стороны то можно двигать группу, хотя метки в дебаг она не возвращает, а возвращает пустую строку, тоесть как бы клик по пустому месту...
Да, и обработка событий мыши в таком варианте тоже не работает.

Короче видимо у меня тотальное непонимание механики QGraphicsItemGroup, фантазия закончилась и идей больше нет, много искал в инете по этой теме-тоже нифига не нашел.

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
detail *_detail=new detail;
_detail.setData(1,"detail");
 
void scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
 
    if((pressedItem!=nullptr)
            //&& (pressedItem->data(1).toString()=="detail") //если метка= detail двигаем итем
            )
    {
                pressedItem->setPos(event->scenePos() + m_shiftMouseCoords);
     }
}
 
//определяем итем под курсором, сохраняем его позицию, выводим в дебаг метку итема
void scene::mousePressEvent(QGraphicsSceneMouseEvent *event){
 
    pressedItem =  this->itemAt(event->scenePos().x(), event->scenePos().y(), QTransform());
    if(pressedItem!=nullptr){
        m_shiftMouseCoords = pressedItem->pos() - event->scenePos();
    }
 
    qDebug()<<pressedItem->data(1).toString();
}
0
15 / 11 / 4
Регистрация: 03.08.2019
Сообщений: 209
20.06.2021, 14:10  [ТС] 5
sdf45, да уж, с группами очень непонятно

Цитата Сообщение от sdf45 Посмотреть сообщение
Еще у меня вопрос-зачем Вы под каждую деталь и блок создаете свой класс?
не обращайте внимания, таким образом я веду либо старые версии классов (вдруг что то пригодится), либо пробую альтернативные реализации

Цитата Сообщение от sdf45 Посмотреть сообщение
void scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
if((pressedItem!=nullptr)
            //&& (pressedItem->data(1).toString()=="detail") //если метка= detail двигаем итем
            )
    {
                pressedItem->setPos(event->scenePos() + m_shiftMouseCoords);
     }
}
судя по всему, создание группы лишь усложняет дальнейшую реализацию.
тут вопрос, при вот таком подходе, группа то создается, или все таки нет? почему тогда поведение абсолютно разное если мы создаем группу через scene->createItemGroup(group) и просто через addItem(item)???

реализация через addItem (createItemGroup есть выше):
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
Detail_7::Detail_7(bool geometry[3])
{
         for(int n{}; n<3; n++) //проход столбов (по x)
        {
            if(geometry[n]==1)
            {
                QGraphicsItem* newBlock = new Block_2();
                newBlock->setX(n*32);
                addToGroup(newBlock);
            }
        }
}
0
1081 / 685 / 184
Регистрация: 30.03.2021
Сообщений: 2,138
20.06.2021, 14:27 6
Цитата Сообщение от Serg1234321 Посмотреть сообщение
почему тогда поведение абсолютно разное если мы создаем группу через scene->createItemGroup(group) и просто через addItem(item)???
я уже боюсь что-либо утверждать с этими группами, но по логике поведение должно быть одинаковое, просто и Вы и я делаем ошибки, я пытался создать группу в конструкторе группы через createItemGroup(group) а Вы QGraphicsItemGroup* group; и addItem(item) потому как не напишешь же this=createItemGroup(group)

Предлагаю отказаться от QGraphicsItemGroup до выяснения правильного подхода к нему, и замутить реализацию группы
QGraphicsItem своими руками.
0
20.06.2021, 14:27
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.06.2021, 14:27
Помогаю со студенческими работами здесь

3D Конструктор в стиле лего с облетом камеры
Доброй ночи всем. Возникла необходимость для преподавателя сделать трехмерный конструктор,...

Qt, лего игрушка (2д), трудности с наследованием и "детальками"
Здравствуйте :senor: К чему стремлюсь: лего-стройка, 2д, детали крепятся в пазы (собственно,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
В чем отличие между INNER JOIN и OUTER JOIN
bytestream 22.01.2025
В современных базах данных информация часто распределена между множеством взаимосвязанных таблиц, что делает операции объединения JOIN неотъемлемой частью работы с SQL. Эти операции позволяют. . .
Как сделать первую букву заглавной в JavaScript
bytestream 22.01.2025
JavaScript предоставляет разработчикам множество инструментов для эффективной работы с текстовыми данными. Одной из часто встречающихся задач при обработке строк является преобразование первой буквы. . .
Что такое Big O нотация и алгоритмическая сложность
bytestream 22.01.2025
Введение в алгоритмическую сложность В мире разработки программного обеспечения эффективность алгоритмов играет crucial роль в создании качественных приложений. Алгоритмическая сложность. . .
Как решать конфликты слияния (merge) в Git
bytestream 22.01.2025
Конфликты слияния в системе контроля версий Git возникают в ситуациях, когда две или более ветки разработки содержат несовместимые изменения в одних и тех же участках кода. Эти конфликты представляют. . .
Как использовать регулярные выражения
bytestream 22.01.2025
Регулярные выражения представляют собой мощный инструмент для работы с текстовыми данными, который позволяет осуществлять поиск, проверку и манипуляцию строками на основе определенных шаблонов. Этот. . .
Как выйти из Vim
bytestream 22.01.2025
Vim (Vi IMproved) представляет собой один из самых влиятельных текстовых редакторов в истории компьютерной индустрии, эволюционировавший из своего предшественника Vi, созданного Биллом Джоем в 1976. . .
NoSQL базы данных: что это такое и какие существуют
bytestream 22.01.2025
В современную эпоху цифровой трансформации объемы данных растут экспоненциально, создавая новые вызовы для традиционных систем управления базами данных. NoSQL (Not Only SQL) представляет собой. . .
Обновление исследования от команды MCM (январь 2025 г.)
Programma_Boinc 22.01.2025
Обновление исследования от команды MCM (январь 2025 г. ) Мы продолжаем изучать молекулярные сигнатуры, связанные с раком легких, с текущим фокусом на GCM1, факторе транскрипции, участвующем в. . .
Как работать с Kafka в Go (Golang)
bytestream 22.01.2025
Apache Kafka представляет собой распределенную платформу потоковой передачи данных, которая произвела революцию в области обработки событий и интеграции микросервисов. Эта система, изначально. . .
Как использовать RabbitMQ в Go (Golang)
bytestream 22.01.2025
RabbitMQ представляет собой надежный и широко используемый брокер сообщений, который играет ключевую роль в построении современных распределенных систем и микросервисной архитектуры. В основе работы. . .
Как преобразовать список списков в простой список в Python
bytestream 22.01.2025
При работе с Python разработчики часто сталкиваются с необходимостью обработки сложных структур данных, среди которых особое место занимают вложенные списки. Эти структуры представляют собой списки,. . .
Что такое GUID / UUID и как их создать
bytestream 22.01.2025
В мире разработки программного обеспечения существует постоянная потребность в уникальной идентификации объектов, записей и ресурсов. Эта задача становится особенно актуальной в распределенных. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru