1

大家好,我想从非成员函数更新 ui。除了将“this”指针作为我的非成员传递之外的任何帮助都是来自库的回调。

下面是我的代码:

主窗口.cpp

static void callback(QString result) 
{
ui->textBrowser->append(result);
}

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

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

void MainWindow::on_pushButton_clicked()
{
int a=1,b=2;
QLibrary myLib("myaddlib");
myLib.load();
add = (myadd)myLib.resolve("add_function");
add(callback, a, b);
}

所以我需要的是我应该能够从我的非成员回调中将数据附加到 UI。请帮我。

编辑:我不允许修改我的回调

根据评论编辑:callback将在不同的线程中调用,因此从那里调用小部件方法会出错'cannot send events to objects owned by a different thread'

4

4 回答 4

2

按照你的评论走

“我试图创建全局指针 Ui::MainWindow *myui 并在构造函数中将 myui 分配给 ui,但它引发了以下错误:'无法将事件发送到不同线程拥有的对象'。”

问题是,您callback在错误的线程中被调用。这是一个解决方案:

  1. 创建指向实际主窗口实例的全局指针,我们称之为MainWindow *mainWinInstance;. 还要注意,主窗口实例的寿命将比回调所针对的库/线程的寿命长,或者即使在主窗口被破坏后QPointer仍有被调用的风险时使用。callback

  2. 将以下插槽方法添加到MainWindow

    MainWindow::appendText(const QString &text) { // use const ref for efficiency
        ui->textBrowser->append(result);
    }
    
  3. 使用排队连接类型更改您callback以调用该方法:QMetaObject::invokeMethod

    static void callback(QString result) {
        bool r = QMetaObject::invokeMethod(mainWinInstance, 
                                           "appendText", 
                                           Qt::QueuedConnection,
                                           Q_ARG(QString, result));
        Q_ASSERT(r); // should only fail if there's a mistake in above code
    }
    

    使用Qt::QueuedConnection很重要。它将方法调用放入目标对象的正确线程的事件队列中并立即返回。然后目标线程的事件循环将执行实际调用。

于 2014-11-13T21:55:08.603 回答
1

您需要在单独的标头中创建一个接口:

itextbrowseraccessor.h

class ITextBrowserAccessor
{
public:
  void appendText(const QString& text) = 0;
}

继承MainWindowITextBrowserAccessor实现该方法:

void MainWindow::appendText(const QString& text)
{
   ui->textBrowser->append(text);
}

包含itextbrowseraccessor.h在您的库源文件中。将指向接口的指针传递给回调。

static void callback(ITextBrowserAccessor* accessor, QString result) 
{
  accessor->appendText(result);
}
于 2014-11-11T14:10:37.380 回答
0

您可以尝试使用QApplication::topLevelWidgets().

找到主窗口后,使用mainWindow->findChild<QTextBrowser*>()找到浏览器小部件,然后根据需要修改其内容。

编辑:
示例:

Q_ASSERT(QApplication::topLevelWidgets() == 1);
QWidget* mainWindow = QApplication::topLevelWidgets().first();
QTextEditor* editor = mainWindow->findChild<QTextBrowser*>();
Q_ASSERT(editor != NULL);
editor->append(QLatin1String("abc"));
于 2014-11-11T14:45:21.063 回答
0

这里提到的所有事情都对我有用。通过创建一个具有向主窗口发送信号的公共函数的虚拟 Qobject 来解决它。创建这个虚拟 qobject 的实例并在我的回调中调用公共函数。

PS:我有一个限制,不能修改我的回调,因此上述解决方案。

于 2014-12-02T13:51:01.323 回答