How to start Go's main function from within the NSApplication event loop?

限于喜欢 提交于 2019-12-06 00:52:20

Using QApplication together with a Runloop

Regarding your question how to use your QApplication together with a NSRunloop: you are doing it already. Since you are using QApplication (and not QCoreApplication) you already have a Runloop running,

see http://code.qt.io/cgit/qt/qt.git/plain/src/gui/kernel/qeventdispatcher_mac.mm and http://code.qt.io/cgit/qt/qt.git/plain/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm

Proof

A NSTimer needs a run loop to work. So we could add quick test with an existing example Qt app called 'widget' from the repository you referenced in your question.

Adding a small Objective-C test class TimerRunloopTest with a C function wrapper that can be called from GO:

#import <Foundation/Foundation.h>
#include <os/log.h>


@interface TimerRunloopTest : NSObject

- (void)run;

@end

void runTimerRunloopTest() {

    [[TimerRunloopTest new] run];

}


@implementation TimerRunloopTest

- (void)run {

    os_log_t log = os_log_create("widget.example", "RunloopTest");
    os_log(log, "setup happening at %f", NSDate.timeIntervalSinceReferenceDate);


    [NSTimer scheduledTimerWithTimeInterval:1.0
                                     target:self
                                   selector:@selector(timerTick:)
                                   userInfo:nil
                                    repeats:YES];
}

- (void)timerTick:(NSTimer *)timer {
    os_log_t log = os_log_create("widget.example", "RunloopTest");
    os_log(log, "timer tick %f", NSDate.timeIntervalSinceReferenceDate);
}

@end

GO counterpart timerrunlooptest.go

package main

/*
#cgo LDFLAGS: -framework Foundation

void runTimerRunloopTest();
*/
import "C"

func runTimerRunloopTest() { C.runTimerRunloopTest() }

Change in main.go

At the end before app.Exec() add this line:

runTimerRunloopTest()

Build and Run it

Switch loggin on for our logging messages:

sudo log config --subsystem widget.example --mode level:debug

Afterwards build an run it:

$(go env GOPATH)/bin/qtdeploy test desktop examples/basic/widgets

Test

In the macOS Console uitlity we can now see, that the timer ticks are shown, proofing that a run-loop is running

NSAlert

Then you cited in your question, that NSAlert needs a run loop to work. We already proofed that we have one, but testing it explicitely makes sense.

So we can modify timerrunlooptest.go to inform it, that we want to link agains Cocoa also, not only Foundation:

package main

/*
#cgo LDFLAGS: -framework Foundation
#cgo LDFLAGS: -framework Cocoa

void runTimerRunloopTest();
*/
import "C"

func runTimerRunloopTest() { C.runTimerRunloopTest() }

Then we could add the following code to the run method of TimerRunLoopTest:

#import <Cocoa/Cocoa.h>

...


NSAlert *alert = [[NSAlert alloc] init];
alert.messageText = @"Message";
alert.informativeText = @"Info";
[alert addButtonWithTitle:@"OK"];
[alert runModal];

Result

After doing a

$(go env GOPATH)/bin/qtdeploy test desktop examples/basic/widgets

the native Alert is shown from the GO/QT application as expected:

Mixing Qt with Native Code

Although we seem to be able to display native alerts in the way described above, there is this hint in the QT documents that may or may not be useful:

Qt's event dispatcher is more flexible than what Cocoa offers, and lets the user spin the event dispatcher (and running QEventLoop::exec) without having to think about whether or not modal dialogs are showing on screen (which is a difference compared to Cocoa). Therefore, we need to do extra management in Qt to handle this correctly, which unfortunately makes mixing native panels hard. The best way at the moment to do this, is to follow the pattern below, where we post the call to the function with native code rather than calling it directly. Then we know that Qt has cleanly updated any pending event loop recursions before the native panel is shown.

see https://doc.qt.io/qt-5/macos-issues.html#using-native-cocoa-panels

There is also a small code example for this.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!