【问题标题】:running draw_polygon example in CGAl package in qt widget application在 qt 小部件应用程序的 CGAl 包中运行 draw_polygon 示例
【发布时间】:2018-11-14 10:48:28
【问题描述】:

我尝试在 Qt 小部件应用程序中遵循 CGAL 示例: example

ma​​in.ccp:

#include "mainwindow.h"
#include <QApplication>

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

        return a.exec();
}

ma​​inwindow.ccp:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
typedef CGAL::Polyhedron_3<Kernel>                       Polyhedron;

void MainWindow::on_pushButton_clicked()
{
   QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));

draw_poly(fileName);
 }

void MainWindow::draw_poly(QString fileName)
{
    QByteArray inBytes;
    const char *c;
     inBytes = fileName.toUtf8();
     c = inBytes.constData();
          std::ifstream input(c);

          if (!input || !(input >> mesh) || mesh.is_empty()) {
            std::cerr << "Not a valid off file." << std::endl;
         //   return 1;
          }

          input >> mesh;

          CGAL::draw(mesh);
}

当我运行它时,它打开对话框文件以选择 .off 文件,然后显示以下错误:

QCoreApplication::exec: The event loop is already running

有什么帮助吗?

【问题讨论】:

    标签: c++ qt qt-creator fedora cgal


    【解决方案1】:

    我在日常业务中使用 Qt5,并且曾经将 CGAL 视为可能的应用程序基础(没有进一步朝这个方向发展——目前还没有)。因此,这个问题让我很好奇。

    我在github上翻了一下CGAL的源码,发现了错误信息的原因

    QCoreApplication::exec: The event loop is already running
    

    发生。

    为此,我从CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h复制了相关行:

    template<class Polyhedron, class ColorFunctor>
    void draw(const Polyhedron& apoly,
              const char* title,
              bool nofill,
              const ColorFunctor& fcolor)
    {  
    #if defined(CGAL_TEST_SUITE)
      bool cgal_test_suite=true;
    #else
      bool cgal_test_suite=false;
    #endif
    
      if (!cgal_test_suite)
      {
        int argc=1;
        const char* argv[2]={"polyhedron_viewer","\0"};
        QApplication app(argc,const_cast<char**>(argv));
        SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
        mainwindow.show();
        app.exec();
      }
    }
    

    查看此源代码,很明显CGAL::draw() 本身就是一个小型全功能Qt 应用程序,它建立了自己的QApplication 实例。 OP 反过来尝试将CGAL::draw() 嵌入到她/他自己的 Qt 应用程序中。不允许多次实例化QCoreApplication 的任何派生项(根据QApplication 的Qt 文档):

    对于任何使用 Qt 的 GUI 应用程序,精确地有 一个 QApplication 对象,无论应用程序在任何给定时间是否有 0、1、2 或更多窗口。

    (强调不是我的。)

    CGAL 文档。在Polyhedron/draw_polyhedron.cpp 中提供了一个(甚至更短的)示例来正确执行此操作:

    #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
    #include <CGAL/Polyhedron_3.h>
    #include <CGAL/IO/Polyhedron_iostream.h>
    #include <CGAL/draw_polyhedron.h>
    #include <fstream>
    typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
    typedef CGAL::Polyhedron_3<Kernel>                       Polyhedron;
    int main(int argc, char* argv[])
    {
      Polyhedron P;
      std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
      in1 >> P;
      CGAL::draw(P);
      return EXIT_SUCCESS;
    }
    

    但是没有地方可以在正确的位置插入QFileDialog

    因此,CGAL::draw() 是 OP(可能)打算做的错误工具——将 CGAL 多面体渲染嵌入到 Qt 应用程序中。为此,有必要直接使用CGAL::draw()内部某处调用的东西。

    所以,这对我来说是合适的:
    在 OPs Qt 应用程序中制作 SimplePolyhedronViewerQt&lt;Polyhedron, ColorFunctor&gt; 一个(主或子)小部件。

    然后,我浏览了 github 存储库,以找出实际派生自哪个 Qt 小部件 CGAL::SimplePolyhedronViewerQt&lt;Polyhedron, ColorFunctor&gt;,并找到了以下继承:

    CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
                               |
                               V
                     CGAL::Basic_viewer_qt
                               |
                               V
                       CGAL::QGLViewer
                               |
                +--------------+--------------+
                |                             |
                V                             V
          QOpenGLWidget               QOpenGLFunctions
    

    因此,CGAL::SimplePolyhedronViewerQt&lt;Polyhedron, ColorFunctor&gt; 可以像任何QWidget 一样使用(这涉及使其成为主窗口)。它也可以成为QMainWindow 的中心小部件,它获取带有QAction 的菜单栏/工具栏以打开QFileDialog,请求文件路径,使用此文件路径打开文件流,并加载来自这个文件流的网格。

    我偶然发现了另一个小细节:CGAL::Polyhedron 必须在构造函数中通过 const 引用提供给 CGAL::SimplePolyhedronViewerQt。考虑到这一点,恕我直言,有必要(在成功加载网格后)通过 new 构造 CGAL::SimplePolyhedronViewerQt 实例,然后将其设置/添加到父窗口小部件。如果这是不可接受的,则可能需要更深入地使用自己的实现替换CGAL::SimplePolyhedronViewerQt,使用前者的源代码作为“备忘单”。

    这是这样的应用程序的样子:

    #include <fstream>
    
    #include <QtWidgets>
    
    #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
    #include <CGAL/Polyhedron_3.h>
    #include <CGAL/IO/Polyhedron_iostream.h>
    #include <CGAL/draw_polyhedron.h>
    
    typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
    typedef CGAL::Polyhedron_3<Kernel>                       Polyhedron;
    
    int main(int argc, char **argv)
    {
      qDebug() << "Qt Version:" << QT_VERSION_STR;
      QApplication app(argc, argv);
      CGAL::DefaultColorFunctorPolyhedron fColor;
      Polyhedron mesh;
      // setup UI
      QMainWindow qWin;
      QToolBar qToolbar;
      QAction qCmdLoad(QString::fromUtf8("Load File..."));
      qToolbar.addAction(&qCmdLoad);
      qWin.addToolBar(&qToolbar);
      qWin.show();
      // install signal handlers
      QObject::connect(&qCmdLoad, &QAction::triggered,
        [&qWin, &mesh, &fColor]() {
          const QString filePath = QFileDialog::getOpenFileName(
            &qWin,
            QString::fromUtf8("Open .off model"),
            QString::fromUtf8("/home"),
            QString::fromUtf8("*.off"));
          if (filePath.isEmpty()) return;
          std::ifstream fIn(filePath.toUtf8().data());
          if (!(fIn >> mesh) || mesh.is_empty()) {
            qDebug() << "Loading of" << filePath << "failed!";
            return;
          }
          qWin.setCentralWidget(
            new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
              &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
          qWin.centralWidget()->show();
        });
      // runtime loop
      return app.exec();
    }
    

    请注意这一点——我手头没有 CGAL,无法编译/测试上述代码。

    【讨论】:

    • @n.m 你试过这个示例代码了吗?如果您无法编译,请发表评论。我小心翼翼地这样做了,但是,编译器通常会发现一些可抱怨的地方。
    • 很遗憾我在使用 SimplePolyhedronViewerQt 时仍然有问题,它不能用作类型
    • qWin.setCentralWidget(new SimplePolyhedronViewerQt(qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
    • @n.m 我真是个混蛋!请您将ColorFunctor 替换为CGAL::DefaultColorFunctorPolyhedron。 (我完全忘记了在示例代码中,ColorFunctor 只是一个模板参数。)
    • @Sceff 抱歉打扰,但我在上面的代码中有问题 SimplePolyhedronViewerQ 无法识别,所以我在它之前添加了“CGAL::”,但现在存在的错误是:没有匹配的函数调用'CGAL::SimplePolyhedronViewerQt<:polyhedron_3>, CGAL::DefaultColorFunctorPolyhedron>::SimplePolyhedronViewerQt(QMainWindow&, Polyhedron&, const char [24], bool, CGAL::DefaultColorFunctorPolyhedron&)' qWin, mesh, "Basic多面体查看器", false, fColor));
    【解决方案2】:

    CGAL::draw() 已经处理了 Qt 的东西。您正试图在另一个主窗口中打开一个主窗口。只需在 main() 函数中调用 CGAL::draw(mesh) 即可,无需任何其他操作。

    编辑:这正是 Sheff 以更详细的方式解释的内容。

    【讨论】:

    • 它在 main() 中工作,但我想在 GUI 应用程序中使用它,所以我想在方法中使用它并调用它
    • 你不能那样做。您必须从 Surface_mesh/include/CGAL/draw_surface_mesh.h 和 GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h 中提取重要代码,并将其适应您的应用程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-05
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多