Доступ к указателю на пользовательский интерфейс из библиотеки (DLL)

Привет всем, я хочу обновить пользовательский интерфейс из функции, не являющейся членом. Любая помощь, кроме передачи указателя this в качестве моего не члена, является обратным вызовом из библиотеки.

Ниже мой код:

mainwindow.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);
}

Так что все, что мне нужно, это то, что я должен иметь возможность добавлять данные в пользовательский интерфейс из моего не члена обратного вызова. Пожалуйста, помогите мне.

РЕДАКТИРОВАТЬ: мне не разрешено изменять мой обратный вызов

РЕДАКТИРОВАТЬ на основе комментария: callback будет вызван в другом потоке, поэтому вызов метода виджета оттуда дает ошибку 'cannot send events to objects owned by a different thread'

1

Решение

Исходя из вашего комментария

«Я пытался создать глобальный указатель Ui :: MainWindow * myui и назначил
Мой пользовательский интерфейс в конструкторе, но он выдает мне следующую ошибку:
‘не может отправлять события объектам, принадлежащим другому потоку’. «

Проблема в том, что ваш 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 это важно. Он поместит вызов метода в очередь событий правильного потока целевого объекта и немедленно вернется. Цикл событий целевого потока будет затем выполнять фактический вызов.

2

Другие решения

Вам нужно создать интерфейс в отдельном заголовке:

itextbrowseraccessor.h

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

унаследовать MainWindow от ITextBrowserAccessor и реализовать метод:

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

Включают itextbrowseraccessor.h в исходном файле вашей библиотеки. Передайте указатель на интерфейс для обратного вызова.

static void callback(ITextBrowserAccessor* accessor, QString result)
{
accessor->appendText(result);
}
1

Вы можете попытаться найти главное окно, используя 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"));
0

Ничто из того, что было здесь упомянуто, не сработало.
Решил это, создав фиктивный объект Qobject, который имеет публичную функцию для отправки сигнала в главное окно. Создайте экземпляр этого фиктивного объекта qobject и вызовите публичную функцию внутри моего обратного вызова.

PS: у меня есть ограничение не изменять мой обратный вызов, следовательно, вышеупомянутое решение.

0
По вопросам рекламы [email protected]