Obecnie piszę wersję Problemu komiwojażera dla klasy uniwersyteckiej przy użyciu qt. Aby umieścić miasta na widżecie QGraphicsView, stworzyłem ten program tak, jak w tym samouczku YouTube: https://www.youtube.com/watch?v=hgDd2QspuDg

Niestety po prostu robię wszystko tak, jak w samouczku, ale tylko otrzymuję błąd, że moja klasa jest abstrakcyjna, czego nie rozumiem, ponieważ wszystko, co umieściłem w tej klasie, definiuję w kodzie i nie ma w mojej klasie Nic bez odwołań.

Dialog.h:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtCore>
#include <QtGui>
#include <QMessageBox>
#include <iostream>
#include <QPointF>
#include "mycity.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();
private slots:
    double on_Kelvin_box_valueChanged();

    double on_Iter_box_valueChanged();

    double on_Radius_box_valueChanged();

    double on_CVRatio_box_valueChanged();

    void on_resetButton_clicked();

    void on_startButton_released();

    void on_stopButton_released();

private:
    Ui::Dialog *ui;
    QGraphicsScene *scene;
    MyCity *city;

protected:

};

#endif // DIALOG_H

Mojemiasto.h:

#ifndef MYCITY_H
#define MYCITY_H

#include <QPainter>
#include <QGraphicsItem>
#include <QDebug>
#include <string.h>

class MyCity : public QGraphicsItem
{
public:
    MyCity();

    QRectF boundingRect() const;
    void paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget);
    bool Pressed;
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};

#endif // MYCITY_H

Dialog.cpp:

#include "dialog.h"
#include "ui_dialog.h"
#include <qtCore>
#include <qtGui>
#include <QPointF>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);

    city = new MyCity();
    scene->addItem(city);
}

Dialog::~Dialog()
{
    delete ui;
}

double Dialog::on_Kelvin_box_valueChanged()
{
    double kelvin = ui->Kelvin_box->value();
    return kelvin;
}

double Dialog::on_Iter_box_valueChanged()
{
    double iter = ui->Iter_box->value();
    return iter;
}

double Dialog::on_CVRatio_box_valueChanged()
{
    double cvRatio = ui->CVRatio_box->value();
    return cvRatio;
}

double Dialog::on_Radius_box_valueChanged()
{
    double radius = ui->Radius_box->value();
    return radius;
}

void Dialog::on_resetButton_clicked()
{
   ui->Kelvin_box->setValue(0.3);
   ui->Iter_box->setValue(10000);
   ui->CVRatio_box->setValue(2.5);
   ui->Radius_box->setValue(0.1);
}

//Wenn dieser Knopf gedrückt wird startet die Iteration
void Dialog::on_startButton_released()
{

}
//Wenn dieser Knopf gedrückt wird beendet sich die Iteration
void Dialog::on_stopButton_released()
{

}

Main.cpp:

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}

Mojemiasto.cpp:

#include "mycity.h"
//Das is das Objekt 'Stadt' welches wir erzeugen in der dialog.cpp
MyCity::MyCity()
{
    Pressed = false;
    setFlag(ItemIsMovable);
}

QRectF MyCity::boundingRect() const
{
   return QRectF(0,0,20,20);
}

void MyCity::paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //ellipse wird rot bei draufdrücken, grün bei loslassen
    QRectF rec = boundingRect();
    QBrush brush(Qt::green);
    if(Pressed)
    {
        brush.setColor((Qt::red));
    }
    else
    {
        brush.setColor((Qt::green));
    }

    painter->fillRect(rec,brush);
    painter->drawRect(rec);
}

void MyCity::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    //hier geschieht, was beim mausdruck passieren soll (stadt kreieren)
    Pressed = true;
    update();
    QGraphicsItem::mousePressEvent(event);//überschreiben der eigentlichen mousePressEvent-funktion
}

void MyCity::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    //nur temporäre testfunktion, wird am ende nich gebraucht
    Pressed = false;
    update();
    QGraphicsItem::mouseReleaseEvent(event);
}

A oto błąd, który otrzymuję:

C:...\dialog.cpp:16: Błąd: nieprawidłowe nowe wyrażenie klasy abstrakcyjnej typu „MyCity” city = new MyCity();

Czy ktoś może mi pomóc znaleźć błąd, który powoduje tę klasę abstrakcyjną?

EDYCJA: Oto cały komunikat o błędzie, który otrzymałem od qt:

..\Milestone_Traveling\dialog.cpp: In constructor 'Dialog::Dialog(QWidget*)':
..\Milestone_Traveling\dialog.cpp:16:31: error: invalid new-expression of abstract class type 'MyCity'
     MyCity* city = new MyCity();
                               ^
In file included from ..\Milestone_Traveling\dialog.h:10:0,
                 from ..\Milestone_Traveling\dialog.cpp:1:
..\Milestone_Traveling\mycity.h:9:7: note:   because the following virtual functions are pure within 'MyCity':
 class MyCity : public QGraphicsItem
       ^
In file included from D:\QT\5.10.1\mingw53_32\include\QtWidgets/QGraphicsItem:1:0,
                 from ..\Milestone_Traveling\mycity.h:5,
                 from ..\Milestone_Traveling\dialog.h:10,
                 from ..\Milestone_Traveling\dialog.cpp:1:
D:\QT\5.10.1\mingw53_32\include\QtWidgets/qgraphicsitem.h:344:18: note:     virtual void QGraphicsItem::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
     virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) = 0;
                  ^
Makefile.Debug:1144: recipe for target 'debug/dialog.o' failed
mingw32-make[1]: Leaving directory 'C:/…/build-Milestone_Traveling-Desktop_Qt_5_10_1_MinGW_32bit-Debug'
mingw32-make[1]: *** [debug/dialog.o] Error 1
Makefile:36: recipe for target 'debug' failed
mingw32-make: *** [debug] Error 2
15:48:32: Der Prozess "D:\QT\Tools\mingw530_32\bin\mingw32-make.exe" wurde mit dem Rückgabewert 2 beendet.
Fehler beim Erstellen/Deployment des Projekts Milestone_Traveling (Kit: Desktop Qt 5.10.1 MinGW 32bit)
Bei der Ausführung von Schritt "Make"
15:48:32: Verstrichene Zeit: 00:11.
-1
Kubaguette The Testobun 2 grudzień 2018, 17:27

1 odpowiedź

Najlepsza odpowiedź

Podczas zastępowania metody wirtualnej zawsze używaj słowa kluczowego override. Gdybyś to zrobił podczas pisania MyCity::paint, zdałbyś sobie sprawę, że nie pasuje do podpisu dla QGraphicsItem::paint:

QGraphicsItem:

virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) = 0;

Moje Miasto:

void paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget);

Zobacz różnicę? To subtelne, ale brakuje Ci const

Gdybyś zamiast tego napisał MyCity::paint ze słowem kluczowym override w następujący sposób:

void paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget) override;

Wtedy otrzymasz błąd kompilatora zgodnie z liniami

błąd: 'virtual void MyCity::paint(...)' oznaczony jako 'override', ale nie zastępuje

5
AndyG 2 grudzień 2018, 18:02