PyQt: Getting the amount of lines from QTextEdit - python

I am trying to make a chat application, so i added the QTextEdit widget where user types the content, maximum height of widget is 30 pixels, so basically one line.
self.msgtext = QtGui.QTextEdit(self)
self.msgtext.setObjectName('msgtext')
self.msgtext.setStyleSheet("#msgtext {background-color: black; color: yellow; font-size: 18pt; }")
self.msgtext.setMaximumSize(500, 30)
self.msgtextplain = self.msgtext.toPlainText()
I want to increase the maximum height of the widget whenever user get's one new line, But i don't know if there is any signal that can tell that i have reached new line.
Is there any signal, that can count the amount of lines from QTextEdit?

You can use blockCount() but don't forget to also resize whatever parent you are using for your QTextEdit. Here is an example:
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.msgtext = QtWidgets.QTextEdit(self)
self.msgtext.setObjectName('msgtext')
self.msgtext.setStyleSheet("#msgtext {background-color: black; color: yellow; font-size: 18pt; }")
self.msgtext.resize(500, 30)
self.msgtextplain = self.msgtext.toPlainText()
self.msgtext.textChanged.connect(self.changed)
def changed(self):
lines = self.msgtext.document().blockCount()
self.msgtext.resize(500, 30*lines)
self.resize(500, 30*lines)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
It's PyQt5. To do this in PyQt4 change everything that is QtWidgets to QtGui (and check the import lines evidently; this should be enough but do tell if you have any difficulties). Here is the result:

Related

Button doesn't show up

i'm trying to do a simple GUI for a python script that convert some text into a specific format but buttons doesn't show up in the window.
I first create the button class
class Button(QPushButton):
def __init__(self, btn_name=None):
super().__init__()
self.button = QPushButton(btn_name)
self.button.setCursor(
QCursor(QtCore.Qt.CursorShape.PointingHandCursor))
self.button.setStyleSheet(
"""*{border: 4px solid 'green';
border-radius: 45px;
font-size: 35px;
color: 'white';
padding: 25px 0;
margin: 100px, 200px}
*:hover{background: 'green'}
*:pressed{background: 'lightgreen'}"""
)
Then create the window class like this
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.window = QWidget()
self.window.resize(500, 500)
self.window.setWindowTitle("Pantuflis Software")
self.window.setFixedWidth(1000)
self.window.setStyleSheet("background: 'black';")
self.grid = QGridLayout()
self.window.setLayout(self.grid)
self.button = Button("Play")
self.grid.addWidget(self.button)
self.window.show()
Finally add the rest
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
But the button doesn't show up, only the main window does. I also tried the same but without creataing the button from my own class and works. Must be something wrong in the button class but i can't see what is.
If you are going to implement inherence then you have to apply the changes to the class. In your case it has a class that inherits from QPushButton but where you create the custom button which is not necessary, the same with the main window. My recommendation is that the OP should review his notes about inheritance.
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QCursor
from PyQt6.QtWidgets import QApplication, QGridLayout, QPushButton, QWidget
class Button(QPushButton):
def __init__(self, btn_name=""):
super().__init__(btn_name)
self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.setStyleSheet(
"""*{border: 4px solid 'green';
border-radius: 45px;
font-size: 35px;
color: 'white';
padding: 25px 0;
margin: 100px, 200px}
*:hover{background: 'green'}
*:pressed{background: 'lightgreen'}"""
)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(500, 500)
self.setWindowTitle("Pantuflis Software")
self.setFixedWidth(1000)
self.setStyleSheet("background: 'black';")
self.grid = QGridLayout(self)
self.button = Button("Play")
self.grid.addWidget(self.button)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

PyQt5 QPushButton setSyleSheet does not change button color when pressed

After studying various examples in this forum, I tried to change the color of a button when pressed. The button is normally blue, and when it is pressed I want it to turn red. The following code does display a blue button with white text, but it does not change to red when pressed. Please advise. I'm fairly new to learning python/pyqt5.
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
class Push_button(QPushButton):
def __init__(self, parent=None):
super(Push_button, self).__init__(parent)
self.setStyleSheet("background-color: rgb(0,0,255); color: rgb(255,255,255); \
pressed {background-color : rgb(255,0,0); color: rgb(255,255,255);} ")
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.myButton = Push_button(self)
self.myButton.setText("myButton")
self.myButton.clicked.connect(self.myButtonClicked)
def myButtonClicked(self):
print("myButtonClicked")
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
You are not using selectors correctly.
Right now your stylesheet sets the blue background color universally, and the red color for classes named "pressed".
self.setStyleSheet('''
QPushButton {
background-color: rgb(0,0,255); color: rgb(255,255,255);
}
QPushButton:pressed {
background-color : rgb(255,0,0); color: rgb(255,255,255);
}
''')
Read more about selector types in the official documentation.

Setting border for checkable QListWidgetItem

I have added some check-able QListWidgetItem and I have challenge setting the border color for the checkboxes. setForeground function only sets the color of the checkbox text.
Any suggestion please.
This is my sample code creating the check-able QListWidgetItems:
watch_list = ["Protesters", "Local news staff", "Techfluencers"]
for category in watch_list:
self.checkBox = QtWidgets.QListWidgetItem(category)
self.checkBox.setFlags(self.checkBox.flags() | QtCore.Qt.ItemIsUserCheckable)
self.checkBox.setCheckState(QtCore.Qt.Unchecked)
self.checkBox.setForeground(QtGui.QColor('#FFFFFF'))
self.watchListslistWidget.addItem(self.checkBox)
I have tried
self.watchListslistWidget.setStyleSheet("""
QListWidget::item {
border:1px #FFFFFF
}
""")
But it sets the all background of the QListWidget to white.
You can use a delegate:
from PyQt5 import QtCore, QtGui, QtWidgets
class CheckBoxDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
option.palette.setBrush(QtGui.QPalette.Button, QtGui.QColor("red"))
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.watchListslistWidget = QtWidgets.QListWidget()
self.setCentralWidget(self.watchListslistWidget)
watch_list = ["Protesters", "Local news staff", "Techfluencers"]
for category in watch_list:
checkBox = QtWidgets.QListWidgetItem(category)
checkBox.setFlags(checkBox.flags() | QtCore.Qt.ItemIsUserCheckable)
checkBox.setCheckState(QtCore.Qt.Unchecked)
self.watchListslistWidget.addItem(checkBox)
delegate = CheckBoxDelegate(self.watchListslistWidget)
self.watchListslistWidget.setItemDelegate(delegate)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I got it working by using indicator as follows:
self.watchListslistWidget.setStyleSheet("""
QListWidget::indicator{
border: 1px solid white;
}
""")

Adding a Background image with PyQt5

I'm trying to add a background using the answers from previous questions.
Sadly they don't work and return errors, either stylesheet, or the = sign, or the """.
I think it may be my location of the image? Is there something special required to store the image perhaps or something else I'm missing?
I've shown an edited down version of the code.
Thanks
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QMainWindow, QPushButton, QAction
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import pyqtSlot
import os
os.chdir(r'C:\Users\Paul Hannell\python_files')
class App(QMainWindow): # Opening Window
def __init__(self):
super().__init__()
self.title = "Timelord Timer PyQt5"
self.left = 70
self.top = 100
self.width = 1170
self.height = 740
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.setWindowIcon(QIcon(r'C:\Users\Paul Hannell\python_files\Timelord.ico'))
self.statusBar().showMessage('Message in Status Bar')
label=QLabel(self)
############################
# Background Image
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
lay = QHBoxLayout(self.centralwidget)
stylesheet = '''
MainWindow {
background-image: url(r'C:\Users\Paul Hannell\python_files\Running_Around4.png');
background-repeat: no-repeat;
background-position: center;
}
'''
#####################################
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
settingsMenu = mainMenu.addMenu('Settings')
resultsMenu = mainMenu.addMenu('Results')
reportsMenu = mainMenu.addMenu('Reports')
infoMenu = mainMenu.addMenu('Info')
newButton=QAction('New', self)
newButton.setStatusTip('New Race')
#newButton.triggered.connect(self.create) #This open new event options
fileMenu.addAction(newButton)
openButton = QAction('Open' , self)
openButton.setStatusTip('Open File')
#openButton.triggered.connect(self.open) # This will open existing
fileMenu.addAction(openButton)
deleteButton=QAction('Delete', self)
deleteButton.setStatusTip('Delete Race')
#deleteButton.triggered.connect(self.create) #This delete existing event.
fileMenu.addAction(deleteButton)
exitButton=QAction('Exit', self)
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(self.close)
fileMenu.addAction(exitButton)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Your code is badly indented (and too long) so it's hard to tell, but I see several issues:
it shoud be #MainWindow in the style sheet (you're missing a #)
you need to name the App with this name: self.setObjectName('MainWindow')
you need to use setStyleSheet at some point
the url needs fixing: no quotes nor 'r'; simply the file name (maybe the space in the file name needs escaping, you could try to play with it)
This, for instance, works:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QMainWindow, QPushButton, QAction
class App(QMainWindow): # Opening Window
def __init__(self):
super().__init__()
self.setWindowTitle('hello bg')
self.setObjectName('MainWindow')
stylesheet = '''
#MainWindow {
background-image: url(/home/me/photos/DSC_0001.jpg);
background-repeat: no-repeat;
background-position: center;
}
'''
self.setStyleSheet(stylesheet)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())

How to customise QGroupBox title in PyQt5?

Here's a piece of code that creates a simple QGroupBox:
from PyQt5.QtWidgets import (QApplication, QWidget,
QGroupBox, QGridLayout)
class QGroupBoxTest(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
gb = QGroupBox()
gb.setTitle('QGroupBox title')
appLayout = QGridLayout()
appLayout.addWidget(gb, 0, 0)
self.setLayout(appLayout)
self.setWindowTitle('QGroupBox test window')
self.setGeometry(300, 300, 300, 200)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
test = QGroupBoxTest()
test.show()
sys.exit(app.exec_())
and here's what the output looks like to me:
Now let's say I want to add some style to it and I do this by adding this line to the initUI method:
gb.setStyleSheet("border: 1px solid gray; border-radius: 5px")
here's the output:
As can be clearly seen from the pic, the title has ended up inside the frame and now is overlapping the frame border.
So I have three questions actually:
Why did the title move?
How do I move it about and place it wherever I want (if possible)?
What if I simply want to round off border corners without specifying the border-style property. Let's say I want the border-style to stay the same as in the first pic but with rounded corners. How do I do that?
1) Probably that's the default QT placement, in the first image the platform style is used, and its take care of borders and title placement, when you change the stylesheet you override something and you get the ugly placement.
2) You can control the "title" position using the QGroupBox:title controls, for example:
gb.setStyleSheet('QGroupBox:title {'
'subcontrol-origin: margin;'
'subcontrol-position: top center;'
'padding-left: 10px;'
'padding-right: 10px; }')
will result in something like this:
3) My suggestion is to create different strings for the stylesheet attributes you want to change, then compose them to create the style you want.
Even though this question has already been answered, I will post what I've figured out regarding technics of applying style sheets to widgets in PyQt which partly answers my original question. I hope someone will find it useful.
I think it's nice to keep the styles in separate css(qss) files:
/*css stylesheet file that contains all the style information*/
QGroupBox {
border: 1px solid black;
border-radius: 5px;
}
QGroupBox:title{
subcontrol-origin: margin;
subcontrol-position: top center;
padding: 0 3px 0 3px;
}
and the python code looks like this:
from PyQt5.QtWidgets import (QApplication, QWidget,
QGroupBox, QGridLayout)
from PyQt5.QtCore import QFile, QTextStream
class QGroupBoxTest(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
gb = QGroupBox()
gb.setTitle('QGroupBox title:')
gb.setStyleSheet(self.getStyleSheet("./styles.qss"))
appLayout = QGridLayout()
appLayout.addWidget(gb, 0, 0)
self.setLayout(appLayout)
self.setWindowTitle('QGroupBox test window')
self.setGeometry(300, 300, 300, 300)
def getStyleSheet(self, path):
f = QFile(path)
f.open(QFile.ReadOnly | QFile.Text)
stylesheet = QTextStream(f).readAll()
f.close()
return stylesheet
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
test = QGroupBoxTest()
test.show()
sys.exit(app.exec_())
which yields the following output:

Categories

Resources