Microsoft Visual Studio 中的 QWT 直方图和立即关闭的 Qt 插件

Posted

技术标签:

【中文标题】Microsoft Visual Studio 中的 QWT 直方图和立即关闭的 Qt 插件【英文标题】:Histogram with QWT in Microsoft Visual Studio and Qt addin which closes immediately 【发布时间】:2014-01-14 17:18:33 【问题描述】:

我正在为我的 GUI 使用用于 Visual Studio C++ 的 Qt 插件。

在我的 GUI 上,我有一个名为 plotButton 的按钮,单击它会绘制图像的直方图。我的绘图选项是通过使用 QWT。

但是,它似乎没有在策划任何事情,并且几乎立即关闭。试过 sleep(),但它似乎也不起作用。问题可能出在我的代码上吗? 这是我的参考代码:

void qt5test1 ::on_plotButton_clicked()

    //Convert to grayscale
    cv::cvtColor(image, image, CV_BGR2GRAY);


    int histSize[1] = 256; // number of bins
    float hranges[2] = 0.0, 255.0; // min andax pixel value
    const float* ranges[1] = hranges;
    int channels[1] = 0; // only 1 channel used

    cv::MatND hist;
    // Compute histogram
    calcHist(&image, 1, channels, cv::Mat(), hist, 1, histSize, ranges);

    double minVal, maxVal;
    cv::minMaxLoc(hist, &minVal, &maxVal);//Locate max and min values

    QwtPlot plot; //Create plot widget
    plot.setTitle( "Plot Demo" ); //Name the plot
    plot.setCanvasBackground( Qt::black ); //Set the Background colour
    plot.setAxisScale( QwtPlot::yLeft, minVal, maxVal ); //Scale the y-axis
    plot.setAxisScale(QwtPlot::xBottom,0,255); //Scale the x-axis
    plot.insertLegend(new QwtLegend()); //Insert a legend

    QwtPlotCurve *curve = new QwtPlotCurve(); // Create a curve
    curve->setTitle("Count"); //Name the curve
    curve->setPen( Qt::white, 2);//Set colour and thickness for drawing the curve 
    //Use Antialiasing to improve plot render quality
    curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
    /*Insert the points that should be plotted on the graph in a 
    Vector of QPoints or a QPolgonF */
    QPolygonF points;
    for( int h = 0; h < histSize[0]; ++h) 
        float bin_value = hist.at<float>(h);
        points << QPointF((float)h, bin_value);
    

    curve->setSamples( points ); //pass points to be drawn on the curve
    curve->attach( &plot ); // Attach curve to the plot 
    plot.resize( 600, 400 ); //Resize the plot
    plot.replot();
    plot.show(); //Show plot
    Sleep(100);

加载图像后单击此按钮,会立即出现一个窗口并立即消失。在输出窗口下,可以找到行。

First-chance exception at 0x75d54b32 (KernelBase.dll) in qt5test1.exe: Microsoft C++ exception: cv::Exception at memory location 0x0044939c..
Unhandled exception at 0x75d54b32 (KernelBase.dll) in qt5test1.exe: Microsoft C++ exception: cv::Exception at memory location 0x0044939c..

有人知道我的代码有什么问题吗?谢谢。请再次注意,该程序是在 Microsoft Visual Studio C++ 中构建和编写的。谢谢。

【问题讨论】:

如果您在事件范围内创建情节,这可能会导致问题。超出范围,垃圾收集器会清理它。尝试在 mainwindow.h 中声明 QwtPlot *plot,使用表单加载定义它: plot = new QwtPlot(0);在这个事件中使用它:plot->property->... 你也没有将情节插入你的用户界面。您应该将其插入布局、框架等... layout->addWidget(plot) @C.CanberkBacı,谢谢。我稍后会尝试一下。并就结果回复您 @rockinfresh 尝试将问题发布到 Qt/Qwt 论坛 qtcentre.org/forums/23-Qwt。如果你足够幸运,Uwe(qwt创始人)会详细回答你的问题。文档可能只是一个 doxygen 输出,但应该承认他对项目的支持。 @rockinfresh 还要提一件事,如果您提出与 c++ 本身相关的问题,而不是关于您的标签的问题,您可能会被否决。例如,在这里我看到一个垃圾堆栈变量;指针问题等都与缺乏内存管理有关。 【参考方案1】:

问题是你在这里构造了一个栈对象:

QwtPlot plot; //Create plot widget

确实,您正试图在方法末尾显示绘图,但是当您对它们使用 exec() 调用时,show() 方法不会像 QDialog 类那样被事件循环阻塞。

它将被处理,但无论哪种方式,您都将在调用后立即离开范围。

有几种方法可以解决这个问题,但我会争取在使用指针时自动删除的 Qt 父/子层次结构。

1) Qt 父/子关系

QwtPlot *plot = new QwtPlot(this);
                            ^^^^

2) 让“情节”成为班级成员

plot.show();

并在类构造函数中构造它。

3) 使用智能指针

QSharedPointer<QwtPlot> plot = QSharedPointer<QwtPlot>(new QwtPlot());

这取决于你在课堂上的进一步背景,选择哪种方式,所以试着理解这些方法,然后看看。

【讨论】:

我不太明白如果show() 被阻止会有什么不同,因为它会阻止什么?直到第一次重绘完成?即使那样,它也无济于事,所以 show() 的阻塞性是一个红鲱鱼。无论如何,show 并没有真正使用事件循环进行大部分处理。说它“将事件发布到事件循环以供执行”在技术上是正确的,但误导。如果您检查QWidget 源,postEvent 仅出现 5 次。显示小部件时,可能会从 updateGeometry_helper 发布 LayoutRequest。 @KubaOber:好的,经过重新考虑,我做了一些修改,以“更少,但更多”。 :-) 谢谢@Laszlo!到目前为止,我一直在帮助我处理所有 QWT 查询(:无论如何,会有一个新错误,C2664: 'QwtPlotItem::attach': cannot convert parameter 1 from 'QwtPlot **' to 'QwtPlot *'。知道吗?在这行代码中发现错误: (curve->attach( &plot ); // 将曲线附加到绘图上 ) @rockinfresh: 改成curve-&gt;attach(plot); 从栈切换到堆对象时不需要请求指针的地址。这已经包含一个地址。 刚刚意识到...基础知识。不敢相信我没有看到:/ 猜猜我需要休息一下,再次提高我的编程技能。不过谢谢(:【参考方案2】:

plot 应使用new 创建。现在你在堆栈上创建它,所以当on_plotButton_clicked 函数完成时它会被立即删除。 Sleep 不应该在这里使用,你不会从中得到任何好处。

QwtPlot* plot = new QwtPlot();
plot->setTitle( "Plot Demo" ); //Name the plot
//...
plot->show(); //Show plot

【讨论】:

如果我使用这种方法,会出现新的错误,C2664: 'QwtPlotItem::attach': cannot convert parameter 1 from 'QwtPlot **' to 'QwtPlot *'。任何的想法?在这行代码中发现了错误: (curve->attach( &plot ); // 将曲线附加到绘图上 ) 您应该使用attach(plot) 而不是attach(&amp;plot),因为plot 已经是一个指针。 刚刚意识到...基础知识。不敢相信我没有看到:/ 猜猜我需要休息一下,再次提高我的编程技能。不过谢谢(:真的很感激。【参考方案3】:

问题可能是您的 QwtPlot 只是一个局部变量,即使因为 sleep 也在主线程中,您也无法在函数返回之前及时绘制它。然后,当它完成睡眠时,它会破坏您的本地 QwtPlot 对象并返回,所以如果您像这样闪烁窗口,您就足够幸运了。

要让它工作,你必须这样称呼它:

QwtPlot* plot = new QwtPlot(this);

其中 this 是将托管您的绘图(如果有)的父窗口。这样,您的小部件将保持活动状态,直到您关闭它或它的父级在程序执行结束时将其销毁。

【讨论】:

会有新的错误,C2664: 'QwtPlotItem::attach': cannot convert parameter 1 from 'QwtPlot **' to 'QwtPlot *'。任何的想法?在这行代码中发现了错误: (curve->attach( &plot ); // 将曲线附加到图上 )

以上是关于Microsoft Visual Studio 中的 QWT 直方图和立即关闭的 Qt 插件的主要内容,如果未能解决你的问题,请参考以下文章

如何下载microsoft visual studio

Microsoft visual c++弹窗?

怎么用microsoft visual studio制作一个选择题

microsoft visual c++里的编译在哪里?

microsoft visual studio 2008找不到一个或多个组件,请重新安装应用程序 的原因都有哪些?

Microsoft Visual Studio 发展历史