为什么在我的自定义Slider类中调用setValue会导致该程序崩溃?

时间:2019-05-01 22:44:55

标签: qt qt5 qwidget

这似乎有点愚蠢,但如果可以的话,请关注我

class Slider : public QSlider
{
    Q_OBJECT
public:
    Slider(QWidget *parent = nullptr);

    void updateValue(int value) { setValue(value);}
    int get() const { return value(); }
};

简而言之,我只是试图通过控制器来更新自定义滑块的值(我知道,我可以通过执行ui->horizontalSlider->setValue(int);来使用插槽来完成此操作。)

我有一个Controller<T....> controller(t&...),它接受​​任意数量的类,并允许我设置其值并获取其值,例如:

Controller<CustomSlider,CustomSpinBox,MyClass> controller(*ui->horizontalSlider,*ui->spinBox,myClass);

所以我对插槽所做的就是告诉控制器更新所有值,如下所示:

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
    controller.setValues(value);
    getValues();
}

getValues()只是输出到控制台,告诉我它们确实已全部更新。

setValues(int)调用函数updateValue(int),该函数调用每个类的setter函数。这应该是一个直接的更新,但是,每当我尝试移动滑块时,程序都会崩溃,并且调试器除了在qabstractslider.cpp第531 Q_D(QAbstractSlider)行崩溃之外,没有给我任何有用的信息。所以我真的不知道这是怎么回事。有人有建议吗?

编辑:我要说的是,ui->horizontalSlider已被提升为Slider类。

EDIT2 :被要求制作MVE,所以这是我可以做的:

#ifndef TESTCONTROLLER_HPP
#define TESTCONTROLLER_HPP

#include <QMainWindow>

#include "slider.hpp"
#include "spinbox.hpp"
#include "controller.hpp"
#include "myclass.hpp"

namespace Ui {
class TestController;
}

class TestController : public QMainWindow
{
    Q_OBJECT

public:
    explicit TestController(QWidget *parent = nullptr);
    ~TestController();

    void getValues();
    void print(const std::vector<int> &p);

private slots:
    void on_horizontalSlider_valueChanged(int value);
    void on_spinBox_valueChanged(int arg1);

private:
    Ui::TestController *ui;

    MyClass myClass;

    Controller<Slider,SpinBox,myClass> controller;
};

#endif // TESTCONTROLLER_HPP

TestController.cpp:

#include "testcontroller.hpp"
#include "ui_testcontroller.h"

TestController::TestController(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::TestController),
    controller(*ui->horizontalSlider,*ui->spinBox,myClass)
{
    ui->setupUi(this);

}

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

void TestController::getValues()
{
    std::vector<int> values;
    controller.getValues(values);
    print(values);
}

void TestController::print(const std::vector<int> &p)
{
    for(const auto & e: p)
    {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}


void TestController::on_horizontalSlider_valueChanged(int value)
{
    controller.setValues(value);
    getValues();
}

void TestController::on_spinBox_valueChanged(int arg1)
{
    controller.setValues(arg1);
    getValues();
}

controller.hpp:

#ifndef CONTROLLER_HPP
#define CONTROLLER_HPP

#include <functional>
#include <vector>
#include <iostream>
#include <utility>

template<typename...Classes>
class Controller
{
  public:
    Controller(Classes&...objects) : objects(objects...){}
    Controller(std::tuple<Classes&...> tup) : objects(tup){}

    void setValues(int value)
    {
      std::apply([&](auto&...x) { (x.updateValue(value),...);}, objects);
    }

    void getValues(std::vector<int> &values) const
    {
      std::apply([&](auto&...x) { (values.push_back(x.get()),...);}, objects);
    }

    std::tuple<Classes&...> getObjects() const
    {
      return objects;
    }

  private:
    std::tuple<Classes&...> objects;
};

template<typename...ClassesL, typename...ClassesR>
auto operator+(const Controller<ClassesL...>& lhs, const Controller<ClassesR...>& rhs)
{
  return Controller(std::tuple_cat(lhs.getObjects(),rhs.getObjects()));
}

template<typename...ClassesL, typename ClassesR>
auto operator+(const Controller<ClassesL...> &lhs, ClassesR rhs)
{
  Controller<ClassesR> makeController(rhs);
  return Controller(std::tuple_cat(lhs.getObjects(),makeController.getObjects()));
}

template<typename ClassesL, typename...ClassesR>
auto operator+(ClassesL lhs, const Controller<ClassesR...> &rhs)
{
  Controller<ClassesL> makeController(lhs);
  return Controller(std::tuple_cat(makeController.getObjects(),rhs.getObjects()));
}

#endif // CONTROLLER_HPP

所有这些,您只需要复制Slider类,就可以在.cpp文件中执行Slider::Slider(QWidget *parent) : QSlider(parent)。 Spin Box类看起来与滑块完全相同,只是它继承自QSpinBox,因此MyClass具有自己的getter和setter,但是还必须包括updateValueget

然后,您需要在设计中添加一个水平滑块和一个旋转框,将这两个滑块都升级到我提供的类中,并且应该很好地复制问题。

0 个答案:

没有答案