如何在QML中创建一个没有标题栏但带有关闭/最小化/最大化按钮的窗口?

huangapple go评论120阅读模式
英文:

How to create a window without a title bar but with the close/minimize/maximizie buttons in QML?

问题

我想创建一个没有标题栏,但带有本地关闭、最小化和最大化按钮的应用程序。这是布局的意图:

如何在QML中创建一个没有标题栏但带有关闭/最小化/最大化按钮的窗口?

该应用程序使用Go和QML构建。我能够通过添加以下代码来移除标题栏:

  1. flags: Qt.FramelessWindowHint | Qt.Window

但这意味着我需要重新创建各种本地行为,比如窗口移动和调整大小。我还要手动重新创建关闭/最小化/全屏按钮,但这意味着我失去了窗口在Windows上的吸附功能或Mac上的缩放选项等各种本地操作系统行为。

有没有更好的方法来实现这一点?是否至少可以创建本地的最大化、最小化和关闭按钮,而不是从头开始构建?

谢谢

英文:

I want to create an application without the title bar, but with native close, minimize and maximize buttons. This is the intent of the layout:

如何在QML中创建一个没有标题栏但带有关闭/最小化/最大化按钮的窗口?

The app is built using Go and QML. I was able to remove the title bars by adding:

  1. flags: Qt.FramelessWindowHint | Qt.Window

But this means that I'm having to recreate all kinds of native behaviors, like window moving and resizing. I'm also recreating the close/minimize/fullscreen buttons by hand, but it means I lose all kinds of native OS behaviour like the window snapping in windows or the zoom option on mac.

Is there a better way to do this? Is it possible at least to create the native max-min-close buttons instead of building it by scratch?

Thanks for all

答案1

得分: 5

你可以使用Objective-C来正确设置窗口。这可能会有一些错误,但是通过以下方法我已经使其正常工作(创建一个单独的.mm类):

  1. #include "macwindow.h"
  2. #include <Cocoa.h>
  3. MacWindow::MacWindow(long winid)
  4. {
  5. NSView *nativeView = reinterpret_cast<NSView *>(winid);
  6. NSWindow* nativeWindow = [nativeView window];
  7. [nativeWindow setStyleMask:[nativeWindow styleMask] | NSFullSizeContentViewWindowMask | NSWindowTitleHidden];
  8. [nativeWindow setTitlebarAppearsTransparent:YES];
  9. [nativeWindow setMovableByWindowBackground:YES];
  10. }

在你的main.cpp中,你需要像这样传递窗口ID:

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QWindow>
  4. #include "macwindow.h"
  5. int main(int argc, char *argv[])
  6. {
  7. QGuiApplication app(argc, argv);
  8. QQmlApplicationEngine engine;
  9. engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
  10. QWindowList windows = QGuiApplication::allWindows();
  11. QWindow* win = windows.first();
  12. MacWindow* mac = new MacWindow(win->winId());
  13. return app.exec();
  14. }

在你的.pro文件中,你需要添加Cocoa引用:

  1. macx:LIBS += -framework Foundation -framework Cocoa
  2. macx:INCLUDEPATH += /System/Library/Frameworks/Foundation.framework/Versions/C/Headers \
  3. /System/Library/Frameworks/AppKit.framework/Headers \
  4. /System/Library/Frameworks/Cocoa.framework/Headers

不确定为什么,但是我不得不添加一个具有焦点属性的TextEdit,以正确绘制窗口,否则它会显示为纯黑色(我的main.qml):

  1. import QtQuick 2.5
  2. import QtQuick.Window 2.2
  3. import QtQuick.Controls 1.4
  4. ApplicationWindow {
  5. visible: true
  6. color: "white"
  7. width: 600
  8. height: 400
  9. minimumWidth: width
  10. minimumHeight: height
  11. maximumWidth: width
  12. maximumHeight: height
  13. Rectangle {
  14. anchors.fill: parent
  15. color: "white"
  16. TextEdit {
  17. opacity: 0
  18. focus: true
  19. }
  20. }
  21. }

如何在QML中创建一个没有标题栏但带有关闭/最小化/最大化按钮的窗口?

英文:

You can use objective-c to setup your window correctly. This might be a little buggy, but I got it working through this (create a separate .mm class):

  1. #include &quot;macwindow.h&quot;
  2. #include &lt;Cocoa.h&gt;
  3. MacWindow::MacWindow(long winid)
  4. {
  5. NSView *nativeView = reinterpret_cast&lt;NSView *&gt;(winid);
  6. NSWindow* nativeWindow = [nativeView window];
  7. [nativeWindow setStyleMask:[nativeWindow styleMask] | NSFullSizeContentViewWindowMask | NSWindowTitleHidden];
  8. [nativeWindow setTitlebarAppearsTransparent:YES];
  9. [nativeWindow setMovableByWindowBackground:YES];
  10. }

In your main.cpp you need to pass the window id like this:

  1. #include &lt;QGuiApplication&gt;
  2. #include &lt;QQmlApplicationEngine&gt;
  3. #include &lt;QWindow&gt;
  4. #include &quot;macwindow.h&quot;
  5. int main(int argc, char *argv[])
  6. {
  7. QGuiApplication app(argc, argv);
  8. QQmlApplicationEngine engine;
  9. engine.load(QUrl(QStringLiteral(&quot;qrc:/main.qml&quot;)));
  10. QWindowList windows = QGuiApplication::allWindows();
  11. QWindow* win = windows.first();
  12. MacWindow* mac = new MacWindow(win-&gt;winId());
  13. return app.exec();
  14. }

In your .pro file you'll need to add the Cocoa reference:

  1. macx:LIBS += -framework Foundation -framework Cocoa
  2. macx:INCLUDEPATH += /System/Library/Frameworks/Foundation.framework/Versions/C/Headers \
  3. /System/Library/Frameworks/AppKit.framework/Headers \
  4. /System/Library/Frameworks/Cocoa.framework/Headers

Not sure why, but I had to add a TextEdit with the focus attribute to get the window drawn correctly, otherwise it appeared just black (my main.qml):

  1. import QtQuick 2.5
  2. import QtQuick.Window 2.2
  3. import QtQuick.Controls 1.4
  4. ApplicationWindow {
  5. visible: true
  6. color: &quot;white&quot;
  7. width: 600
  8. height: 400
  9. minimumWidth: width
  10. minimumHeight: height
  11. maximumWidth: width
  12. maximumHeight: height
  13. Rectangle {
  14. anchors.fill: parent
  15. color: &quot;white&quot;
  16. TextEdit {
  17. opacity: 0
  18. focus: true
  19. }
  20. }
  21. }

如何在QML中创建一个没有标题栏但带有关闭/最小化/最大化按钮的窗口?

答案2

得分: 0

我的解决方案(基于Eduard的方案,调整了窗口可拖动的部分)。

(完整的源代码请参考https://github.com/teimuraz/qt-macos-without-title)

创建macos.h和macos.mm文件(如果使用qt creator创建,请将macos.cpp重命名为macos.mm)。

macos.h

  1. #ifndef MACOS_H
  2. #define MACOS_H
  3. #include <QGuiApplication>
  4. #include <QWindow>
  5. class MacOS {
  6. MacOS(long winid);
  7. public:
  8. static void removeTitlebarFromWindow(long winId = -1);
  9. };
  10. #endif // MACOS_H

macos.mm

  1. #include "macos.h"
  2. #include <Cocoa/Cocoa.h>
  3. #include <QGuiApplication>
  4. #include <QWindow>
  5. void MacOS::removeTitlebarFromWindow(long winId)
  6. {
  7. if(winId == -1) {
  8. QWindowList windows = QGuiApplication::allWindows();
  9. QWindow* win = windows.first();
  10. winId = win->winId();
  11. }
  12. NSView *nativeView = reinterpret_cast<NSView *>(winId);
  13. NSWindow* nativeWindow = [nativeView window];
  14. [nativeWindow setStyleMask:[nativeWindow styleMask] | NSFullSizeContentViewWindowMask | NSWindowTitleHidden];
  15. [nativeWindow setTitlebarAppearsTransparent:YES];
  16. [nativeWindow setMovableByWindowBackground:YES];
  17. }

main.qml

  1. import QtQuick
  2. import QtQuick.Controls
  3. ApplicationWindow {
  4. id: mainWindow
  5. visible: true
  6. width: 640
  7. height: 480
  8. // 让窗口可拖动,当前整个窗口区域都可拖动,但可以调整为只能拖动顶部区域
  9. property int previousX
  10. property int previousY
  11. MouseArea {
  12. anchors {
  13. top: parent.top
  14. bottom: parent.bottom
  15. left: parent.left
  16. right: parent.right
  17. }
  18. onPressed: {
  19. previousX = mouseX
  20. previousY = mouseY
  21. }
  22. onMouseXChanged: {
  23. var dx = mouseX - previousX
  24. mainWindow.setX(mainWindow.x + dx)
  25. }
  26. onMouseYChanged: {
  27. var dy = mouseY - previousY
  28. mainWindow.setY(mainWindow.y + dy)
  29. }
  30. }
  31. }

main.cpp

只需添加MacWindow::removeTitlebarFromWindow();

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include "macos.h"
  4. int main(int argc, char *argv[])
  5. {
  6. QGuiApplication app(argc, argv);
  7. QQmlApplicationEngine engine;
  8. const QUrl url(QStringLiteral("qrc:/qt-macos-without-title/main.qml"));
  9. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
  10. &app,
    (QObject *obj, const QUrl &objUrl) {
  11. if (!obj && url == objUrl)
  12. QCoreApplication::exit(-1);
  13. }, Qt::QueuedConnection);
  14. engine.load(url);
  15. MacOS::removeTitlebarFromWindow();
  16. return app.exec();
  17. }

最后在.pro文件中包含Cocoa库

yourapp.pro

  1. ...
  2. macx:LIBS += -framework Foundation -framework Cocoa
  3. macx:INCLUDEPATH += /System/Library/Frameworks/Foundation.framework/Versions/C/Headers \
  4. /System/Library/Frameworks/AppKit.framework/Headers \
  5. /System/Library/Frameworks/Cocoa.framework/Headers
英文:

My solution (based on Eduard's one, adjusted so window is draggable).

(Complete source code https://github.com/teimuraz/qt-macos-without-title)

Create macos.h and macos.mm files (If you create it with qt creator rename macos.cpp to macos.mm)

macos.h

  1. #ifndef MACOS_H
  2. #define MACOS_H
  3. #include &lt;QGuiApplication&gt;
  4. #include &lt;QWindow&gt;
  5. class MacOS {
  6. MacOS(long winid);
  7. public:
  8. static void removeTitlebarFromWindow(long winId = -1);
  9. };
  10. #endif // MACOS_H

macos.mm

  1. #include &quot;macos.h&quot;
  2. #include &lt;Cocoa/Cocoa.h&gt;
  3. #include &lt;QGuiApplication&gt;
  4. #include &lt;QWindow&gt;
  5. void MacOS::removeTitlebarFromWindow(long winId)
  6. {
  7. if(winId == -1) {
  8. QWindowList windows = QGuiApplication::allWindows();
  9. QWindow* win = windows.first();
  10. winId = win-&gt;winId();
  11. }
  12. NSView *nativeView = reinterpret_cast&lt;NSView *&gt;(winId);
  13. NSWindow* nativeWindow = [nativeView window];
  14. [nativeWindow setStyleMask:[nativeWindow styleMask] | NSFullSizeContentViewWindowMask | NSWindowTitleHidden];
  15. [nativeWindow setTitlebarAppearsTransparent:YES];
  16. [nativeWindow setMovableByWindowBackground:YES];
  17. }

main.qml

  1. import QtQuick
  2. import QtQuick.Controls
  3. ApplicationWindow {
  4. id: mainWindow
  5. visible: true
  6. width: 640
  7. height: 480
  8. // Make windows draggable, currently whole windows area is draggable, but can be adjusted to make draggable only top area
  9. property int previousX
  10. property int previousY
  11. MouseArea {
  12. anchors {
  13. top: parent.top
  14. bottom: parent.bottom
  15. left: parent.left
  16. right: parent.right
  17. }
  18. onPressed: {
  19. previousX = mouseX
  20. previousY = mouseY
  21. }
  22. onMouseXChanged: {
  23. var dx = mouseX - previousX
  24. mainWindow.setX(mainWindow.x + dx)
  25. }
  26. onMouseYChanged: {
  27. var dy = mouseY - previousY
  28. mainWindow.setY(mainWindow.y + dy)
  29. }
  30. }
  31. }

main.cpp

Just add MacWindow::removeTitlebarFromWindow();

  1. #include &lt;QGuiApplication&gt;
  2. #include &lt;QQmlApplicationEngine&gt;
  3. #include &quot;macos.h&quot;
  4. int main(int argc, char *argv[])
  5. {
  6. QGuiApplication app(argc, argv);
  7. QQmlApplicationEngine engine;
  8. const QUrl url(u&quot;qrc:/qt-macos-without-title/main.qml&quot;_qs);
  9. QObject::connect(&amp;engine, &amp;QQmlApplicationEngine::objectCreated,
  10. &amp;app,
    (QObject *obj, const QUrl &amp;objUrl) {
  11. if (!obj &amp;&amp; url == objUrl)
  12. QCoreApplication::exit(-1);
  13. }, Qt::QueuedConnection);
  14. engine.load(url);
  15. MacOS::removeTitlebarFromWindow();
  16. return app.exec();
  17. }

And finally include cocoa lib in .pro file

yourapp.pro

  1. ...
  2. macx:LIBS += -framework Foundation -framework Cocoa
  3. macx:INCLUDEPATH += /System/Library/Frameworks/Foundation.framework/Versions/C/Headers \
  4. /System/Library/Frameworks/AppKit.framework/Headers \
  5. /System/Library/Frameworks/Cocoa.framework/Headers

huangapple
  • 本文由 发表于 2015年3月5日 21:04:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/28878533.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定