17

I'm new to Qt C++. I downloaded the latest windows version, did some tutorials and its great.

I saw some styling options that the Qt framework has and its great, but now I need to build my application that its main windows (form) it designed/skinned with image without the rectangle borders (borderless?).

How can I do it with Qt?

Mat
  • 202,337
  • 40
  • 393
  • 406
user63898
  • 29,839
  • 85
  • 272
  • 514

4 Answers4

19

If your looking for some advanced styling in the shape of a widget, maybe this example will help you:

Shaped Clock Example

Or maybe you're simply looking for this kind of flag: Qt::CustomizeWindowHint or simply Qt::FramelessWindowHint.

omninonsense
  • 6,644
  • 9
  • 45
  • 66
Andy M
  • 5,945
  • 7
  • 51
  • 96
8

I created a small example, of how to create VS2013 like frameless window in Qt5: screenshot (mac) qt frameless window with dark style

You can get the complete sources here: https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle

Otherwise here a code overview of how to embed the "main" mainwindow into the "frameless" window. Also you can see how to add titlebar, buttons and do maximize, resize and move of the frameless window.

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtWidgets>

/*
place your QMainWindow code here
*/
namespace Ui {
  class MainWindow;
}

class MainWindow : public QMainWindow
{
  Q_OBJECT
public:
  explicit MainWindow(QWidget *parent = 0);
  ~MainWindow();
private:
  Ui::MainWindow *ui;
};

/*
this class is to add frameless window supoort and do all the stuff with titlebar and buttons
*/
class BorderlessMainWindow: public QMainWindow
{
  Q_OBJECT
public:
  explicit BorderlessMainWindow(QWidget *parent = 0);
  ~BorderlessMainWindow() {}
protected:
  void mouseMoveEvent(QMouseEvent* event);
  void mousePressEvent(QMouseEvent* event);
  void mouseReleaseEvent(QMouseEvent* event);
  void mouseDoubleClickEvent(QMouseEvent *event);
private slots:
  void slot_minimized();
  void slot_restored();
  void slot_maximized();
  void slot_closed();
private:
  MainWindow *mMainWindow;
  QWidget *mTitlebarWidget;
  QLabel *mWindowTitle;
  QPushButton *mMinimizeButton;
  QPushButton *mRestoreButton;
  QPushButton *mMaximizeButton;
  QPushButton *mCloseButton;
  QPoint mLastMousePosition;
  bool mMoving;
  bool mMaximized;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

/*
frameless window class: it adds the MainWindow class inside the centralWidget
*/
BorderlessMainWindow::BorderlessMainWindow(QWidget *parent) : QMainWindow(parent, Qt::CustomizeWindowHint ) {
  setObjectName("borderlessMainWindow");
  setWindowFlags(Qt::FramelessWindowHint| Qt::WindowSystemMenuHint);
  // to fix taskbar minimize feature
  setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint);

  mMainWindow = new MainWindow(this);
  setWindowTitle(mMainWindow->windowTitle());

  QVBoxLayout *verticalLayout = new QVBoxLayout();
  verticalLayout->setSpacing(0);
  verticalLayout->setMargin(1);

  QHBoxLayout *horizontalLayout = new QHBoxLayout();
  horizontalLayout->setSpacing(0);
  horizontalLayout->setMargin(0);

  mTitlebarWidget = new QWidget(this);
  mTitlebarWidget->setObjectName("titlebarWidget");
  mTitlebarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  mTitlebarWidget->setLayout(horizontalLayout);

  mMinimizeButton = new QPushButton(mTitlebarWidget);
  mMinimizeButton->setObjectName("minimizeButton");
  connect(mMinimizeButton, SIGNAL(clicked()), this, SLOT(slot_minimized()));

  mRestoreButton = new QPushButton(mTitlebarWidget);
  mRestoreButton->setObjectName("restoreButton");
  mRestoreButton->setVisible(false);
  connect(mRestoreButton, SIGNAL(clicked()), this, SLOT(slot_restored()));

  mMaximizeButton = new QPushButton(mTitlebarWidget);
  mMaximizeButton->setObjectName("maximizeButton");
  connect(mMaximizeButton, SIGNAL(clicked()), this, SLOT(slot_maximized()));

  mCloseButton = new QPushButton(mTitlebarWidget);
  mCloseButton->setObjectName("closeButton");
  connect(mCloseButton, SIGNAL(clicked()), this, SLOT(slot_closed()));

  mWindowTitle = new QLabel(mTitlebarWidget);
  mWindowTitle->setObjectName("windowTitle");
  mWindowTitle->setText(windowTitle());

  horizontalLayout->addWidget(mWindowTitle);
  horizontalLayout->addStretch(1);
  horizontalLayout->addWidget(mMinimizeButton);
  horizontalLayout->addWidget(mRestoreButton);
  horizontalLayout->addWidget(mMaximizeButton);
  horizontalLayout->addWidget(mCloseButton);

  verticalLayout->addWidget(mTitlebarWidget);
  verticalLayout->addWidget(mMainWindow);

  QWidget *centralWidget = new QWidget(this);
  centralWidget->setObjectName("centralWidget");
  centralWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  centralWidget->setLayout(verticalLayout);

  setCentralWidget(centralWidget);
}
void BorderlessMainWindow::mousePressEvent(QMouseEvent* event) {
  if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
    return;

  if(event->button() == Qt::LeftButton) {
    mMoving = true;
    mLastMousePosition = event->pos();
  }
}
void BorderlessMainWindow::mouseMoveEvent(QMouseEvent* event) {
  if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
    return;

  if( event->buttons().testFlag(Qt::LeftButton) && mMoving) {
    this->move(this->pos() + (event->pos() - mLastMousePosition));
  }
}
void BorderlessMainWindow::mouseReleaseEvent(QMouseEvent* event) {
  if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
    return;

  if(event->button() == Qt::LeftButton) {
    mMoving = false;
  }
}
void BorderlessMainWindow::mouseDoubleClickEvent(QMouseEvent *event) {
  Q_UNUSED(event);
  if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
    return;

  mMaximized = !mMaximized;
  if (mMaximized) {
    slot_maximized();
  } else {
    slot_restored();
  }
}
void BorderlessMainWindow::slot_minimized() {
  setWindowState(Qt::WindowMinimized);
}
void BorderlessMainWindow::slot_restored() {
  mRestoreButton->setVisible(false);
  mMaximizeButton->setVisible(true);
  setWindowState(Qt::WindowNoState);
  setStyleSheet("#borderlessMainWindow{border:1px solid palette(highlight);}");
}
void BorderlessMainWindow::slot_maximized() {
  mRestoreButton->setVisible(true);
  mMaximizeButton->setVisible(false);
  setWindowState(Qt::WindowMaximized);
  setStyleSheet("#borderlessMainWindow{border:1px solid palette(base);}");
}
void BorderlessMainWindow::slot_closed() {
  close();
}

/*
MainWindow class: put all your code here
*/
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent, Qt::FramelessWindowHint), ui(new Ui::MainWindow) {
  ui->setupUi(this);
  statusBar()->setSizeGripEnabled(true);
}

MainWindow::~MainWindow() {
  delete ui;
}
mtn
  • 3
  • 1
  • 1
  • 4
Jorgen
  • 440
  • 6
  • 10
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. Please read this [how-to-answer](http://stackoverflow.com/help/how-to-answer) for providing quality answer. – thewaywewere Jun 25 '17 at 16:58
5

There is a sample application in your Qt directory: examples/widgets/windowsflags.

omninonsense
  • 6,644
  • 9
  • 45
  • 66
3

I ran into this myself and figured it out after some time. Check out https://github.com/ianbannerman/TrueFramelessWindow for sample code for both Windows & macOS.

Qt::FramelessWindowHint sacrifices resizing and min/max/close, so is probably not what mot people are looking for.

Ian
  • 73
  • 6
  • Note for readers: You can still handle the min/max/close/resizing/dragging operations yourself. It takes extra code, but it's possible. I have a nice frameless app with my own custom title bar that acts exactly like a real window. – Kobato Aug 09 '19 at 21:21
  • @JohnDoe Does your code work on linux too by any chance ? Sry for asking on here, but i start to get desperate ;) – SleepProgger Jul 28 '20 at 17:23