app.exec() 不能调用其他方法(static lib Qt)
app.exec() cannot call other method (static lib Qt)
我创建了一个静态库Qt。我需要通过调用一些方法来更改图片的位置。问题是"app.exec()"完全阻止了该过程。你知道怎么做吗?
多谢!
这是我的库头文件
int init(int argc, char *argv[], int width, int height);
void changePos (int x, int y);
void destroyPic();
我的初始化是: Q维吉特* 窗口(0); QLabel* 图片(0);
int init(int argc, char *argv[], int width, int height) {
// initialize resources, if needed
Q_INIT_RESOURCE(target);
QApplication app(argc, argv);
window = new QWidget();
window->setWindowTitle("Test");
window->setFixedSize(width, height);
// create and show your widgets here
pic = new QLabel(window);
QPixmap pixmap(QString(":/res/pic.png"));
pic->setPixmap(pixmap);
pic->move(100,100);
pic->setVisible(true);
window->show();
app.exec();
return 0;
}
问题是我无法在我的主代码(使用此库)中调用方法changePos或销毁,因为app.exec()阻止了该过程...怎么办?
多谢!
您需要
在单独的QThread中启动QApplication。这显示在下面的代码中。我还没有让它在OS X上运行,但我相信它应该是可行的。我首先需要为OS X制作一个调试版本,然后我会看看发生了什么。它经过测试可以在Windows上运行,并且可能也可以在X11上运行。Objective C 代码仅适用于 mac,它可能是必需的,但还不够。
它是一个完整的可运行应用程序,对于一个库,您将删除main()
函数并调用 init、changePos 并根据需要直接完成。
#applib.pro
QT += core gui
TARGET = applib
TEMPLATE = app
!x11:!embedded:!qpa:mac {
LIBS_PRIVATE += -framework Cocoa -lz
OBJECTIVE_SOURCES += thread.mm
}
SOURCES += main.cpp
//main.cpp
#include <cstdlib>
#include <QtCore/QThread>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
#include <QtCore/QWaitCondition>
#include <QtCore/QEvent>
#include <QtGui/QLabel>
#include <QtGui/QApplication>
//
// API
//
extern "C" {
void init(int argc, char ** argv);
void changePos(int x, int y);
void finish();
}
// demonstration code, remove from the library
int main(int argc, char ** argv)
{
class Helper : private QThread {
public:
static void msleep(unsigned long ms) {
QThread::msleep(ms);
}
};
init(argc, argv);
Helper::msleep(2000);
changePos(0, 0);
Helper::msleep(2000);
finish();
}
//
// IMPLEMENTATION
//
struct PosEvent : public QEvent
{
PosEvent(int x_, int y_) : QEvent(t()),
x(x_), y(y_) {}
const int x, y;
static QEvent::Type t() { return (QEvent::Type)(QEvent::User + 0); }
};
class Widget : public QLabel
{
public:
Widget() : QLabel("Hello!") {}
protected:
void customEvent(QEvent * ev) {
if (ev->type() == PosEvent::t()) {
PosEvent * pev = static_cast<PosEvent*>(ev);
move(pev->x, pev->y);
}
}
};
class QCoreApplicationPrivate {
public:
static QThread * theMainThread;
};
extern "C++" { Qt::HANDLE qt_application_thread_id; }
class AppThread : public QThread
{
public:
AppThread(int& argc_, char ** argv_) {
Q_ASSERT(!instance);
instance = this;
QMutexLocker lock(&argMutex);
argc = &argc_;
argv = argv_;
start();
wc.wait(&argMutex);
}
static void changePos(int x, int y) {
QCoreApplication::postEvent(instance->widget, new PosEvent(x,y));
}
static void finish() {
instance->app->exit();
instance->wait();
delete instance;
}
protected:
void run() {
int i = 0;
#ifdef Q_OS_UNIX
//qDebug("%p", qt_application_thread_id);
QCoreApplicationPrivate::theMainThread = QThread::currentThread();
#endif
QApplication a(i, 0);
app = &a;
wc.wakeAll();
Widget w;
widget = &w;
w.show();
rc = a.exec();
}
private:
static AppThread * instance;
QCoreApplication * app;
QObject * widget;
QMutex argMutex;
QWaitCondition wc;
int* argc;
char** argv;
int rc;
};
AppThread * AppThread::instance = 0;
bool multiThreader();
#ifndef Q_OS_MAC
bool multiThreader() { return true; }
#endif
extern "C" void init(int argc, char ** argv) {
multiThreader();
#ifdef Q_OS_MAC
qDebug("DYLD_IMAGE_SUFFIX=%s", getenv("DYLD_IMAGE_SUFFIX"));
#endif
new AppThread(argc, argv);
}
extern "C" void changePos(int x, int y) { AppThread::changePos(x, y); }
extern "C" void finish() { AppThread::finish(); }
//thread.mm
#import <Foundation/Foundation.h>
@interface DeadThread : NSObject { ;; }
+ (void)enterMultiThreadedMode;
+ (void)emptyThreadMethod:(id)obj;
@end
@implementation DeadThread
+ (void)enterMultiThreadedMode {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSThread detachNewThreadSelector:@selector(emptyThreadMethod:)
toTarget:[DeadThread class] withObject:nil];
[pool release];
}
+ (void)emptyThreadMethod:(id)obj { (void)obj; }
@end
bool multiThreader()
{
[DeadThread enterMultiThreadedMode];
return [NSThread isMultiThreaded];
}
您可以在使用 QApplication::exec() 进入 QApplication 事件循环之前调用 init()。
我能想到的唯一其他选择是:
-
懒惰的 init,当即使是库的用户调用 changePos() 或 destroyPic() 时,如果还没有被调用,就会调用 init()。
-
在事件循环后使用单次计时器执行:
像这样:
QTimer::singleShot(0, this, SLOT(init()));
这将要求你有一个QObject,并且init或其他一些调用init的函数很多。在 QApplication::exec() 之前调用它,时隙将在事件循环启动后执行。
相关文章:
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- JSON转换为nlohmann JSON-lib中的结构数组
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 使用 VS2015 在 Windows 10 上构建 Fortran .lib x64 位并将其链接到 C++
- 为什么我的链接器在找到Coin4d.lib后搜索Coin4sd.lib?
- 收到错误"invalid use of non-static data member 'stu::n' "
- libcpmtd.lib有什么用?
- LNK1104:无法打开libpjproject-i386-Win32-vc14-Debug-Static.lib
- 解析引用 |exe/dll vs lib
- 我应该在 C++ 中何时/为什么使用 STATIC?
- 在VS2019项目中集成ImageMagick:x64-windows-static library
- 在 /usr/local/lib 下找不到库
- LLVM 编译:目标的配方 '../lib/IR/Release+Asserts/Intrinsics.gen.tmp' failed
- CMake 生成的 MSVC 项目找不到符号,即使为其相关 dll 正确生成了 lib 文件也是如此
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- 无法在 DLL 中链接 SDL2-static.lib
- C++如何判断static.lib是否有效,是否可从外部代码调用
- app.exec() 不能调用其他方法(static lib Qt)