@Dogrtt
Qt/Python разработчик

Как поймать сигнал переопределенного QGraphicsPixmapItem в слот главного окна?

Есть кастомный `QGraphicsView`, в нем отлавливаю эвенты мыши, чтобы скалировать и панарамировать изображение. В `QGraphicsScene` лежит кастомный `QGraphicsPixmapItem`, в нем, по `mousePressEvent` определяется информация о пикселе и испускается сигнал `pixelData`, который я хочу отловить главным окном:
void myPixItemX::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        if (event->button() != Qt::RightButton) {
            QPoint position(event->pos().x(), event->pos().y());
            QImage local_image = QImage(qImg_x);
            QColor *color = new QColor;
            pixel_color = color->fromRgb(local_image.pixel(position));
            if (pixel_color.isValid ()) {
                pixel_data (position.x (), position.y (), pixel_color.red (), pixel_color.green (), pixel_color.blue ());
            }

        }
    }

Я прочитал, что если переопределять свой `QGraphicsItem`, то нужно в конструкторе наследовать сначала от `QObject` и вызывать макрос `Q_OBJECT`. Сделал так со своим `QGraphicsPixmapItem`, вроде ошибок не выдало:
class myPixItemX : public QObject, public QGraphicsPixmapItem
    {
        Q_OBJECT
    public:
        myPixItemX(const QPixmap & pixmap, QGraphicsItem * parent = 0);
    // Ну и далее по списку, не буду тут все приводить...

Однако, беда пришла оттуда, откуда её совсем не ждешь ...

При попытке соединить в главном окне сигнал моего объекта `Pix` с слотом
connect(ui->graphicsView->Pix, SIGNAL(pixel_data(int,int,int,int,int)),this , SLOT(color_pick(int,int,int,int,int)));

, в консоль выдает следующее:
QObject::connect: Cannot connect (null)::pixel_data(int,int,int,int,int) to MainWindow::color_pick(int,int,int,int,int)

Как я понял, на момент создания связки сигнал-слот, объект `Pix` еще не был создан, так как он создается после принятия изображения через последовательный порт. Я попытался создать объект `Pix` при инициализации объекта `QGraphicsView`, потом его удалять через `scene->clear();`, при приеме изображения и на его место ставить новый. Вот код установки изображения в сцену:
void ImageViewer::setPixmapImage(QByteArray image_data, int image_width, int image_height, int image_resolution)
    {
        del_grid();
        scene->clear();
        w_img = image_width;
        h_img = image_height;
        zoom = 0;
        unsigned char data[image_resolution];
        memcpy(data, image_data.toStdString().c_str(), image_resolution);
        qImg = QImage(data, image_width, image_height, image_width, QImage::Format_Grayscale8);
        pixmap = QPixmap::fromImage(qImg);
        Pix = new myPixItemX(pixmap);
        Pix->setQImg_x (qImg);
        scene->addItem(Pix);
        scene->setSceneRect(0, 0, pixmap.size().width(), pixmap.size().height());
        this->fitInView();
    }

Теперь ничто не ругается, однако и сигнал не доходит до главного окна.
И вообще, мне дико не нравиться эта идея с кастомным `QGraphicsPixmapItem`, в `PyQt5`, можно сделать так:
self._photo = QGraphicsPixmapItem(QPixmap(self.qImg))
    self._photo.mousePressEvent = self.pixelSelect
    self._scene.addItem(self._photo)

и по клику в пределах `QGraphicsPixmapItem` будет вызываться `self.pixelSelect`, а можно-ли подобное сделать в `Qt`, не создавая лишних классов?
  • Вопрос задан
  • 464 просмотра
Решения вопроса 1
@Fil
Не думаю, что можно решить без переопределения QGraphicsPixmapItem. Лучше всего один раз в начале создать myPixItemX и обновлять его pixmap вызовом setPixmap. Как вы и сами поняли, connect нужно прописывать после создания объекта. Чтобы исправить ваше решение, так и пишите:
Pix = new myPixItemX(pixmap);
Pix->setQImg_x (qImg);
scene->addItem(Pix);
connect(Pix, SIGNAL(pixel_data(int,int,int,int,int)),this , SLOT(color_pick(int,int,int,int,int)));


Или по-новому:
connect(Pix, &myPixItemX::pixel_data, this, &ImageViewer::color_pick);


И еще: QGraphicsPixmapItem и так наследуется от QObject, поэтому замените
class myPixItemX : public QObject, public QGraphicsPixmapItem

на
class myPixItemX : public QGraphicsPixmapItem
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы