使用 Qt GUI 编写 c++ dll,在自定义小部件中显示失败

Posted

技术标签:

【中文标题】使用 Qt GUI 编写 c++ dll,在自定义小部件中显示失败【英文标题】:Writing c++ dll with Qt GUI, displaying fails in custom widget 【发布时间】:2017-10-27 15:38:44 【问题描述】:

我正在为无法修改的应用程序编写 dll。这个应用程序正在向我的 dll 发送请求,我可以在单请求模式下运行这个应用程序,也可以在它以某种循环发送请求和处理响应的情况下自动运行。我不知道这种自动模式究竟是如何工作的,我也无法访问源代码来查看差异。

在我的 dll 中,我有一个继承 QMainWindow 的自定义 MainWindow 类,其中包含两个对象:继承 QPlainTextEdit 的 LogWindow 和继承 QWidget 的自定义 Widget。我想根据主应用程序的请求在我的小部件中显示一些文本并更改一些属性。这一切都适用于单个请求。但是,在自动模式下,仅更新文本。我需要一些帮助才能在小部件中进行更新。现在一些实现细节:

在我的 dll 代码中,我有应用程序和主窗口的全局变量:

QApplication * app = nullptr; 
MainWindow * win = nullptr;

我在加载 dll 时创建它们:

app = new QApplication(*argc, argv);
win = new MainWindow;
win->show();
app->processEvents();

我的主窗口如下所示:

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

    ui->setupUi(this);
    connect(this, &MainWindow::message_received, ui->log_window, &LogWindow::appendMessage);
    connect(this, &MainWindow::colors_received, ui->custom_widget, &CustomWidget::set_colors);


void MainWindow::append_log(std::string const & str) 
    emit message_received(QString::fromStdString(str));

void MainWindow::display_colors(Colors const & colors) 
    emit colors_received(colors);   

我根据应用程序的请求调用“append_log()”和“display_colors()”。这些是被调用的插槽:

void LogWindow::appendMessage(const QString & message) 
    this->appendPlainText(message);

在自定义小部件中:

void CustomWidget::set_colors(Colors const & colors) 
    setStyleSheet("background-color: red");

根据 dll 的请求,我同时调用了“win->append_log()”和“win->display_colors()”。正如我所说,在自动模式下只显示文本,但不更新颜色。我猜 PlainTextEdit::appendPlainText() 方法必须调用一些更新,但我不知道如何将行为复制到我的类上。我尝试了“update()”和“repaint()”,但似乎没有任何效果。

我想以前没有人遇到过类似的问题,但我会很感激一些关于尝试什么或在哪里寻找的建议。

更新

原来CustomWidget::set_colors() 在“自动”模式下运行时不会调用方法。我假设它被调用了,因为我使用与LogWindow::appendMessage() 完全相同的方法来调用它。

现在的问题是为什么不调用它。一些代码细节:

class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void append_log(std::string const &);
    void display_colors(Colors const &);
signals:
    void message_received(QString const &);
    void colors_received(Colors const &);

private:
    Ui::MainWindow *ui;
;

class LogWindow : public QPlainTextEdit

public:
    LogWindow();
    LogWindow(QWidget * parent);
public slots:
    void appendMessage(QString const &);
;

class CustomWidget : public QWidget

    Q_OBJECT

public:
    CustomWidget(QWidget *);
    CustomWidget(QWidget *, Colors);

public slots:
    void set_colors(Colors const &);

;

来自生成的setupUi()函数:

centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
log_window = new LogWindow(centralWidget);
log_window->setObjectName(QStringLiteral("log_window"));
log_window->setGeometry(QRect(10, 10, 421, 561));
custom_widget = new CustomWidget(centralWidget);
custom_widget->setObjectName(QStringLiteral("custom_widget"));
custom_widget->setGeometry(QRect(439, 9, 381, 331));
MainWindow->setCentralWidget(centralWidget);

可能我遗漏了一些东西,但在我看来,这两种方法的调用方式完全相同。不幸的是,其中只有一个在工作。寻找可能是什么问题的建议。

【问题讨论】:

您确定setStyleSheet() 是在“自动模式”下调用的吗?如果它在你“手动”调用时有效,则表明它在不起作用时根本不调用。 @BenjaminT 感谢您的建议!这确实是问题所在。我认为它会被调用,因为这两种方法看起来完全一样。我添加了std::abort() 而不是setStyleSheet(),它只在“手动”模式下崩溃,而不是在“自动”模式下。但是,这并不能解决我的问题:我仍然不知道为什么不调用它。我用更多代码更新了这个问题。 您没有解释“自动”和“手动”之间的区别。你做什么动作?调用什么函数?我之前的评论也仍然成立(递归地):你确定 colors_received() 信号被调用(发出)吗?您必须跟进电话,直到发现错误。而不是 std::abort() 使用调试器或至少 qDebug(). MainWindow::display_colors() 被调用,它正在发射colors_received()。问题一定是由于某种原因信号没有触发插槽。正如我所提到的,我的 dll 由我无法修改的应用程序运行,我只有 *.exe 文件和一个基本手册,它导入/导出了哪些 dll 功能。我也不知道“自动”模式究竟是如何工作的,只是与正在返回的“手动”模式相比,它是一些连续的流程。由于上述原因,我也无法调试(或至少不知道如何调试)并且没有qDebug() 如果发出信号并且未调用插槽,则表示它们未连接。你检查QObject::connect()的返回值了吗? 【参考方案1】:

槽/信号机制不适用于自定义类Colors,因为它没有在 Qt 元对象系统中注册。在信号连接之前添加此行解决了问题:

qRegisterMetaType<Colors>("Colors");

【讨论】:

以上是关于使用 Qt GUI 编写 c++ dll,在自定义小部件中显示失败的主要内容,如果未能解决你的问题,请参考以下文章

比较 GTK+、Qt 和 MATLAB 为 C++ 编写的科学程序开发 GUI [关闭]

在 Qt 中使用信号会破坏 DLL

如何在自定义文件浏览对话框Qt C++中实现返回和下一步按钮

OpenGL / C++ / Qt - 需要的建议

在 C++ opencv 中扩展的 GUI

一个简单的Qt词典程序