samedi 23 juillet 2022

How to the same Interface to different QT Classes

Goal

I want to benchmark some drawing libraries and gather diagnostics. I thought of implementing in each benchmark the same interface and then instantiating different classes in the main window.

The Challenge

The problem is that some benchmarks use QWidget and other QOpenGLWidget. So even if I implement the same functionality I can not use it, without dynamic casting to each possible instance.

What I tried so far

My first thought was to create an interface and use virtual multiple inheritance. But that doesn't seem to work and I am not sure if that's even the right solution.

I also thought of the Composite Pattern or Adapter Pattern, but seem some problems, as I want to override some functions of QWidget like resizeEvent in each benchmark. Of course I could duplicate that code or put it into some non-member function. But maybe there is something more elegant?

QWidgets Addin

class BenchmarkAddin : virtual public QWidget {
public:
    BenchmarkAddin() {
        connect(&timer_, SIGNAL(timeout()), this, SLOT(update()));
    }

    double get_fps() {
        // use frames_ and time to estimate fps
    }

    void count_frame() {
        ++frames_;
    }
    
    void set_parameters(int param1_) {
        param1_;
    }

protected:
    void resizeEvent(QResizeEvent* event) override {
        init();
    }

    virtual void init() = 0;

    int param1_;
private:
    int frames_;
    QTimer timer_;
}

Raster Benchmark

class RasterBenchmark : public BenchmarkAddin {
protected:
    void init() override {
        // create buffers
    }

    void paintEvent(QPaintEvent* event) override {
        // do drawing using param1_
        count_frame();
    }
}

OpenGL benchmark

class OpenGLBenchmark : virtual public QOpenGLWidget, public BenchmarkAddin {
protected:
    void paintGL() override {
        // do GL drawing using param1_
        count_frame();
    }
}

Main Window Example Usage

BenchmarkAddin *widget; 
if (benchmark == "raster") {
    widget = new RasterBenchmark(this);
else
    widget = new OpenGLBenchmark(this);

widget.set_parameters(100);

...

std::cout << widget.get_fps() << std::endl;

Obviously this doesn't work, as QOpenGLWidget doesn't use virtual inheritance for QWidget. Also there is a problem with Qt's object meta system.

Question:

Any idea how I could implement an interface that is both accessible within a subclass of QWidget and QOpenGLWidget?

Aucun commentaire:

Enregistrer un commentaire