PyQt5 Custom Title Bar Doesn't Show

I am trying to make my first program. I'm hoping for custom dark mode design, and that requires me to make a custom title bar. I copied the code for the title bar from someone else, it worked perfectly - custom movable window. I have carefully merged it with my previous code, though title bar doesn't appear. Now my guess is I have to call it at the end of my code, but it ends up with errors, as I'm not sure how to properly call it.

Note: removing the QtCore.Qt.FramelessWindowHint part is NOT the answer, as it just brings back the stock Win title bar, that's supposed to be hidden and replaced by dark title bar.

Part of code copied from: https://stackoverflow.com/a/44249552/12221725

Image:

IMAGE _ THE look im aiming at

import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QTextEdit

#fCol = "#e0e0e0"
#bCol = "#212121"

class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.layout = QHBoxLayout()
        self.textArea = QTextEdit("Lorem ipsum...")
        self.layout.addWidget(self.textArea)
        self.textArea.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;}")
        self.sans = QFont("Segoe UI",20)
        self.textArea.setFont(self.sans)
        self.btnLayout = QVBoxLayout()
        self.btnLayout.addWidget(QPushButton("Open"))
        self.btnLayout.addWidget(QPushButton("Setup"))
        self.btnLayout.addWidget(QPushButton("Find"))
        self.setStyleSheet("QPushButton {max-width:200px;color:#4fc3f7;background-color:#424242;border:2px solid #4fc3f7;border-radius:16px;font-size:35px;font-weight:bold;}" + "QPushButton:hover {color:#212121;background-color:#4fc3f7;}" + "QPushButton:pressed {color:white;background-color:#212121;border-color:white;}")
        self.status = QTextEdit()
        self.status.insertPlainText("Successfully loaded" + "\nOpen a file...")
        self.status.setReadOnly(1)
        self.status.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;font-size:14px;max-width:200px;}")
        self.btnLayout.addWidget(self.status)
        self.layout.addLayout(self.btnLayout)
        self.setLayout(self.layout)
        #self.setFixedSize(650, 320)
        self.setFixedSize(800, 400)
        self.setWindowTitle("Py Program")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)# | QtCore.Qt.WindowStaysOnTopHint)
        #self.layout.setContentsMargins(0,0,0,0)
        #self.layout.addStretch(-1)
        #self.pressing = False
        print("MainWindow Loaded")
        #self.show()



class MyBar(QWidget):

    def __init__(self, parent):
        super(MyBar, self).__init__()
        self.parent = parent
        print(self.parent.width())
        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(0,0,0,0)
        self.title = QLabel("My Own Bar")

        btn_size = 35

        self.btn_close = QPushButton("x")
        self.btn_close.clicked.connect(self.btn_close_clicked)
        self.btn_close.setFixedSize(btn_size,btn_size)
        self.btn_close.setStyleSheet("background-color: red;")

        self.btn_min = QPushButton("-")
        self.btn_min.clicked.connect(self.btn_min_clicked)
        self.btn_min.setFixedSize(btn_size, btn_size)
        self.btn_min.setStyleSheet("background-color: gray;")

        self.btn_max = QPushButton("+")
        self.btn_max.clicked.connect(self.btn_max_clicked)
        self.btn_max.setFixedSize(btn_size, btn_size)
        self.btn_max.setStyleSheet("background-color: gray;")

        self.title.setFixedHeight(35)
        self.title.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(self.title)
        self.layout.addWidget(self.btn_min)
        self.layout.addWidget(self.btn_max)
        self.layout.addWidget(self.btn_close)

        self.title.setStyleSheet("background-color: black;color: white;")
        self.setLayout(self.layout)

        self.start = QPoint(0, 0)
        self.pressing = False
        print("MyBar Loaded")


    def resizeEvent(self, QResizeEvent):
        super(MyBar, self).resizeEvent(QResizeEvent)
        self.title.setFixedWidth(self.parent.width())

    def mousePressEvent(self, event):
        self.start = self.mapToGlobal(event.pos())
        self.pressing = True

    def mouseMoveEvent(self, event):
        if self.pressing:
            self.end = self.mapToGlobal(event.pos())
            self.movement = self.end-self.start
            self.parent.setGeometry(self.mapToGlobal(self.movement).x(),
                                self.mapToGlobal(self.movement).y(),
                                self.parent.width(),
                                self.parent.height())
            self.start = self.end

    def mouseReleaseEvent(self, QMouseEvent):
        self.pressing = False


    def btn_close_clicked(self):
        self.parent.close()

    def btn_max_clicked(self):
        self.parent.showMaximized()

    def btn_min_clicked(self):
        self.parent.showMinimized()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setWindowIcon(QtGui.QIcon("icon.png"))
    app.setStyleSheet("QWidget {background-color:#424242;border-radius:12px;}")
    app.setFont(QFont("Consolas"))
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

Upvotes: 2

Views: 1402

Answers (1)

eyllanesc
eyllanesc

Reputation: 243965

The problem is that you have not created or placed a Bar() inside the window. You must also restructure your layout so that the titlebar is displayed at the top and your content at the bottom using a QVBoxLayout.

On the other hand I have improved the original titleBar so that it is not necessary to set the parent directly but instead use the window():

import sys
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QTextEdit, QLabel

class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowFlags(Qt.FramelessWindowHint)

        hlayout = QHBoxLayout()
        self.textArea = QTextEdit("Lorem ipsum...")
        hlayout.addWidget(self.textArea)
        self.textArea.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;}")
        self.sans = QFont("Segoe UI",20)
        self.textArea.setFont(self.sans)
        self.btnLayout = QVBoxLayout()
        self.btnLayout.addWidget(QPushButton("Open"))
        self.btnLayout.addWidget(QPushButton("Setup"))
        self.btnLayout.addWidget(QPushButton("Find"))
        self.setStyleSheet("QPushButton {max-width:200px;color:#4fc3f7;background-color:#424242;border:2px solid #4fc3f7;border-radius:16px;font-size:35px;font-weight:bold;}" + "QPushButton:hover {color:#212121;background-color:#4fc3f7;}" + "QPushButton:pressed {color:white;background-color:#212121;border-color:white;}")
        self.status = QTextEdit()
        self.status.insertPlainText("Successfully loaded" + "\nOpen a file...")
        self.status.setReadOnly(1)
        self.status.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;font-size:14px;max-width:200px;}")
        self.btnLayout.addWidget(self.status)
        self.setFixedSize(800, 400)
        self.setWindowTitle("Py app")
        hlayout.addLayout(self.btnLayout)
        
        custom_titlebar = TitleBar()

        lay = QVBoxLayout(self)
        lay.addWidget(custom_titlebar)
        lay.addLayout(hlayout)



class TitleBar(QWidget):
    def __init__(self, parent=None):
        super(TitleBar, self).__init__(parent)
 
        self.title = QLabel("My Own Bar")

        btn_size = 35

        self.btn_close = QPushButton("x")
        self.btn_close.clicked.connect(self.btn_close_clicked)
        self.btn_close.setFixedSize(btn_size,btn_size)
        self.btn_close.setStyleSheet("background-color: red;")

        self.btn_min = QPushButton("-")
        self.btn_min.clicked.connect(self.btn_min_clicked)
        self.btn_min.setFixedSize(btn_size, btn_size)
        self.btn_min.setStyleSheet("background-color: gray;")

        self.btn_max = QPushButton("+")
        self.btn_max.clicked.connect(self.btn_max_clicked)
        self.btn_max.setFixedSize(btn_size, btn_size)
        self.btn_max.setStyleSheet("background-color: gray;")

        self.title.setFixedHeight(35)
        self.title.setAlignment(Qt.AlignCenter)
        self.title.setStyleSheet("background-color: black;color: white;")

        lay = QHBoxLayout(self)
        lay.setContentsMargins(0,0,0,0)

        lay.addWidget(self.title)
        lay.addWidget(self.btn_min)
        lay.addWidget(self.btn_max)
        lay.addWidget(self.btn_close)

        self.pressing = False
        self.dragPosition = QPoint()

    def resizeEvent(self, QResizeEvent):
        super(TitleBar, self).resizeEvent(QResizeEvent)
        self.title.setFixedWidth(self.window().width())

    def mousePressEvent(self, event):
        self.start = event.globalPos()
        self.pressing = True

    def mouseMoveEvent(self, event):
        if self.pressing:
            self.end = event.globalPos()
            delta = self.end - self.start
            self.window().move(self.window().pos() + delta)
            self.start = self.end

    def mouseReleaseEvent(self, QMouseEvent):
        self.pressing = False


    def btn_close_clicked(self):
        self.window().close()

    def btn_max_clicked(self):
        self.window().showMaximized()

    def btn_min_clicked(self):
        self.window().showMinimized()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setWindowIcon(QIcon("icon.png"))
    app.setStyleSheet("QWidget {background-color:#424242;border-radius:12px;}")
    app.setFont(QFont("Consolas"))
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 1

Related Questions