Как предотвратить масштабирование QChartView до отрицательных значений оси x или y

Я хочу предотвратить масштабирование QChartView до отрицательных значений оси x или y. Итак, я пытаюсь перехватить mouseReleaseEvent в моем подклассе QChartView, а затем изменить координаты RubberBandRect перед выполнением масштабирования. Но кажется, что координаты RubberBandRect всегда равны нулю после отпускания мыши, поэтому я думаю, что я не работаю с правильным RubberBandRect.

Я пытаюсь адаптироваться на основе документации для QChartView (выделено мной):

недействительным QChartView::mouseReleaseEvent(QMouseEvent *event)

Если левая кнопка мыши отпущена, а резинка включена, событие event принимается, и изображение масштабируется до прямоугольника, обозначенного резинкой.

Когда я попытался посмотреть на фактические значения в RubberBandRect в приведенном ниже фрагменте кода, значения x/y и высоты/ширины прямоугольника всегда равны нулю, независимо от того, как я увеличивал масштаб с помощью курсора.

Я также посмотрел ответ на этот вопрос: Qt Как подключить сигнал RubberBandChanged но в этом случае они хотели поведения в главном окне, чего я не хочу. Спасибо!

class MyQChartView : public QtCharts::QChartView
{
    Q_OBJECT
public:
    MyQChartView(QWidget *parent = 0);
    //...
protected:
    void mouseReleaseEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);

};


void MyQChartView::mouseReleaseEvent(QMouseEvent *event)
{
    
    //always shows zeroes for the x and y position
    if(event->button() == Qt::LeftButton){
        std::cout << "x: " << this->rubberBandRect().x() << " y: " << this->rubberBandRect().y() << std::endl;
        
        QChartView::mouseReleaseEvent(event);
    }
    
    //any other event
    QChartView::mouseReleaseEvent(event);
}

person qDibeX7NB    schedule 16.09.2020    source источник
comment
Что возвращает функция rubberBand()? Вы установили это значение с помощью setRubberBand на что-то, отличное от NoRubberBand?   -  person Maxim Skvortsov    schedule 19.09.2020
comment
@MaximSkvortsov резинка настроена на прямоугольную резинку (не показана во фрагменте выше)   -  person qDibeX7NB    schedule 21.09.2020
comment
Если да, просмотрите исходный код: code.woboq. org/qt5/qtcharts/src/charts/ Должны быть установлены правильные значения   -  person Maxim Skvortsov    schedule 21.09.2020


Ответы (1)


После обширных экспериментов я думаю, что нашел лучший обходной путь. Необходимо было сделать указатель на резиновую ленту, а затем найти ребенка, чтобы добраться до настоящей резиновой ленты. Затем, после отпускания мыши, я получаю координаты области графика, а также координаты резиновой ленты. Затем я сделал ограничивающую рамку (bounded_geometry) и ограничил ее значения, если резинка выходила за границы. Затем я увеличиваю масштаб до ограниченного поля геометрии. Не получится просто изменить резиновую ленту, потому что эти координаты не являются числами с плавающей запятой, а ошибки округления вызывают неправильное масштабирование.

class MyQChartView : public QtCharts::QChartView
{
    Q_OBJECT
public:
    MyQChartView(QWidget *parent = 0):
    QChartView(parent)
    {
        myChart = new QtCharts::QChart();
        setRubberBand(QtCharts::QChartView::RectangleRubberBand);
        rubberBandPtr = this->findChild<QRubberBand *>();
        this->setChart(myChart);
        //...other things
    }
    //...
protected:
    void mouseReleaseEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
private:
    QRubberBand * rubberBandPtr;
    QtCharts::QChart * myChart;
};


void MyQChartView::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        //first get the plot area and save the needed values (could change each time)
        QRectF plotArea = myChart->plotArea();
        qreal xbound = plotArea.x(); //values < xbound are out of bounds on x axis
        qreal ybound = plotArea.y() + plotArea.height(); // !!! note that values > ybound are out of bounds (i.e. negative y values)
        
        QPointF rb_tl = rubberBandPtr->geometry().topLeft();
        QPointF rb_br = rubberBandPtr->geometry().bottomRight();
        
        QRectF bounded_geometry = rubberBandPtr->geometry();
        
        if(rb_tl.x() < xbound){
            bounded_geometry.setX(xbound);
        }
        if(rb_br.y() > ybound){ //note that values > ybound are out of bounds
            bounded_geometry.setBottom(ybound);
        }
        
        myChart->zoomIn(bounded_geometry);        
        rubberBandPtr->close();

        return;
    }
    
    //any other event
    QChartView::mouseReleaseEvent(event);
}
person qDibeX7NB    schedule 23.09.2020