sh13max
@sh13max
Хочу научиться качественно программировать☺

Как создать кликабельный элемент QML с помощью Qt/C++?

Имеется графический элемент QML основанный на классе QQuickPaintedItem

invitemslot.h
#ifndef INVITEMSLOT_H
#define INVITEMSLOT_H

#include<QtQuick/QQuickPaintedItem>
#include <QColor>
#include <QBrush>
#include <QPen>
#include <QPainter>
#include <QImage>
#include <QStaticText>
#include <InvItem>
#include <QMouseEvent>
#include <QAbstractButton>
#include <QtQuickWidgets/QQuickWidget>

class InvItemSlot : public QQuickPaintedItem
{
public:
  explicit InvItemSlot(QQuickItem *parent = 0);

  Q_OBJECT

  Q_PROPERTY(int slotIndex READ slotIndex WRITE setSlotIndex NOTIFY slotIndexChanged)
  Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY backgroundChanged)
  Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
  Q_PROPERTY(QString slotState READ slotState WRITE setSlotState NOTIFY slotStateChanged)
  Q_PROPERTY(InvItem* containedItem READ containedItem WRITE setContainedItem NOTIFY containedItemChanged)
//  Q_PROPERTY(InvItem containedItem READ containedItem)

  int slotIndex();
  QColor background();
  QColor borderColor();
  QString slotState();
  InvItem *containedItem();
  Q_INVOKABLE void setIcon(QString url);


  void paint(QPainter *painter) override;

public slots:

  void setSlotIndex(int slotIndex);
  void setBackground(QColor background);
  void setBorderColor(QColor borderColor);
  void setSlotState(QString slotState);
  void setContainedItem(InvItem *containedItem);
  void setIcon();

signals:
  void slotIndexChanged(int slotIndex);
  void backgroundChanged(QColor background);
  void borderColorChanged(QColor borderColor);
  void slotStateChanged(QString slotState);
  void containedItemChanged(InvItem *containedItem);

private:
  int m_slotIndex;
  QColor m_background;
  QColor m_borderColor;
  QString m_slotState;
  InvItem *m_containedItem = new InvItem(this);
  QImage icon;

};

#endif // INVITEMSLOT_H


invitemslot.cpp
#include "invitemslot.h"

#ifdef DEBUG
#include <QDebug>
#endif

InvItemSlot::InvItemSlot(QQuickItem *parent) :
  QQuickPaintedItem(parent),
  m_background(35, 35, 35,102),
  m_borderColor(Qt::white)
{
  connect(m_containedItem, SIGNAL(itemPropertiesChanged(QVariant)), this, SLOT(setIcon()));
}

void InvItemSlot::paint(QPainter *painter){

  QBrush brush(m_background);
  QPen border;
  QPen textPen(Qt::red);
  textPen.setWidth(20);
  border.setWidth(5);

  if(m_slotState == "pressed"){
    m_background = QColor(102,102,102,102);
    m_borderColor = QColor(102,102,102,102);
  }else if(m_slotState == "released"){
    m_background = QColor(35, 35, 35,102);
    m_borderColor = QColor(Qt::white);
  }else if (m_slotState == "selected") {
    m_background = QColor(35, 35, 35,102);
    m_borderColor = QColor(Qt::red);
  }

  border.setColor(m_borderColor);
  painter->setRenderHints(QPainter::Antialiasing, true);
  painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
  painter->setRenderHints(QPainter::HighQualityAntialiasing, true);
  painter->setPen(border);
  painter->setBrush(brush);
  painter->drawRect(QRectF(0,0,this->width(),this->height()));
  painter->drawImage(QRectF(5,5,(this->width() - (border.width()*2)),(this->height() - (border.width()*2))),icon);
  QStaticText itemName(m_containedItem->itemName());
  painter->setPen(Qt::NoPen);
  painter->setBrush(QBrush(Qt::black));
  painter->drawRect(QRectF(0,0,itemName.textWidth(),20));
  painter->drawStaticText(QPointF(0,0),itemName);

  if(m_slotState == "pressed"){
    painter->setPen(textPen);
    painter->drawText(QRectF(0,0,this->width(),this->height()),Qt::AlignCenter,m_containedItem->itemName());
  }

}



int InvItemSlot::slotIndex(){return m_slotIndex;}

void InvItemSlot::setSlotIndex(int slotIndex){
  m_slotIndex = slotIndex;
  emit slotIndexChanged(slotIndex);
  return;
}



QColor InvItemSlot::background(){return m_background;}

void InvItemSlot::setBackground(QColor background){
  m_background = background;
  emit backgroundChanged(background);
  return;
}



QColor InvItemSlot::borderColor(){return m_borderColor;}

void InvItemSlot::setBorderColor(QColor borderColor){
  m_borderColor = borderColor;
  emit borderColorChanged(borderColor);
  return;
}

QString InvItemSlot::slotState(){return m_slotState;}

void InvItemSlot::setSlotState(QString slotState){
  bool blocked = false;
  if(slotState == "pressed"){
    m_slotState = slotState;
  }else if (slotState == "released") {
    m_slotState = slotState;
  }else if (slotState == "selected") {
    m_slotState = slotState;
  }else{
    blocked = true;
  }
  update();
  emit slotStateChanged(slotState);
}


InvItem *InvItemSlot::containedItem(){
  return m_containedItem;
}

void InvItemSlot::setContainedItem(InvItem *overrideItem){
  disconnect(m_containedItem, SIGNAL(itemPropertiesChanged(QVariant)), this, SLOT(setIcon()));
  m_containedItem = overrideItem;
  connect(m_containedItem, SIGNAL(itemPropertiesChanged(QVariant)), this, SLOT(setIcon()));
  emit containedItemChanged(m_containedItem);
}


void InvItemSlot::setIcon(){
  QString url = m_containedItem->itemProperties().toJsonObject().value("iconSorce").toString();
  qDebug()<<"Load:"<<url;
  icon.load(url);
  update();
}

void InvItemSlot::setIcon(QString url){
  icon.load(url);
  update();
}


//void InvItemSlot::mousePressEvent(QMouseEvent *event){
//  if(event->button() == Qt::LeftButton){

//    }
//}


Хочется сделать элемент кликабельным, чтобы не писать в QML костыли вроде такого:

main.qml
InvItemSlot{
    width: 100;
    height: 100;
    MouseArea{
        anchors.fill: parent;
        onPressed: slotState = "pressed";
        onReleased: slotState = "released";
    }
}


Попытался использовать QAbstractButton, но не получается ввиду того, что класс QQuickPaintedItem унаследован от QQuickItem, в то время как класс QAbstractButton от QWidget, попытка прописать наследования постоянноутыкается в следующие ошибки:
C:\Users\User\Documents\QtProjects\MainDot\gameAPI\invitemslot.h:60: error: 'QObject' is an ambiguous base of 'InvItemSlot'
   InvItem *m_containedItem = new InvItem(this);
                                              ^
C:\Qt\5.9.1\mingw53_32\include\QtCore\qmetatype.h:1376: error: 'QObject' is an ambiguous base of 'InvItemSlot'
         enum { Value = sizeof(checkType(static_cast<T*>(Q_NULLPTR))) == sizeof(yes_type) };
                                        ^
  • Вопрос задан
  • 632 просмотра
Решения вопроса 1
@TriKrista
Переопределите в InvItemSlot функции отвечающие за события мыши.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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