首页 > 解决方案 > QEvent:: MouseButtonPress 和 QEvent:: MouseMove 以一种奇怪的方式影响 QGraphicsScene

问题描述

我有一个应用程序,我想在图形视图中获取鼠标的位置,并使用它来绘制一对阈值标记来调整同一图形视图中的渐变比例。

graphicsView_gradbar 小部件为 162x22 像素,边框为 1 像素,为灰度图留下 160x20 像素。

我将事件过滤器安装到此视图,然后使用事件处理程序选择相对于此视图的鼠标坐标。

如果我将返回值设置为我认为在处理事件后应该设置的值,则鼠标单击和鼠标移动将得到正确处理,但图形视图未正确显示 - 右侧为空白且边框不正确画。但是在这个区域点击会拾起鼠标正确移动,并将应用程序中绘制的光标移动到正确绘制的图形视图部分。单击视图的正确绘制部分仅响应鼠标单击,而不是单击并按住鼠标时的移动。

如果我将返回值设置为“false”,则渐变条会正确绘制,但它只响应鼠标点击,而不是在点击并按住鼠标时响应鼠标移动。

良好的渐变条:
良好的渐变条

不好的渐变条:
渐变条不好

主窗口功能设置一切。GradbarRefresh 函数在发生新的鼠标点击或移动时重绘渐变条。eventFilter 处理事件并为渐变条中绘制的阈值(红线)生成新坐标。

我只是无法弄清楚为什么图形视图会像这样损坏。

这是标题:- `

#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
```

这是main.cpp

#include "mainwindow.h"

#include <QApplication>

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

这是来源:-

#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
}

这是表格:-

<?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>


标签: c++qtmouseeventqgraphicsviewqevent

解决方案


推荐阅读