M
M
Maks_Semenduk;2017-10-03 00:19:15
Qt
Maks_Semenduk;, 2017-10-03 00:19:15

How to create clickable QML element using Qt/C++?

There is a QML graphic element based on the class 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){

//    }
//}

I want to make the element clickable so as not to write crutches in QML like this:
main.qml
InvItemSlot{
    width: 100;
    height: 100;
    MouseArea{
        anchors.fill: parent;
        onPressed: slotState = "pressed";
        onReleased: slotState = "released";
    }
}

I tried to use QAbstractButton, but it does not work because the QQuickPaintedItem class is inherited from QQuickItem, while the QAbstractButton class is from QWidget, an attempt to write inheritance constantly hits the following errors:
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) };
                                        ^

Answer the question

In order to leave comments, you need to log in

1 answer(s)
T
TriKrista, 2017-10-03
@sh13max

Redefine the functions responsible for mouse events in InvItemSlot.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question