Qt 5.0以上mac版本一致存在这个bug,网上也有解决方案,一个是修改Qt源码重新编译,这个比较费事,另一个是将文件改为.mm后缀,使用oc代码:

 NSView* view = (NSView*)this->winId();
 NSWindow* wnd = [view window];
 [wnd miniaturize:nil];
这句代码好像在qt5.2中可以解决,然后我测试了之后的所有版本(qt5.1-qt5.9)均失败。

所以这个方案不是合适方案。我给出一个通用的方案,也是使用oc:

this->setWindowFlags(Qt::FramelessWindowHint);
这样的代码去修改Qt未无边框,改用oc:
 //去掉系统标题栏(qt 在mac使用Qt::frameless标志有bug)
    NSView* view = (NSView*)this->winId();
    NSWindow* wndd = [view window];
    wndd.titlebarAppearsTransparent = YES;
    wndd.titleVisibility = NSWindowTitleHidden;
    wndd.styleMask |= NSFullSizeContentViewWindowMask;
    [[wndd standardWindowButton:NSWindowZoomButton] setHidden:YES];
    [[wndd standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
    [[wndd standardWindowButton:NSWindowCloseButton] setHidden:YES];

这样就实现了无边框,然后可以自己定义标题栏:

this->showMinimized();
this->showMaximized();

这样的函数功能也正常。

这里还有一个问题如果窗体开始是最大化显示时,调用

this->showMinimized(); 会调用一次showNomal函数,导致在恢复时与开始状态不一致 所以这里最小化最好也使用oc
  NSView* view = (NSView*)this->winId();
  NSWindow* wnd = [view window];
  [wnd miniaturize:nil];
到这里问题就解决了么?

答案是否定的,上面的方法表面上却是解决了, 但是有个一个问题,会导致qt的内存异常,我测试大概要增长1.5倍,如果你的程序只有100M左右,那么着不算什么,上面的解决方案可用,如果你的程序本身就有500M+。这个方案就悲剧了。

QMacNativeWidget

这个类就是用来将qt的窗体潜入oc的。 大家应该知道我的思路了

//以下oc代码为了解决qt设置无边框后 不能最小化的问题
/*******************oc start*************************/
@interface SGRoundView : NSView
@implementation SGRoundView
- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    // Drawing code here.
    [[NSColor colorWithDeviceCyan:0.23 magenta:0.17 yellow:0.17 black:0 alpha:1] set];
    NSRectFill(dirtyRect);
@interface SGRoundWindow : NSWindow
@implementation SGRoundWindow
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
    self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask  backing:bufferingType defer:flag];
    if ( self )
        //设置窗口为无边界
        [self setStyleMask:NSBorderlessWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask];
        //设置窗口为透明
        [self setOpaque:NO];
        //设置背景无色
        [self setBackgroundColor:[NSColor clearColor]];
        //设置为点击背景可以移动窗口
        [self setMovableByWindowBackground:YES];
        [self setHasShadow:YES];
    return self;
//实现圆角,直播晕是直角故这里不需要
//- (void) setContentView:(NSView *)aView
//    aView.wantsLayer            = YES;
//    aView.layer.frame           = aView.frame;
//    aView.layer.cornerRadius    = 0;
//    aView.layer.masksToBounds   = YES;
//    [super setContentView:aView];
//如果不写此方法,生产的窗口上,添加的一些控件或文本处于editable
//加上此方法是使window变为keywindow
//一般是在无TitleBar时,也就是BorderlessWindow,才覆写此方法
//有TitleBar的Window默认是KeyWindow
- (BOOL)canBecomeKeyWindow
    return YES;
-(BOOL)canBecomeMainWindow {
    return YES;
/*******************oc end*************************/
QMacNativeWidget * changeWidgetToMacNativeWidge ( QWidget widget ,
QMacNativeWidget* WindowMgr::changeWidgetToMacNativeWidget(QWidget *widget, int x, int y)
    if(Q_NULLPTR == widget)
        return Q_NULLPTR;
    SGRoundWindow*nsWindow = [[SGRoundWindow alloc] initWithContentRect:NSMakeRect(x, y, widget->width(), widget->height())
      styleMask:NSTitledWindowMask | NSClosableWindowMask
                                       | NSMiniaturizableWindowMask | NSResizableWindowMask
                        backing




    
:NSBackingStoreBuffered defer:NO];
     nsWindow.collectionBehavior = NSWindowCollectionBehaviorFullScreenPrimary;
    QMacNativeWidget *nativeWidget = new QMacNativeWidget();
    nativeWidget->setWindowFlags(Qt::FramelessWindowHint);
    nativeWidget->move(0,0);
    QVBoxLayout *layout = new QVBoxLayout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->addWidget(widget);
    nativeWidget->setLayout(layout);
    // Adjust Cocoa layouts
    NSView *nativeWidgetView = reinterpret_cast<NSView *>(nativeWidget->winId());
    NSView *contentView = [nsWindow contentView];
    [contentView setAutoresizesSubviews:YES];
    [nativeWidgetView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
    [nativeWidgetView setAutoresizesSubviews:YES];
    [nativeWidgetView setAutoresizingMask:NSViewWidthSizable];
    // Add the nativeWidget to the window.
   [contentView addSubview:nativeWidgetView positioned:NSWindowAbove relativeTo:nil];
    return nativeWidget;
    if(Q_NULLPTR == widget)
        return Q_NULLPTR;
    NSWindow*nsWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(x, y, widget->width(), widget->height())
                        styleMask:NSTitledWindowMask | NSClosableWindowMask
                                  | NSMiniaturizableWindowMask | NSResizableWindowMask
                        backing:NSBackingStoreBuffered defer:NO];
    //去掉标题栏
    nsWindow.titlebarAppearsTransparent = YES;
    nsWindow.titleVisibility = NSWindowTitleHidden;
    nsWindow.styleMask |= NSFullSizeContentViewWindowMask;
    [[nsWindow standardWindowButton:NSWindowZoomButton] setHidden:YES];
    [[nsWindow standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
    [[nsWindow standardWindowButton:NSWindowCloseButton] setHidden:YES];
    QMacNativeWidget *nativeWidget = new QMacNativeWidget();
    nativeWidget->setWindowFlags(Qt::FramelessWindowHint);
    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(widget);
    nativeWidget->setLayout(layout);
    // Adjust Cocoa layouts
    NSView *nativeWidgetView = reinterpret_cast<NSView *>(nativeWidget->winId());
    NSView *contentView = [nsWindow contentView];
    [contentView setAutoresizesSubviews:YES];
    [nativeWidgetView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
    [nativeWidgetView setAutoresizesSubviews:YES];
    [nativeWidgetView setAutoresizingMask:NSViewWidthSizable];
    // Add the nativeWidget to the window.
   [contentView addSubview:nativeWidgetView positioned:NSWindowAbove relativeTo:nil];
    // Show the window.
    [nsWindow makeKeyAndOrderFront:nsWindow];
    return nativeWidget;
int main(int argc, char *argv[])
    QApplication app(argc, argv);
    MainWindow *mainwindow = new MainWindow();
    mainwindow->setFixedSize(app.desktop()->width(), app.desktop()->height());
    QWidget *widget = changeWidgetToMacNativeWidget(mainwindow, 0, 40);
    widget->show();
    return app.exec();

然后你就可以对MainWindow实现最小化,如放一个按钮,链接一下槽:

void MainWindow::minize()
   [windo1 miniaturize:nil];

跑一下,点一下最小化,效果还可以跟系统的一样。

但还有一个问题,这里应该是

QMacNativeWidget

的一个bug,最小化有点级dock栏的按钮无法显示窗体,但是不要怕,我既然写了,就有解决方案:

connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(slot_restoreWindow(Qt::ApplicationState)));

应用程序激活的时候会信号,链接一下

void MainWindow:slot_restoreWindow
(Qt::ApplicationState state)
    if(state == Qt::ApplicationActive)
        [window makeKeyAndOrderFront:window];

这里的window是

changeWidgetToMacNativeWidge返回的QMacNativeWidget所以要保存一下,QMacNativeWidget可以获取NSVIew,NSview可以获取到window

到这里这个问题算是解决了,期待各位更好的解决方案

不过还是期望Qt新版本能解决这个问题。毕竟这个bug已经出现好久了

在Windows和macOS上均具有Qt的真正无框架窗口 我对自己的应用程序外观很挑剔,所以我想控制整个应用程序区域。 Windows和macOS都在其窗口上绘制标题栏镶边,这很难从应用程序控制。 令人惊奇的是,除去这种Chrome。 Qt具有“ Qt :: FramelessWindowHint”属性,该属性可按所述方式绘制无框架窗口,但是它的代价是最小/最大/关闭,调整大小以及在Windows上使用Aero Snap功能。 您可以自己重新实现“最小/最大” /“关闭” /“调整大小”,但是我觉得没有Aero Snap太烦人了。 有一些针对Windows的嵌入式项目,例如BorderlessWindow和lib sleek旨在解决此问题,但它们需要至少1px的边框(不完整)才能显示Qt小部件下方的本机窗口,以调整大小。 它们还附带了自己 1.Qt窗口无边框时,最小化失效 https://www.jianshu.com/p/3b4777a0bae1 基本原理是:在执行最小化之前先取消窗口无边框,而从最小化显示窗口时(后)再设置窗口无边框。 //设置透明标题栏 flags: Qt.Window | Qt.FramelessWindowHint //去标题栏 color: "transparent" onWindowStateChanged: { console.log("state changed 试过国内网上的很多方法,但都是无效的,我的qt版本是5.14.2,所以翻墙找到了可以用的方法(国内的macqt开发的资料真的太少了,而且mac下的qt真的很坑)。 在 最小化函数里用下面的代码: NSView* view = (NSView*)window()->winId(); NSWindow* wnd = [view window]; [wnd setStyleMask:[wnd styleMask] | NSWindowStyleMaskMiniaturizable]; showMin title: 让自定义view铺满整个NSWindow我们通过IB拖到窗体中的控件都是放到NSWindow的contentView视图中的,但是这个contentView不是铺满整个window的,顶部会有一个系统风格的titlebarView,现在项目需要让自定义的view可以铺满整个window。 在OS X 10.10之前,我们可以通过简单的两行代码来搞定://把自定义的view添加到con 如果只setWindowFlags(Qt::FramelessWindowHint); 去掉边框,此时会发现,当程序打开后,单击任务栏的按钮,会发现无法最小化,隐藏窗口。 解决的方法是:setWindowFlags(Qt::Window|Qt::FramelessWindowHint |Qt::WindowSystemMenuHint|Qt::WindowMinimizeButtonHint|Qt::WindowMaximizeButtonHint); 再次测试,发现边框去掉了,而且鼠标点击任务栏图标,也可 w.setWindowFlags(w.windowFlags()&amp;~Qt::WindowMaximizeButtonHint&amp;~Qt::WindowMinimizeButtonHint); w.showMaximized(); NSApplication *application = [NSApplication sharedApplication]; [[application.mainWindow standardWindowButton:NSWindowZoomButton] setHidden:YES]; [[application.mainWindow standardWindowButton:NSWind 1 Esc 切换到代码编辑状态 2 F1 查看帮助(选中某一类或函数,按下F1,出现帮助文档) ==3 F2 在光标选中对象的声明和定义之间切换(和Ctrl+鼠标左键一样的效果,选中某一类或函数,按下F2,迅速定位到该类或函数声明的地方或被调用的地方) == 4 F3 查找下一个 5 F4 头文件和源文件之间切换 6 F5 开始调试/继续执行 7 F9 设置和取消断点 8 F1...