Custom window with pyqT5 under Linux - python

I've made a program with pyQT5 on Windows which works great, but now I'm switching back to Linux and the program is buggy, when I move the window with the custom titlebar sometimes it jumps across the screen
I used this post to write the code:
Custom Titlebar with frame in PyQt5
Anyone can help me
Here is a simplified sample code:
import sys
from PyQt5.QtCore import QPoint
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QLabel
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QWidget
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.layout = QVBoxLayout()
self.layout.addWidget(MyBar(self))
self.setLayout(self.layout)
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.addStretch(-1)
self.setMinimumSize(800, 400)
self.setWindowFlags(Qt.FramelessWindowHint)
self.pressing = False
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
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)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
I have no idea where the problem is, and I didn't test it under macOS

Related

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:
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_())
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_())

Adding widget to QMainWindow from context menu

I can add QWidget to QMainWindow and set its position to cursor position.
But every single time, I want to add new QWidget to QMainWindow. I don't maybe given codes add new QWidget but at canvas, I see just one QWidget. Here my codes:
from PyQt5.QtWidgets import QMainWindow, QApplication, QMenu, QMenuBar, QAction, QFileDialog, QWidget, QLabel
from PyQt5.QtGui import QIcon, QImage, QPainter, QPen, QBrush
from PyQt5.QtCore import Qt, QPoint
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
title = "Paint Application"
top = 400
left = 400
width = 800
height = 600
self.objStr = "berkayy"
self.count = 0
# icon = "icons/pain.png"
self.setAcceptDrops(True)
self.setWindowTitle(title)
self.setGeometry(top, left, width, height)
# self.setWindowIcon(QIcon(icon))
self.image = QImage(self.size(), QImage.Format_RGB32)
self.image.fill(Qt.white)
self.drawing = False
self.brushSize = 2
self.brushColor = Qt.black
self.lastPoint = QPoint()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("File")
brushSize = mainMenu.addMenu("Brush Size")
brushColor = mainMenu.addMenu("Brush Color")
saveAction = QAction(QIcon("icons/save.png"), "Save",self)
saveAction.setShortcut("Ctrl+S")
fileMenu.addAction(saveAction)
saveAction.triggered.connect(self.save)
clearAction = QAction(QIcon("icons/clear.png"), "Clear", self)
clearAction.setShortcut("Ctrl+C")
fileMenu.addAction(clearAction)
clearAction.triggered.connect(self.clear)
threepxAction = QAction( QIcon("icons/threepx.png"), "3px", self)
brushSize.addAction(threepxAction)
threepxAction.triggered.connect(self.threePixel)
fivepxAction = QAction(QIcon("icons/fivepx.png"), "5px", self)
brushSize.addAction(fivepxAction)
fivepxAction.triggered.connect(self.fivePixel)
sevenpxAction = QAction(QIcon("icons/sevenpx.png"),"7px", self)
brushSize.addAction(sevenpxAction)
sevenpxAction.triggered.connect(self.sevenPixel)
ninepxAction = QAction(QIcon("icons/ninepx.png"), "9px", self)
brushSize.addAction(ninepxAction)
ninepxAction.triggered.connect(self.ninePixel)
blackAction = QAction(QIcon("icons/black.png"), "Black", self)
blackAction.setShortcut("Ctrl+B")
brushColor.addAction(blackAction)
blackAction.triggered.connect(self.blackColor)
whitekAction = QAction(QIcon("icons/white.png"), "White", self)
whitekAction.setShortcut("Ctrl+W")
brushColor.addAction(whitekAction)
whitekAction.triggered.connect(self.whiteColor)
redAction = QAction(QIcon("icons/red.png"), "Red", self)
redAction.setShortcut("Ctrl+R")
brushColor.addAction(redAction)
redAction.triggered.connect(self.redColor)
greenAction = QAction(QIcon("icons/green.png"), "Green", self)
greenAction.setShortcut("Ctrl+G")
brushColor.addAction(greenAction)
greenAction.triggered.connect(self.greenColor)
yellowAction = QAction(QIcon("icons/yellow.png"), "Yellow", self)
yellowAction.setShortcut("Ctrl+Y")
brushColor.addAction(yellowAction)
yellowAction.triggered.connect(self.yellowColor)
def rectangle(self, e, pos):
print(pos)
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
painter.setBrush(QBrush(Qt.green, Qt.DiagCrossPattern))
painter.drawRect(100, 15, 400, 200)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = True
self.lastPoint = event.pos()
#print(self.lastPoint)
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
newAct = contextMenu.addAction("New")
openAct = contextMenu.addAction("Open")
closeAct = contextMenu.addAction("Close")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == closeAct:
self.close()
elif action == openAct:
self.berkay(event.pos())
def mouseMoveEvent(self, event):
if(event.buttons() & Qt.LeftButton) & self.drawing:
painter = QPainter(self.image)
painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.lastPoint, event.pos())
self.lastPoint = event.pos()
self.update()
def berkay(self, pos):
wid = QWidget(self)
btn = QLabel(wid)
btn.setText("skjdf")
btn.setObjectName(self.objStr + str(self.count) )
btn.move(pos)
self.setCentralWidget(wid)
self.count += 1
# btn.setDragEnabled(True)
print(btn.objectName())
# self.show()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = False
def paintEvent(self, event):
canvasPainter = QPainter(self)
canvasPainter.drawImage(self.rect(),self.image, self.image.rect() )
def save(self):
filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")
if filePath == "":
return
self.image.save(filePath)
def clear(self):
self.image.fill(Qt.white)
self.update()
def threePixel(self):
self.brushSize = 3
def fivePixel(self):
self.brushSize = 5
def sevenPixel(self):
self.brushSize = 7
def ninePixel(self):
self.brushSize = 9
def blackColor(self):
self.brushColor = Qt.black
def whiteColor(self):
self.brushColor = Qt.white
def redColor(self):
self.brushColor = Qt.red
def greenColor(self):
self.brushColor = Qt.green
def yellowColor(self):
self.brushColor = Qt.yellow
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec()
I want to create new QWidget when user clicked context menu item every single time.
A QMainWindow can have only one central widget. So, adding the new QLabel as central widget will remove the previous. That's why you can see only the last label.
Create a single widget and define it as central widget. Then, add the label as child of the central widget:
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.area = QWidget(self)
self.setCentralWidget(self.area)
def berkay(self, pos):
btn = QLabel("BOOH", self.area)
btn.move(self.area.mapFromParent(pos)) # Map the pos in the coord system of self.area
btn.show()
First, for every single widget, store x and y value in a list. After that, adding new and current widgets to window central widget.
Edit
We do not need store widget x and y, anymore.
Thank you Romha for optimisation suggestion.
import sys
from PyQt5.QtWidgets import QMainWindow, QMenu, QApplication, QWidget, QPushButton, qApp
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import Qt
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.area = QWidget(self)
self.setCentralWidget(self.area)
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Context menu')
self.setStyleSheet("QMainWindow {background: 'white';}")
self.show()
def contextMenuEvent(self, event):
cmenu = QMenu(self)
addBtnAct = cmenu.addAction("Add Button")
quitAct = cmenu.addAction("Quit")
action = cmenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
qApp.quit()
elif action == addBtnAct:
self.addLabel(event.pos())
def addLabel(self, pos):
btn = QLabel("BOOH", self.area)
btn.move(self.area.mapFromParent(pos)) # Map the pos in the coord system of self.area
btn.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

Insert Image into QGridLayout and Draw on top of image in PyQt5

I'm pretty new to PyQt and am trying to make an application with a QPixmap on the left, which can be drawn on, and a QTextEdit on the right (for a simple OCR GUI).
I looked at:
PyQt5 Image and QGridlayout
but I couldn't connect it with the code below (I'm losing my hair with all the head scratching!!)
When I try adapting the following code, what I get is a QMainWindow with the QPixmap as the background which can be drawn on with the mouse and a second occurance of the QPixmap in it's correct position, which can not be drawn on. Can someone tell me what I'm doing wrong?
Thank you very much!
# https://stackoverflow.com/questions/51475306/
import sys
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QMainWindow, QApplication,QGridLayout, QLabel, QWidget, QTextEdit
from PyQt5.QtGui import QPixmap, QPainter, QPen
class Menu(QMainWindow):
def __init__(self):
super().__init__()
self.drawing = False
self.lastPoint = QPoint()
self.image = QPixmap("S3.png")
self.setGeometry(100, 100, 500, 300)
self.resize(self.image.width(), self.image.height())
layout = QGridLayout()
# Add a QTextEdit box
self.edit = QTextEdit()
layout.addWidget(self.edit, 0, 0, 10, 20)
# This:
# https://stackoverflow.com/questions/52616553
# indicates that a QPixmap must be put into a label to insert into a QGridLayout
self.label = QLabel()
self.label.setPixmap(self.image)
layout.addWidget(self.label, 10, 20, 10, 20)
# https://stackoverflow.com/questions/37304684/
self.widget = QWidget()
self.widget.setLayout(layout)
self.setCentralWidget(self.widget)
self.show()
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(self.rect(), self.image)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = True
self.lastPoint = event.pos()
print(self.lastPoint)
def mouseMoveEvent(self, event):
if event.buttons() and Qt.LeftButton and self.drawing:
painter = QPainter(self.image)
painter.setPen(QPen(Qt.red, 3, Qt.SolidLine))
painter.drawLine(self.lastPoint, event.pos())
print(self.lastPoint,event.pos())
self.lastPoint = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button == Qt.LeftButton:
self.drawing = False
if __name__ == '__main__':
app = QApplication(sys.argv)
mainMenu = Menu()
sys.exit(app.exec_())
Each widget must fulfill a specific task, so I have created a widget that only has the painted function, the main widget works as a container for the painting widget and the QTextEdit.
from PyQt5 import QtCore, QtGui, QtWidgets
class Label(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Label, self).__init__(parent)
self.image = QtGui.QPixmap("S3.png")
self.drawing = False
self.lastPoint = QtCore.QPoint()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(QtCore.QPoint(), self.image)
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.drawing = True
self.lastPoint = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() and QtCore.Qt.LeftButton and self.drawing:
painter = QtGui.QPainter(self.image)
painter.setPen(QtGui.QPen(QtCore.Qt.red, 3, QtCore.Qt.SolidLine))
painter.drawLine(self.lastPoint, event.pos())
self.lastPoint = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button == QtCore.Qt.LeftButton:
self.drawing = False
def sizeHint(self):
return self.image.size()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.label = Label()
self.textedit = QtWidgets.QTextEdit()
widget = QtWidgets.QWidget()
self.setCentralWidget(widget)
lay = QtWidgets.QHBoxLayout(widget)
lay.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)
lay.addWidget(self.textedit)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

pyqt add rectangle in Qgraphicsscene

I have a scene like this
class Scene(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super(Scene, self).__init__(parent)
def mousePressEvent(self, event):
print('scene pressed')
self.wid = MyRect(event.pos(), event.pos())
self.addItem(self.wid)
self.wid.show()
I would like class MyRect(QtWidgets.QGraphicsRectItem) with painter, mouse event and so on to be a draggable rectangle.
all stuff in MyRect
So then I could have many Rectangle to the scene and even after draw line between them and so on (kind of diagram app), but keeping objects related editable options in MyRect, MyLine , ....
I thought :
class MyRect(QtWidgets.QGraphicsRectItem):
def __init__(self, begin, end, parent=None):
super().__init__(parent)
self.begin = begin
self.end = end
def paintEvent(self, event):
print('painting')
qp = QtGui.QPainter(self)
qp.drawRect(QtCore.QRect(self.begin, self.end))
def mousePressEvent(self, event):
self.begin = event.pos()
self.end = event.pos()
self.update()
def mouseMoveEvent(self, event):
self.end = event.pos()
self.update()
def mouseReleaseEvent(self, event):
self.begin = event.pos()
self.end = event.pos()
self.update()
But I does not work (paint event not initiated whereas mousepressed event in scene is intiated)
I did not find what I wanted through the web so started totry do it by myself. I'm pretty sure it is a must known starting point but I cannot find it
First of all a QGraphicsItem is not a QWidget, so it has those events and does not handle them directly, that's what QGraphicsView and QGraphicsScene do. For example you say that you want to have a moveable rectangle because that task is simple is QGraphicsView, it is not necessary to overwrite:
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
view = QtWidgets.QGraphicsView(scene)
self.setCentralWidget(view)
rect_item = QtWidgets.QGraphicsRectItem(QtCore.QRectF(0, 0, 100, 100))
rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
scene.addItem(rect_item)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
If you want to change the way you paint the rectangle you must overwrite the paint() method as shown below:
from PyQt5 import QtCore, QtGui, QtWidgets
class RectItem(QtWidgets.QGraphicsRectItem):
def paint(self, painter, option, widget=None):
super(RectItem, self).paint(painter, option, widget)
painter.save()
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtCore.Qt.red)
painter.drawEllipse(option.rect)
painter.restore()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
view = QtWidgets.QGraphicsView(scene)
self.setCentralWidget(view)
rect_item = RectItem(QtCore.QRectF(0, 0, 100, 100))
rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
scene.addItem(rect_item)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
Update:
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsScene(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super(GraphicsScene, self).__init__(QtCore.QRectF(-500, -500, 1000, 1000), parent)
self._start = QtCore.QPointF()
self._current_rect_item = None
def mousePressEvent(self, event):
if self.itemAt(event.scenePos(), QtGui.QTransform()) is None:
self._current_rect_item = QtWidgets.QGraphicsRectItem()
self._current_rect_item.setBrush(QtCore.Qt.red)
self._current_rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
self.addItem(self._current_rect_item)
self._start = event.scenePos()
r = QtCore.QRectF(self._start, self._start)
self._current_rect_item.setRect(r)
super(GraphicsScene, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self._current_rect_item is not None:
r = QtCore.QRectF(self._start, event.scenePos()).normalized()
self._current_rect_item.setRect(r)
super(GraphicsScene, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self._current_rect_item = None
super(GraphicsScene, self).mouseReleaseEvent(event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scene =GraphicsScene(self)
view = QtWidgets.QGraphicsView(scene)
self.setCentralWidget(view)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

QFont.setFamily() not working with custom font

I was trying to make nice GUI for my program and I knew I needed a cool font as well. So I installed the 'Ubuntu' font with all weights.
But when I try this:
class MenuButton(QPushButton):
def __init__(self, caption):
super().__init__()
self.setFixedHeight(60)
self.setFixedWidth(100)
self.setFlat(True)
font = QFont()
font.setFamily('Ubuntu')
font.setWeight(QFont.Bold)
font.setPixelSize(20)
self.setFont(font)
self.setStyleSheet("color: rgb(85,170,255);")
self.setText(caption)
I get a font which pretty sure isn't what I picked:
But when I summon a QFontDialog at the start of my app however, I can see Ubuntu font and it IS named Ubuntu!
Why isn't it working and what am I supposed to do for it to work?
Appreciate the help...
Here is all:
import sys
import _thread
from PyQt5.QtCore import QSize, Qt, QRect, QObject
from PyQt5.QtWidgets import QApplication, QWidget, QProgressBar, QLabel, QTabWidget, QGridLayout, QVBoxLayout, \
QHBoxLayout, QSizePolicy, QSpacerItem, QStyle, QStyleFactory, QPushButton, QFrame, QFontDialog, QStackedWidget
from PyQt5.QtGui import QImage, QIcon, QPixmap, QPalette, QBrush, QColor, QFontDatabase, QFont
### Custom Classes
class MenuButton(QPushButton):
def __init__(self, caption):
super().__init__()
self.setFixedHeight(40)
self.setFixedWidth(100)
self.setFlat(True)
font = QFont()
font.setFamily('Ubuntu')
font.setWeight(QFont.Bold)
font.setPixelSize(19)
self.setFont(QFont('Ubuntu', 19, QFont.Medium))
self.setStyleSheet("color: rgb(85,170,255);")
self.setText(caption)
def select(self):
self.setStyleSheet("color: rgb(255,255,255);")
def deselect(self):
self.setStyleSheet("color: rgb(85,170,255);")
class StackPage(QWidget):
def __init__(self):
super().__init__()
self.setStyleSheet('background-color: rgb(28,33,39)')
self.layout = QVBoxLayout()
self.setLayout(self.layout)
class MainScreen(QWidget):
def __init__(self):
super().__init__()
#self.windowWidth = 500
#self.windowHeight = 300
self.icon = 'images\\system\\HashshashinLogo.png'
self.title = 'DevOrder'
self.fontFamily = 'Segoe UI' # Corbel | Sagoe UI
self.fontColor = 'black'
self.fontSize = '12'
self.initUI()
def initUI(self):
self.setStyleSheet('font-family: %s; color: %s; background-color: rgb(28,33,39);' % (self.fontFamily, self.fontColor))
self.setWindowTitle(self.title)
self.setWindowIcon(QIcon(self.icon))
#self.setFixedSize(self.windowWidth, self.windowHeight)
### Top Menu
def menubtnProjectsClicked():
menubtnProjects.select()
menubtnClients.deselect()
menubtnUpdates.deselect()
menubtnSettings.deselect()
self.leftStackMenu.setCurrentIndex(0)
def menubtnClientsClicked():
menubtnProjects.deselect()
menubtnClients.select()
menubtnUpdates.deselect()
menubtnSettings.deselect()
self.leftStackMenu.setCurrentIndex(1)
def menubtnUpdatesClicked():
menubtnProjects.deselect()
menubtnClients.deselect()
menubtnUpdates.select()
menubtnSettings.deselect()
self.leftStackMenu.setCurrentIndex(2)
def menubtnSettingsClicked():
menubtnProjects.deselect()
menubtnClients.deselect()
menubtnUpdates.deselect()
menubtnSettings.select()
self.leftStackMenu.setCurrentIndex(3)
menubtnProjects = MenuButton('Projects')
menubtnProjects.clicked.connect(menubtnProjectsClicked)
menubtnClients = MenuButton('Clients')
menubtnClients.clicked.connect(menubtnClientsClicked)
menubtnUpdates = MenuButton('Updates')
menubtnUpdates.clicked.connect(menubtnUpdatesClicked)
menubtnSettings = MenuButton('Settings')
menubtnSettings.clicked.connect(menubtnSettingsClicked)
### Left Menu
self.leftStackMenu = QStackedWidget()
self.leftStackMenu.setFixedWidth(500)
leftProjectsPage = StackPage()
leftProjectsPage.setStyleSheet('background-color: white;')
leftClientsPage = StackPage()
leftClientsPage.setStyleSheet('background-color: red;')
leftUpdatesPage = StackPage()
leftUpdatesPage.setStyleSheet('background-color: blue;')
leftSettingsPage = StackPage()
leftSettingsPage.setStyleSheet('background-color: yellow;')
self.leftStackMenu.addWidget(leftProjectsPage)
self.leftStackMenu.addWidget(leftClientsPage)
self.leftStackMenu.addWidget(leftUpdatesPage)
self.leftStackMenu.addWidget(leftSettingsPage)
### Placings
menuLayout = QHBoxLayout()
menuLayout.setContentsMargins(50, 10, 10, 10)
menuLayout.addWidget(menubtnProjects)
menuLayout.addWidget(menubtnClients)
menuLayout.addWidget(menubtnUpdates)
menuLayout.addWidget(menubtnSettings)
menuLayout.addSpacerItem(QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum))
stacksLayout = QHBoxLayout()
stacksLayout.addWidget(self.leftStackMenu)
menuWidget = QWidget()
menuWidget.setStyleSheet('background-color: rgb(22,26,31);')
menuWidget.setLayout(menuLayout)
mainLayout = QVBoxLayout()
mainLayout.addWidget(menuWidget)
mainLayout.addLayout(stacksLayout)
mainLayout.addSpacerItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
mainLayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(mainLayout)
#self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
#print('Currently used style:', app.style().metaObject().className())
#print('Available styles:', QStyleFactory.keys())
app.setStyle(QStyleFactory().create('windowsvista'))
QFontDialog().getFont()
loadingScreen = LoadingScren()
sys.exit(app.exec_())
To solve your problem, we need to change slightly your code.
First you add this line code self.setFont(QtGui.QFont("Ubuntu", 20, QtGui.QFont.Bold)) under class MenuButton().
Remember to show mainwindow, that you would do by adding this code
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory().create('windowsvista'))
win = MainScreen()
win.show()
sys.exit(app.exec_())
Window with correct font after launch
The code
import sys
import _thread
from PyQt5 import QtCore, QtGui, QtWidgets
### Custom Classes
class MenuButton(QtWidgets.QPushButton):
def __init__(self, caption):
super(MenuButton, self).__init__()
self.setFlat(True)
self.setFont(QtGui.QFont("Ubuntu", 20, QtGui.QFont.Bold))
self.setStyleSheet("color: rgb(85,170,255);")
self.setText(caption)
def select(self):
self.setStyleSheet("color: rgb(255,255,255);")
def deselect(self):
self.setStyleSheet("color: rgb(85,170,255);")
class StackPage(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setStyleSheet('background-color: rgb(28,33,39)')
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
class MainScreen(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainScreen, self).__init__(parent)
#self.windowWidth = 500
#self.windowHeight = 300
self.icon = 'images\\system\\HashshashinLogo.png'
self.title = 'DevOrder'
self.fontFamily = 'Segoe UI' # Corbel | Sagoe UI
self.fontColor = 'black'
self.fontSize = '12'
self.initUI()
def initUI(self):
self.setStyleSheet('font-family: %s; color: %s; background-color: rgb(28,33,39);' % (self.fontFamily, self.fontColor))
self.setWindowTitle(self.title)
self.setWindowIcon(QtGui.QIcon(self.icon))
#self.setFixedSize(self.windowWidth, self.windowHeight)
### Top Menu
def menubtnProjectsClicked():
menubtnProjects.select()
menubtnClients.deselect()
menubtnUpdates.deselect()
menubtnSettings.deselect()
self.leftStackMenu.setCurrentIndex(0)
def menubtnClientsClicked():
menubtnProjects.deselect()
menubtnClients.select()
menubtnUpdates.deselect()
menubtnSettings.deselect()
self.leftStackMenu.setCurrentIndex(1)
def menubtnUpdatesClicked():
menubtnProjects.deselect()
menubtnClients.deselect()
menubtnUpdates.select()
menubtnSettings.deselect()
self.leftStackMenu.setCurrentIndex(2)
def menubtnSettingsClicked():
menubtnProjects.deselect()
menubtnClients.deselect()
menubtnUpdates.deselect()
menubtnSettings.select()
self.leftStackMenu.setCurrentIndex(3)
menubtnProjects = MenuButton('Projects')
menubtnProjects.clicked.connect(menubtnProjectsClicked)
menubtnClients = MenuButton('Clients')
menubtnClients.clicked.connect(menubtnClientsClicked)
menubtnUpdates = MenuButton('Updates')
menubtnUpdates.clicked.connect(menubtnUpdatesClicked)
menubtnSettings = MenuButton('Settings')
menubtnSettings.clicked.connect(menubtnSettingsClicked)
### Left Menu
self.leftStackMenu = QtWidgets.QStackedWidget()
self.leftStackMenu.setFixedWidth(500)
leftProjectsPage = StackPage()
leftProjectsPage.setStyleSheet('background-color: white;')
leftClientsPage = StackPage()
leftClientsPage.setStyleSheet('background-color: red;')
leftUpdatesPage = StackPage()
leftUpdatesPage.setStyleSheet('background-color: blue;')
leftSettingsPage = StackPage()
leftSettingsPage.setStyleSheet('background-color: yellow;')
self.leftStackMenu.addWidget(leftProjectsPage)
self.leftStackMenu.addWidget(leftClientsPage)
self.leftStackMenu.addWidget(leftUpdatesPage)
self.leftStackMenu.addWidget(leftSettingsPage)
### Placings
menuLayout = QtWidgets.QHBoxLayout()
menuLayout.setContentsMargins(50, 10, 10, 10)
menuLayout.addWidget(menubtnProjects)
menuLayout.addWidget(menubtnClients)
menuLayout.addWidget(menubtnUpdates)
menuLayout.addWidget(menubtnSettings)
menuLayout.addSpacerItem(QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
stacksLayout = QtWidgets.QHBoxLayout()
stacksLayout.addWidget(self.leftStackMenu)
menuWidget = QtWidgets.QWidget()
menuWidget.setStyleSheet('background-color: rgb(22,26,31);')
menuWidget.setLayout(menuLayout)
mainLayout = QtWidgets.QVBoxLayout()
mainLayout.addWidget(menuWidget)
mainLayout.addLayout(stacksLayout)
mainLayout.addSpacerItem(QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding))
mainLayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(mainLayout)
#self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory().create('windowsvista'))
win = MainScreen()
win.show()
sys.exit(app.exec_())

Categories