QEvent:: MouseButtonPress and QEvent:: MouseMove effecting a QGraphicsScene in a strange way

787 views Asked by At

I have an application where I want to pick up the position of the mouse in a graphics view and use this to draw a pair of threshold markers to adjust a gradation scale within the same graphics view.

The graphicsView_gradbar widget is 162x22 pixels with a 1 pixel border, leaving 160x20 pixels for the greyscale plot.

I'm installing the event filter to this view and then with an event handler picking out the mouse coordinates relative to this view.

If I set the return values as I think they should be once the event has been handled, the mouse click, and mouse move is correctly handled, except that the graphics view is not shown correctly - the right side is blank and the border is not drawn. But clicking in this area will pick up the mouse move correctly and move the cursor drawn in the application in the part of the graphics view that is drawn correctly. Clicking in the correctly drawn part of the view only responds to the mouse click and not the movement when the mouse is clicked and held down.

If I set the return values to "false" the gradation bar is drawn correctly but it only responds to mouse clicks and not to mouse moves when the mouse is clicked and held down.

Good gradation bar:
Good gradation bar

Bad gradation bar:
Bad gradation bar

The mainwindow function sets everything up. The GradbarRefresh function redraws the gradation bar when new mouse clicks or movements occur. The eventFilter handles the events and generates the new coordinates for the thresholds (red lines) drawn in the gradation bar.

I just cannot figure out why the graphics view is corrupted like this.

Here's the header:- `

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QtDebug>

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>

#include <QEvent>
#include <QMouseEvent>
#include <QGraphicsSceneMouseEvent>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    QGraphicsScene *scene_gradbar;

    bool eventFilter(QObject *obj, QEvent *event);

private slots:
    void GradbarRefresh(int status);

private:
    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H
```

Here's the main.cpp

#include "mainwindow.h"

#include <QApplication>

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

Here's the source:-

#include "mainwindow.h"
#include "ui_mainwindow.h"

int gradfull_lower;                     // Full range 255 steps (slider is 160)
int gradfull_upper;                     // Full range 255 steps (slider is 160)

int grad_lower;                         // Gradation lower threshold
int grad_upper;                         // Gradation upper threshold

QGraphicsPixmapItem *histgradbarItem;   // Gradation bar pixmap


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    {

        ui->setupUi(this);

        scene_gradbar = new QGraphicsScene(this);
        ui->graphicsView_gradbar->setScene(scene_gradbar);

        ui->graphicsView_gradbar->installEventFilter(this);   // Install the event filter to this graphics view will send mouse events
                                                              // to the filter with the coordinates of this graphicsview item relative mouse position


        //  ui->graphicsView_gradbar->setMouseTracking(true);


        // Initialise gradation range
        grad_lower = 0;
        grad_upper = 159;


        // Set the full histogram ranges from the gradbar values
        gradfull_lower = (grad_lower + 1) * 255 / 160;
        gradfull_upper = (grad_upper +1) * 255/ 160;

        // Initialise the gradation bar
        GradbarRefresh(0);
    }
}

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


void MainWindow::GradbarRefresh(int status)
{

    unsigned char gradationbar[12800];          // Storage for the gradation bar graphic (160x20 pixels, x4 bytes per pixel)

    quint8 gradbarval[3];                       // For future pseudo red, green or blue scale option may need to set colour

    int width;
    int height;
    int index;
    int grad_range;

    // Make the gradation bar under the histogram
    height = 0;
    index = 0;

    // Calculate the range of levels
    grad_range = grad_upper - grad_lower + 1;

    // Greyscale (still RGBA)
    // Must be able to do this with one pass of height then some memcopy function for the 19 other rows
    do {
        width = 0;
        do {
            if (width < grad_lower ) {
                gradbarval[0] = 255;                                                // White if less than the offset
                gradbarval[1] = 255;
            }
            else {
                gradbarval[0] = 255 - ((width - grad_lower) * 255 )/ (grad_range);  // Calculate the greyscale (0-159 grad_bar range scaled to 0-255 greyscale range)
                gradbarval[1] = gradbarval[0];                                      // For now greyscale and not pseudo colour
            }
            if (width > (grad_upper)) {
                gradbarval[0] = 0;                                                  // Black if beyond the gradbar upper level
                gradbarval[1] = 0;
            }
            if ((width == grad_lower) || (width == grad_upper)) {                   // Set to red if on one of the thresholds
                gradbarval[0] = 255;
                gradbarval[1] = 0;
            }
            gradationbar[index] = gradbarval[0];        // Red
            index += 1;
            gradationbar[index] = gradbarval[1];        // Green
            index += 1;
            gradationbar[index] = gradbarval[1];        // Blue
            index += 1;
            gradationbar[index] = 255;                  // A
            index += 1;
            width += 1;
        } while (width < 160);
        height += 1;
    } while (height < 20);


    // First time pass (status 0) add a pixmap, thereafter (status 1) update the first pixmap
    if (status == 0){
        histgradbarItem = scene_gradbar->addPixmap(QPixmap::fromImage(QImage(gradationbar, 160, 20, QImage::Format_RGBA8888)));
        histgradbarItem->setPos(0 , 0);
    } else {
        histgradbarItem->setPixmap(QPixmap::fromImage(QImage(gradationbar, 160, 20, QImage::Format_RGBA8888)));
        scene_gradbar->update();
    }

}

The event filter code that handles the mouse click and movement:-

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{

    int xPos, yPos;             // x and y coordinates of the mouse when pressed
    int grad_midpos;            // Position half way betweent he markers
    char labeltext[10];         // Temp text storage for writing to labels

    QMouseEvent* mEvent = (QMouseEvent*)event;

    // Look for mouse press in the gradation bar, then get x value and move lower/upper range accordingly
    if (obj == ui->graphicsView_gradbar){                   // Only need this if more than one event filter has been installed
        if ((event->type() == QEvent::MouseButtonPress) || (event->type() == QEvent::MouseMove)){  // Check if it's a mouse press or mouse move

            QPoint point = mEvent->pos();
            xPos = point.x();                               // Values 1-162 as it gives coordinates inluding the frame around the scale drawn within it.
            yPos = point.y();                               // The y-coord is interesting to see if it returns a value outside of the gradbar (only applies to MouseMove)
            sprintf(labeltext, "%03i", xPos);               // Write x-coordinate to the label
            ui->label_xvalue->setText(labeltext);
            sprintf(labeltext, "%03i", yPos);               // Write x-coordinate to the label
            ui->label_yvalue->setText(labeltext);
            qDebug() << "Mouse Press x" << xPos;            // Output to debug for good measure
            qDebug() << "Mouse Press y" << xPos;

            if ((xPos < 2) || (xPos > 161)) {                 // If on the box frame or outside, return
                return true;
            }

            xPos = xPos - 2;                                // Convert to a coordinate in the scene, range 0-159 (160 picels)

            // Calculate the gradbar middle
            grad_midpos = grad_lower + ((grad_upper-grad_lower)/2);
            // Check to see which to grab and move
            if (xPos < (grad_midpos - 1) ) {                // If less than half mid position reassign to lower threshold - keep a 2 pix gap in the middle
                grad_lower = xPos;
            } else if (xPos > grad_midpos){                 // If at or beyond the mid position reassign to the upper threshold
                grad_upper = xPos;
            }


            // Refresh the gradation bar
            GradbarRefresh(1);

            return true;                        // This event has been dealt with so stop handling it
        }                                       // ******************* NOTE **********
                                                // Set BOTH theser return values to false and the histogram is drawn properly but only
                                                // responds to mouse clicks, not the mouse move

        return true;                        // Finished handling this event
    }

    return false;                           // Returning false means events are still handled. If set to true, no more events are
                                            // Handled and the histogram won't draw properly
}

Here's the form:-

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QGraphicsView" name="graphicsView_gradbar">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>200</y>
      <width>162</width>
      <height>22</height>
     </rect>
    </property>
   </widget>
   <widget class="QGraphicsView" name="graphicsView_histogram">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>120</y>
      <width>162</width>
      <height>83</height>
     </rect>
    </property>
   </widget>
   <widget class="QLabel" name="label_xtext">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>230</y>
      <width>49</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>x-coord</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_ytext">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>260</y>
      <width>49</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>y-coord</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_xvalue">
    <property name="geometry">
     <rect>
      <x>280</x>
      <y>230</y>
      <width>49</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>x-value</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_yvalue">
    <property name="geometry">
     <rect>
      <x>280</x>
      <y>260</y>
      <width>49</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>y-value</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>


0

There are 0 answers