I have tried to simulated below error but it is not consistent. may I know what does it really mean and how we can debug such issue.
The error generally occur from event function only
Error: elif self.review_waiver_box and obj is self.review_waiver_box.viewport():
RuntimeError: Internal C++ object (PySide2.QtWidgets.QTextEdit) already deleted.
import os
import sys
from PySide2.QtCore import QEvent, QSize, QRegularExpression
from PySide2.QtWidgets import (QPlainTextEdit, QApplication, QLabel,
QGridLayout, QGroupBox, QMessageBox,
QTextEdit, QCheckBox, QTableView,
QTableWidgetItem, QHeaderView, QWidget, QVBoxLayout,
QSizePolicy, QButtonGroup, QAbstractItemView,
QSplitter, QHBoxLayout, QComboBox)
from PySide2.QtWidgets import (QDesktopWidget, QMainWindow, QSizePolicy, QMessageBox, QToolBar, QAction, QLabel,
QMenu, QWidget, QVBoxLayout, QColorDialog, QDialog, QPushButton)
from functools import partial
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.width = 1100
self.height = 700
self.set_main_window()
self.create_violation_text()
def set_main_window(self):
"""
Setting main window position
"""
self.setWindowTitle("GUI %s" % (os.path.abspath(__file__)))
self.setFixedSize(QSize(self.width, self.height))
wid = QDesktopWidget()
screen_width = wid.screen().frameGeometry().width()
screen_height = wid.screen().frameGeometry().height()
self.setGeometry(screen_width / 2 - self.width / 2,
screen_height / 2 - self.height / 2,
self.width, self.height)
def create_violation_text(self):
"""
creating main violation window which contain all violations
"""
self.plain_textedit = QPlainTextEdit()
self.plain_textedit.setLineWrapMode(QPlainTextEdit.NoWrap)
self.plain_textedit.setStyleSheet(
"""QPlainTextEdit {font-size: 14pt;
font-family: Courier;}""")
self.plain_textedit.setReadOnly(True)
self.plain_textedit.setMouseTracking(True)
self.plain_textedit_format = self.plain_textedit.currentCharFormat()
self.plain_textedit.setCursorWidth(5)
self.plain_textedit.viewport().installEventFilter(self)
self.plain_textedit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
class ReviewWindow(MainWindow):
def __init__(self, app):
"""creating Review mode"""
super().__init__()
self.app = app
def create_widget(self):
self.waiver_approval_window = QGroupBox()
self.waiver_approval_layout = QGridLayout()
self.create_violation_window()
self.create_waiver_approval_list()
self.waiver_approval_window.setLayout(self.waiver_approval_layout)
# order matter
main_layout = QVBoxLayout()
main_layout.addWidget(self.create_violation_box)
main_layout.addWidget(self.waiver_approval_window)
# creating widgeth object as main window does not
# add layout directly it add only widget
window = QWidget()
window.setLayout(main_layout)
self.setCentralWidget(window)
def create_violation_window(self):
"""
creating violation window which contain text editor,
violation type and checkbox
"""
self.create_violation_box = QGroupBox()
self.large_file_batch_selection = QComboBox()
self.large_file_batch_selection.setGeometry(10, 15, 10, 15)
self.large_file_batch_selection.currentIndexChanged.connect(partial(self.load_range))
self.large_file_batch_selection.addItems(["0-1", "1-2"])
layout = QGridLayout()
layout.addWidget(self.large_file_batch_selection, 1, 0)
layout.addWidget(self.plain_textedit, 2, 0, 12, 1)
layout.setColumnMinimumWidth(0, 10)
self.create_violation_box.setLayout(layout)
def create_waiver_approval_list(self):
"""
Adding plain text to editor to window
"""
# waiver review pane
print("coming here")
self.waiver_file_path = QLabel()
self.waiver_file_path.setText("path")
# layout.addWidget(self.waiver_file_path, 0, 0)
self.waiver_approval_layout.addWidget(self.waiver_file_path, 0, 0)
font_family = """QTextEdit {font-size: 14pt;
background-color: #ffffe6;
color: #404040;
font-family: Courier;}"""
self.review_waiver_box = QTextEdit("Waiver_window")
self.review_waiver_box.setReadOnly(True)
self.review_waiver_box.setMouseTracking(True)
self.review_waiver_box.viewport().installEventFilter(self)
# layout.addWidget(self.review_waiver_box, 1, 0)
self.waiver_approval_layout.addWidget(self.review_waiver_box, 1, 0)
self.review_waiver_box.setPlainText("data")
# approval pane
self.approval_waiver_box = QTextEdit()
self.approval_file_path = QLabel()
self.approval_file_path.setText("path")
# layout.addWidget(self.approval_file_path, 0, 1)
self.waiver_approval_layout.addWidget(self.approval_file_path, 0, 1)
self.approval_waiver_box.setPlainText("data")
font_family = """QTextEdit {font-size: 14pt;
background-color: #ffd9b3;
color: #404040;
font-family: Courier;}"""
self.approval_waiver_box.setStyleSheet(font_family)
self.approval_waiver_box.setHidden(True)
self.approval_file_path.setHidden(True)
self.approval_waiver_box.setMouseTracking(True)
self.approval_waiver_box.setReadOnly(True)
self.approval_waiver_box.viewport().installEventFilter(self)
# layout.addWidget(self.approval_waiver_box, 1, 1)
# self.waiver_approval_window.setLayout(layout)
self.waiver_approval_layout.addWidget(self.approval_waiver_box, 1, 1)
def load_range(self, index):
print ("index")
def eventFilter(self, obj, event):
print ("event")
if obj is self.plain_textedit.viewport() and event.type() == QEvent.MouseButtonPress:
print ("text edit event")
elif self.review_waiver_box and obj is self.review_waiver_box.viewport():
if event.type() == QEvent.MouseButtonPress:
print ("button press")
return super().eventFilter(obj, event)
def closeEvent(self, event):
print ("pass")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ReviewWindow(app)
window.create_widget()
window.show()
app.exec_()
Related
I am seeing gap into QVBoxLayout when I am placing layout it does not look good, any idea to fix issue
#!/usr/bin/env python
import os
import sys
from PySide2.QtCore import Qt, QSize, QRegExp, QFile, QTextStream
from PySide2.QtGui import QKeySequence, QTextCharFormat, QBrush,QColor, QTextDocument, QTextCursor
from PySide2.QtWidgets import (QApplication, QDesktopWidget, QMainWindow,
QPlainTextEdit, QGridLayout, QGroupBox,
QFormLayout, QHBoxLayout, QLabel, QLineEdit,
QMenu, QMenuBar, QPushButton, QMessageBox,
QTextEdit, QVBoxLayout, QWidget, QAction)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.width = 1100
self.height = 700
self.set_main_window()
self.create_violation_text()
def set_main_window(self):
"""
Setting main window position
"""
self.setWindowTitle("GUI %s" %(os.path.abspath(__file__)))
self.setFixedSize(QSize(self.width, self.height))
wid = QDesktopWidget()
screen_width = wid.screen().frameGeometry().width()
screen_height = wid.screen().frameGeometry().height()
self.setGeometry(screen_width/2-self.width/2,
screen_height/2-self.height/2,
self.width, self.height)
def create_violation_text(self):
"""
creating main violation window which contain all violations
"""
self.plain_textedit = QPlainTextEdit()
self.plain_textedit.setLineWrapMode(QPlainTextEdit.NoWrap)
self.plain_textedit.setStyleSheet(
"""QPlainTextEdit {font-size: 14pt;
font-family: Courier;}""")
class ReviewWindow(MainWindow):
def __init__(self, waiver_files, app):
"""creating Review mode"""
super().__init__()
self.waiver_files = waiver_files
self.app = app
def create_widget(self):
self.create_text_finder()
self.create_violation_window()
#order matter
main_layout = QVBoxLayout()
main_layout.addWidget(self.text_finder)
main_layout.addWidget(self.create_violation_box)
#creating widgeth object as main window does not
#add layout directly it add only widget
window = QWidget()
window.setLayout(main_layout)
self.setCentralWidget(window)
def create_text_finder(self):
"""
create text finder which wil search string into document
"""
self.text_finder = QGroupBox()
layout = QHBoxLayout()
label = QLabel()
label.setText("Keyword:")
self.line_edit = QLineEdit()
self.line_edit.setText("Enter your search here")
push_button = QPushButton("Find")
push_button.clicked.connect(self.find_string_match)
layout.addWidget(label)
layout.addWidget(self.line_edit)
layout.addWidget(push_button)
self.text_finder.setLayout(layout)
def create_violation_window(self):
"""
creating violation window which contain text editor,
violation type and checkbox
"""
self.create_violation_box = QGroupBox()
layout = QGridLayout()
layout.addWidget(self.plain_textedit, 1, 0, 12, 1)
layout.setColumnMinimumWidth(0, 10)
self.create_violation_box.setLayout(layout)
def find_string_match(self):
"""
Adding string match operation
"""
#format for desire match
format = QTextCharFormat()
format.setBackground(QBrush(QColor("red")))
pattern = QRegExp(self.line_edit.text())
text_document = self.plain_textedit.document()
#Reverting if any
text_document.undo()
if pattern.isEmpty():
QMessageBox.warning("Search filed is empty")
else:
find_cursor = QTextCursor(text_document)
cursor = QTextCursor(text_document)
cursor.beginEditBlock()
while (not find_cursor.isNull() and not find_cursor.atEnd()):
found = False
find_cursor = text_document.find(pattern, find_cursor,
QTextDocument.FindWholeWords)
if (not find_cursor.isNull()):
found = True
find_cursor.movePosition(QTextCursor.WordRight,
QTextCursor.KeepAnchor)
find_cursor.mergeCharFormat(format)
cursor.endEditBlock()
if __name__ == '__main__':
app = QApplication(sys.argv)
cwd = os.path.dirname(__file__)
waiver_file = \[os.path.join(cwd, fdata) for fdata in os.listdir(cwd)\]
window = ReviewWindow(waiver_file, app)
window.create_widget()
window.show()
app.exec_()
Im trying to develop a program which have many of my custom widget. in my widget i have a crosshair mouse pointer and when i move it in one of my widgets, all of them must sense it and the crosshair must react on every single widget.
I have a self.update() on the end of the paintEnent function.
How can i force the other widgets on my app to react it?
paintEvent is not a simple code like this and as i add every functions on this part, it make a very high CPU usage. How can i manage it?
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QListWidget,
QComboBox, QVBoxLayout, QPushButton, QLabel, QMainWindow, QWidget,
QHBoxLayout, QVBoxLayout, QSizePolicy
from PyQt5.QtCore import Qt, QSize, QRect
from PyQt5.QtGui import QPalette, QColor, QPen, QPixmap, QPainter,
QBrush
class Boom(QWidget):
xPos=-1.0
def __init__(self,bgColor,xSpace=1,ySpace=1):
super().__init__()
self.bgColor=bgColor
self.x = -1
self.y = -1
self.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding)
self.setMouseTracking(True)
layout = QVBoxLayout()
self.setLayout(layout)
def mouseMoveEvent(self, event):
global xPos
self.x = event.x()
self.y = event.y()
xPos=self.x/self.width()
self.update()
def paintEvent(self, e):
painter = QPainter(self)
font = painter.font()
font.setFamily('Times')
font.setPointSize(8)
painter.setFont(font)
brush = QBrush()
brush.setColor(QColor(self.bgColor))
brush.setStyle(Qt.SolidPattern)
pen = QPen()
pen.setWidth(1)
pen.setColor(QColor('black'))
painter.setPen(pen)
rect = QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(rect, brush)
pen.setColor(QColor('blue'))
painter.setPen(pen)
painter.drawLine(self.x, 0, self.x,painter.device().height()) #V
painter.drawLine(0, self.y, painter.device().width(),self.y) #H
self.update()
painter.end()
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Graph")
MainPanelLayout = QHBoxLayout()
MainPanelLayout.setContentsMargins(1,1,1,1)
MainPanelLayout.setSpacing(1)
B1=Boom('pink',0)
B2=Boom('gray',1)
MainPanelLayout.addWidget(B1)
MainPanelLayout.addWidget(B2)
widget = QWidget()
widget.setLayout(MainPanelLayout)
self.setCentralWidget(widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
# mainWindow.showMaximized()
app.exec_()
Iv found a way!
I used signal and slots to communicate between instances
May it works for others too :)
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QListWidget,QComboBox, QVBoxLayout, QPushButton, QLabel, QMainWindow,QWidget, QHBoxLayout, QVBoxLayout, QSizePolicy
from PyQt5.QtCore import Qt, QSize, QRect, QObject, pyqtSignal
from PyQt5.QtGui import QPalette, QColor, QPen, QPixmap, QPainter,QBrush
import FxMainForm
class BoomCommunicate(QObject):
signal = pyqtSignal()
class Boom(QWidget):
xPos=-1
def __init__(self,bgColor,nChannel=-1,xSpace=1,ySpace=1):
super().__init__()
self.bgColor=bgColor
self.xSpace=xSpace
self.ySpace=ySpace
self.x = -1
self.y = -1
self.nChannel=nChannel
self.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding)
self.setMouseTracking(True)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.communicate = BoomCommunicate()
self.communicate.signal.connect(self.trigger_refresh)
def mouseMoveEvent(self, event):
self.x = event.x()
self.y = event.y()
if self.nChannel==0:
Boom.xPos=self.x/self.width()
self.communicate.signal.emit()
def paintEvent(self, e):
painter = QPainter(self)
font = painter.font()
font.setFamily('Times')
font.setPointSize(8)
painter.setFont(font)
brush = QBrush()
brush.setColor(QColor(self.bgColor))
brush.setStyle(Qt.SolidPattern)
pen = QPen()
pen.setWidth(1)
pen.setColor(QColor('black'))
painter.setPen(pen)
## Border
rect = QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(rect, brush)
pen.setColor(QColor('blue'))
painter.setPen(pen)
# self.Drawings(painter,pen,brush)
if self.nChannel==0:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
painter.drawLine(self.x, self.ySpace, self.x,painter.device().height()-self.ySpace-1) ##V
painter.drawLine(self.xSpace, self.y, painter.device().width()-self.ySpace-1,self.y) ##H
if not FxMainForm.studyItem==None:
painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
painter.drawText(5, 15,FxMainForm.studyItem[0]+' ('+FxMainForm.studyItem[1]+') ')
Boom.xPos=self.x/self.width()
else:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
painter.drawLine(int(Boom.xPos*painter.device().width()), self.ySpace,int(Boom.xPos*painter.device().width()),painter.device().height()-self.ySpace-1)
painter.end()
def trigger_refresh(self):
self.update()
def sizeHint(self):
return QSize(100, 100)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Graph-Boom")
self.MainPanelLayout = QHBoxLayout()
self.MainPanelLayout.setContentsMargins(1,1,1,1)
self.MainPanelLayout.setSpacing(1)
self.B1=Boom('pink',0)
self.B2=Boom('gray',1)
self.MainPanelLayout.addWidget(self.B1)
self.MainPanelLayout.addWidget(self.B2)
self.B1.communicate.signal.connect(self.B2.update)
self.widget = QWidget()
self.widget.setLayout(self.MainPanelLayout)
self.setCentralWidget(self.widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
# mainWindow.showMaximized()
app.exec_()
I want to change the thickness of the text.
In css there is a property for this
-webkit-text-stroke-width
Is there an analog in PyQt5
Changing the font to a thinner one is not an option since I use a unique font that does not have bold italic versions and so on.
import sys
from PyQt5.QtWidgets import (QRadioButton, QHBoxLayout, QButtonGroup,
QApplication, QGraphicsScene,QGraphicsView, QGraphicsLinearLayout, QGraphicsWidget, QWidget, QLabel)
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import QSize, QPoint,Qt
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPainter
class Window(QWidget):
def __init__(self):
super().__init__()
self.resize(800, 800)
label = QLabel(self)
label.setText('<div></div>')
font_id = QFontDatabase.addApplicationFont(url)
if font_id == -1:
print('not fond')
font = QFont("my-font",18)
label.setStyleSheet('''font-size: 80pt; font-family: my-font;''')
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
You can try the font-weight property, values 100-900 have varying thickness. There's an equivalent method with QFont.setWeight().
class Template(QWidget):
def __init__(self):
super().__init__()
grid = QGridLayout(self)
grid.addWidget(QLabel('Hello World'), 0, 0, Qt.AlignHCenter)
for i in range(1, 10):
lbl = QLabel(f'({i * 100}) Hello World')
lbl.setStyleSheet(f'font-weight: {i * 100}')
grid.addWidget(lbl, i, 0)
self.setStyleSheet('''
QLabel {
font-size: 24pt;
font-family: Helvetica Neue;
}''')
It looks like this:
Although this will not work for all fonts. You could alternatively subclass QLabel and reimplement paintEvent to draw an outline of the text in the window color.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class ThinLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def paintEvent(self, event):
qp = QPainter(self)
qp.setRenderHint(QPainter.Antialiasing)
path = QPainterPath()
path.addText(event.rect().bottomLeft(), self.font(), self.text())
qp.setPen(QPen(self.palette().color(QPalette.Window), 2))
qp.setBrush(self.palette().text())
qp.drawPath(path)
class Template(QWidget):
def __init__(self):
super().__init__()
grid = QGridLayout(self)
grid.addWidget(QLabel('Hello World'), 0, 0)
grid.addWidget(ThinLabel('Hello World'), 1, 0)
self.setStyleSheet('''
QLabel {
font-size: 80pt;
font-family: Helvetica Neue;
}''')
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = Template()
gui.show()
sys.exit(app.exec_())
I want my window and it's QGraphicsScene to be transparent which is controlled by QSlider.
I tried looking for some answers here and there, but it's mainly setting background color to 0 :
self.setStyleSheet("background-color:rgba(0, 0, 0, 0);")
or like that :
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
Which does it job, but I would like to make slider which will control level of transparency and I don't see how can I do it with commands above.
Can somebody please give me some advise how to do it ? Thank you
I will attach my test code here below(I want to be able to control transparency of everything , but do not touch slider and button):
from PySide2.QtGui import QBrush, QColor
from PySide2.QtCore import QSize, Qt
from PySide2.QtWidgets import QDialog, QVBoxLayout, QGraphicsView, QGraphicsScene, QFrame, QSizePolicy, QApplication, QSlider, QPushButton
class MainWindow(QDialog):
def __init__(self):
QDialog.__init__(self)
self.mainLayout = QVBoxLayout()
self.graphicsWidget = MainGraphicsWidget()
self.window = 'transp_test'
self.title = 'transparent UI'
self.size = (1000, 650)
self.create()
def create(self, **kwargs):
self.setWindowTitle(self.title)
self.resize(QSize(*self.size))
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.graphicsWidget)
class MainGraphicsWidget(QGraphicsView):
def __init__(self, parent=None):
super(MainGraphicsWidget, self).__init__(parent)
self._scene = QGraphicsScene(backgroundBrush = Qt.gray)
self.setScene(self._scene)
self.transpSlider = QSlider()
self.transpSlider.setRange(0,100)
self.mainButton = QPushButton('I want it to be "Test" button')
self._scene.addWidget(self.mainButton)
self._scene.addWidget(self.transpSlider)
self.transpSlider.move(300, 100)
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QBrush(QColor(30, 30, 30)))
self.setFrameShape(QFrame.NoFrame)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.setGeometry(600, 300, 600, 600)
window.show()
sys.exit(app.exec_())
Here is one way.
class MainWindow(QDialog):
def __init__(self):
QDialog.__init__(self)
# these two lines are needed to get a transparent background in windows
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
# rest of class definition unchanged
class MainGraphicsWidget(QGraphicsView):
def __init__(self, parent=None):
super(MainGraphicsWidget, self).__init__(parent)
# set transparent background color for the widget itself
self.setStyleSheet("background-color: #00000000")
self._scene = QGraphicsScene()
self.setScene(self._scene)
# create of slider and connect to slot for changing opacity.
self.transpSlider = QSlider()
self.transpSlider.setStyleSheet('background-color: #00000000')
self.transpSlider.setRange(0,255)
self.transpSlider.valueChanged.connect(self.set_opacity)
self.transpSlider.setValue(255)
# rest of __init__ unchanged
def set_opacity(self, value):
brush = self.backgroundBrush()
color = brush.color()
color.setAlpha(value)
brush.setColor(color)
self.setBackgroundBrush(color)
Note that I've changed the range of the slider to 0-255 to make changing the opacity from fully opaque to fully transparent easier.
Try it:
#from PySide2.QtGui import QBrush, QColor
#from PySide2.QtCore import QSize, Qt
#from PySide2.QtWidgets import QDialog, QVBoxLayout, QGraphicsView, QGraphicsScene, QFrame, QSizePolicy, QApplication, QSlider, QPushButton
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QGraphicsView, QGraphicsScene,
QFrame, QSizePolicy, QApplication, QSlider, QPushButton)
class MainGraphicsWidget(QGraphicsView):
def __init__(self, parent=None):
super(MainGraphicsWidget, self).__init__(parent)
self._scene = QGraphicsScene()
self.setScene(self._scene)
self.transpSlider = QtWidgets.QSlider(
QtCore.Qt.Horizontal,
minimum=10,
maximum=100,
value=100,
valueChanged=self.onValueChanged,
)
self.mainButton = QPushButton('I want it to be "Test" button \n QUIT')
self.mainButton.resize(150, 150)
self.mainButton.clicked.connect(parent.close)
self._scene.addWidget(self.mainButton)
self._scene.addWidget(self.transpSlider)
self.transpSlider.move(300, 100)
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
c = QColor(220, 30, 30)
c.setAlphaF(1)
self.setBackgroundBrush(QBrush(c))
self.setFrameShape(QFrame.NoFrame)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
#QtCore.pyqtSlot(int)
def onValueChanged(self, value):
c = QColor(220, 30, 30)
c.setAlphaF(value * 0.01)
self.setBackgroundBrush(QBrush(c))
window.setWindowOpacity(value * 0.03)
self.setStyleSheet("MainGraphicsWidget {{background-color: rgba(0, 215, 55, {});}}".format(value))
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setAttribute(Qt.WA_NoSystemBackground, False)
self.setStyleSheet("MainWindow {background-color: rgba(0, 215, 55, 70);}")
self.graphicsWidget = MainGraphicsWidget(self)
self.window = 'transp_test'
self.title = 'transparent UI'
self.size = (1000, 650)
self.setWindowTitle(self.title)
self.resize(QSize(*self.size))
self.mainLayout = QVBoxLayout()
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.graphicsWidget)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.setGeometry(600, 100, 600, 600)
window.show()
sys.exit(app.exec_())
This is what my example looks like:
The text area is a QPlainTextEdit() object because I want the text to wrap to the second line. I think this is the best widget choice.
The user will only enter a maximum number of 90 characters in this box so I don't need a large text area.
I want to disable the key press Enter (carriage return). I got it to work but it seems hacky and I don't think it would work cross-platform (ex: Mac).
Surely, there's got to be a better way to prevent a carriage return key event in a QPlainTextEdit object?
My Current Solution Explained
Below, you can see I'm checking if an IndexError occurs because the last_value throws an IndexError when there's nothing in the QPlainTextEdit box. Then, I'm getting the last character and asking if it's equal to a new line. If it is, I'm re-setting the text without that new line and moving the cursor to the end.
def some_event(self):
try:
last_value = self.field.toPlainText()[-1]
if last_value == '\n':
print('You Pressed Enter!', repr(last_value))
self.field.setPlainText(self.field.toPlainText()[:-1])
self.field.moveCursor(QTextCursor.End)
except IndexError:
print('Index Error occurred')
pass
Full Code Minimal Working Example:
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
from PyQt5.QtGui import QTextCursor
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.grid = QGridLayout()
self.label = QLabel('Description Line 1')
self.grid.addWidget(self.label, 0, 0)
self.field = QPlainTextEdit()
self.field.setMaximumHeight(40)
self.field.textChanged.connect(self.some_event)
#TODO how to disable enter/return key events in this field?
self.grid.addWidget(self.field, 1, 0)
self.button = QPushButton('Some Button')
self.grid.addWidget(self.button)
self.centralWidget = QWidget()
self.centralWidget.setLayout(self.grid)
self.setCentralWidget(self.centralWidget)
def some_event(self):
try:
last_value = self.field.toPlainText()[-1]
if last_value == '\n':
print('You Pressed Enter!', repr(last_value))
self.field.setPlainText(self.field.toPlainText()[:-1])
self.field.moveCursor(QTextCursor.End)
except IndexError:
print('Index Error occurred')
pass
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())
One option is to override the keyPressEvent method of the QPlainTextEdit:
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
class PlainTextEdit(QPlainTextEdit):
def keyPressEvent(self, event):
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
return
super().keyPressEvent(event)
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.label = QLabel("Description Line 1")
self.field = PlainTextEdit()
self.field.setMaximumHeight(40)
self.button = QPushButton("Some Button")
self.centralWidget = QWidget()
grid = QGridLayout(self.centralWidget)
grid.addWidget(self.label, 0, 0)
grid.addWidget(self.field, 1, 0)
grid.addWidget(self.button)
self.setCentralWidget(self.centralWidget)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())
Another option that implements the same logic is to use an eventFilter().
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.label = QLabel("Description Line 1")
self.field = QPlainTextEdit()
self.field.setMaximumHeight(40)
self.button = QPushButton("Some Button")
self.field.installEventFilter(self)
self.centralWidget = QWidget()
grid = QGridLayout(self.centralWidget)
grid.addWidget(self.label, 0, 0)
grid.addWidget(self.field, 1, 0)
grid.addWidget(self.button)
self.setCentralWidget(self.centralWidget)
def eventFilter(self, obj, event):
if obj is self.field and event.type() == QEvent.KeyPress:
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
return True
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())