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,所以翻墙找到了可以用的方法(国内的mac下qt开发的资料真的太少了,而且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()&~Qt::WindowMaximizeButtonHint&~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...