I am having trouble getting this to work the way I want. I want to draw a number of lines below each other and display this in a window that has scrollbars.
So far I can draw the lines and display them, but my scrollbars wont work. What is the correct way to do this?
The file y.list contains simple pairs of numbers as start and end point of my lines. Like:
1 100
4 64
72 98
Here is my code so far:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawLines(qp)
qp.end()
def drawLines(self, qp):
wTotal = 4*2*117
pen = QPen(QColor(100, 200, 0), 5, Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(24, 20, 24+wTotal, 20)
pen = QPen(QColor(0, 0, 255), 2, Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(24+wTotal/2,18,24+wTotal/2,22)
pen = QPen(QColor(0, 50, 255), 2, Qt.SolidLine)
qp.setPen(pen)
with open("y.list", 'r') as points:
linecount = 0
for line in points:
linecount += 1
splitLine = line.split()
start = int(splitLine[0])*4
end = int(splitLine[1])*4
qp.drawLine(20+start, 20+5*linecount, 20+end, 20+5*linecount)
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setGeometry(200,100,1100,800)
#Container Widget
widget = QWidget()
#Layout of Container Widget
layout = QVBoxLayout(self)
lines = Example()
layout.addWidget(lines)
widget.setLayout(layout)
#Scroll Area Properties
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(True)
scroll.setWidget(widget)
#Scroll Area Layer add
vLayout = QVBoxLayout(self)
vLayout.addWidget(scroll)
self.setLayout(vLayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
app.exec_()
Currently, you have made the widget resizable, so the widget will be automatically resized to fit the available space, and the scrollbars will never change (because they're not needed).
To change this, you need give the widget a specific size, and don't automatically resize it:
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
widget.resize(2000, 2000)
NB: don't attempt to programmatically resize the widget during the paint-event, because resizing can itself cause a re-paint.
Related
I want two Widgets/Layouts be next to each other (using QHBoxLayout) but they should have the same size (half the size of the window).
It should look like this:
but I want the button to be smaller (the button is contained in another Layout) while the list widget remains the same size.
I tried using minimumSize, sizeHint, stretch, etc. but it never worked.
My code:
import sys
from PyQt5 import QtWidgets as qtw
class SelectView(qtw.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.width = 750
self.height = 500
self.setGeometry(200, 200, self.width, self.height)
self.setWindowTitle("SelectView")
self.list_widget = qtw.QListWidget()
self.list_widget.setGeometry(0, 0, self.width//2, self.height)
for i in range(100):
self.list_widget.addItem(qtw.QListWidgetItem(f"something{i}"))
left_layout = qtw.QVBoxLayout()
btn = qtw.QPushButton("button")
# I'm using this to show you that I want the widgets/layout
# to be half the size of the window
btn.setFixedWidth(375)
left_layout.addWidget(btn)
h_layout = qtw.QHBoxLayout()
h_layout.addWidget(self.list_widget)
h_layout.addLayout(left_layout)
self.setLayout(h_layout)
self.show()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = SelectView()
sys.exit(app.exec_())
edit:
self.list_widget.setMinimumSize(self.width//2, self.height)
would do the job if the window had a fixed size.
You have to use the stretch factor:
h_layout.addWidget(self.list_widget, stretch=1)
h_layout.addLayout(left_layout, stretch=1)
Note: Remove btn.setFixedWidth(...)
SInce you have specified the size of the window, no need for the fixed width sizes you defined for the widgets. Instead do something like this:
layout = QHBoxLayout()
layout.addWidget(widget1)
layout.addWidget(widget2)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
I want to adjust height and width using grid layout.
class MatchStepWidget(QWidget):
def __init__(self,parent):
super(MatchStepWidget,self).__init__(parent)
self.initUI()
def initUI(self):
layout = QGridLayout(self)
test = QTextEdit(self)
bt_test = QPushButton(self)
layout.addWidget(test,0,0,1,1)
layout.addWidget(bt_test,1,0,1,1)
# bt_test.hide()
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
myapp = MatchStepWidget(None)
myapp.show()
sys.exit(app.exec_())
I set row span and col span as same for both button and textedit.
but Textedit covers so much area than pushbutton
How can i adjust Textedit area using grid layout?
The default QPushButton will not stretch vertically, if you want to change it then you must modify the QSizePolicy. Also if you want the height of the QPushButton and the QTextEdit to be the same then you must set the stretch factor for each row of the layout:
def initUI(self):
test = QTextEdit()
bt_test = QPushButton()
layout = QGridLayout(self)
layout.addWidget(test, 0, 0)
layout.addWidget(bt_test, 1, 0)
sp = bt_test.sizePolicy()
sp.setVerticalPolicy(QSizePolicy.Minimum)
bt_test.setSizePolicy(sp)
layout.setRowStretch(0, 1)
layout.setRowStretch(1, 1)
Consider the following toy example:
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
label.setPixmap(canvas)
layout.addWidget(label)
def paintEvent():
painter = QtGui.QPainter(label.pixmap())
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtCore.Qt.red)
painter.drawArc(0, 0, 100, 100, 1440, -2880)
painter.end()
paintEvent()
self.show()
app = QtWidgets.QApplication([])
window = MainWindow()
app.exec_()
How can I paint the arc using an arbitrary number of colours ideally of varying lengths?
I tried to do it with gradients (linear and conical) but I have been unable to obtain accurate results.
I suppose the broader question is can I somehow have different pen colours when painting an arc? Note that the arc can be a half circle, a full circle or anything in between.
The colours are to be distributed using percentages. Each colour is a fraction of the arc's length. But I am content with a solution where all colours are equally spaced.
A possible solution is to paint the arc in parts:
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
canvas.fill(QtGui.QColor("white"))
label.setPixmap(canvas)
layout.addWidget(label)
def paint_label():
painter = QtGui.QPainter(label.pixmap())
painter.setRenderHint(QtGui.QPainter.Antialiasing)
r = QtCore.QRect(0, 0, 100, 100)
delta_angle = -180 * 16
start_angle = 90 * 16
values = (1, 2, 3, 4)
colors = (
QtGui.QColor("red"),
QtGui.QColor("blue"),
QtGui.QColor("green"),
QtGui.QColor("yellow"),
)
sum_of_values = sum(values)
for value, color in zip(values, colors):
end_angle = start_angle + int((value/sum_of_values) * delta_angle)
painter.setPen(color)
painter.drawArc(r, start_angle, end_angle - start_angle)
start_angle = end_angle
painter.end()
paint_label()
self.show()
def main():
app = QtWidgets.QApplication([])
window = MainWindow()
app.exec_()
if __name__ == "__main__":
main()
The solution provided by eyllanesc is perfectly fine, but I wanted to show the possibility of achieving the same result using a conical gradient instead of drawing single arcs.
Since we want actual arcs to be drawn, the trick is to use "ranges" of colors with very narrow margins.
For example, to get a conical gradient that is half red and half blue, we'll use something like this:
gradient.setColorAt(.5, QtCore.Qt.red)
# set the next color with a stop very close to the previous
gradient.setColorAt(.500001, QtCore.Qt.blue)
I prepared an example with a small interface to test its possibilities out.
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
panelLayout = QtWidgets.QHBoxLayout()
layout.addLayout(panelLayout)
panelLayout.addWidget(QtWidgets.QLabel('Start'))
self.startSpin = QtWidgets.QSpinBox(maximum=360, suffix='°')
self.startSpin.setValue(90)
panelLayout.addWidget(self.startSpin)
panelLayout.addWidget(QtWidgets.QLabel('Extent'))
self.extentSpin = QtWidgets.QSpinBox(maximum=360, suffix='°')
self.extentSpin.setValue(180)
panelLayout.addWidget(self.extentSpin)
panelLayout.addWidget(QtWidgets.QLabel('Width'))
self.penSpin = QtWidgets.QSpinBox(minimum=1, maximum=20, suffix='px')
self.penSpin.setValue(3)
panelLayout.addWidget(self.penSpin)
self.startSpin.valueChanged.connect(self.updateCanvas)
self.extentSpin.valueChanged.connect(self.updateCanvas)
self.penSpin.valueChanged.connect(self.updateCanvas)
self.colors = []
self.colorSpins = []
colorLayout = QtWidgets.QHBoxLayout()
layout.addLayout(colorLayout)
for color in ('red', 'green', 'blue', 'yellow'):
colorLayout.addWidget(QtWidgets.QLabel(color))
self.colors.append(QtGui.QColor(color))
colorSpin = QtWidgets.QSpinBox(minimum=1, maximum=50, value=25)
colorLayout.addWidget(colorSpin)
colorSpin.valueChanged.connect(self.updateCanvas)
self.colorSpins.append(colorSpin)
self.label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
self.label.setPixmap(canvas)
layout.addWidget(self.label)
self.updateCanvas()
self.show()
def updateCanvas(self):
pm = QtGui.QPixmap(self.label.pixmap().size())
pm.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(pm)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.translate(.5, .5)
sizes = [spin.value() for spin in self.colorSpins]
total = sum(sizes)
extent = self.extentSpin.value() / 360
grad = QtGui.QConicalGradient(50, 50, self.startSpin.value())
gradPos = 1
# set colors starting from stop 1.0 to (1.0 - extent), since
# conical gradients are always counter-clockwise and the actual arc
# is negative, so it is drawn clockwise
for i, (size, color) in enumerate(zip(sizes, self.colors)):
grad.setColorAt(gradPos, color)
gradPos -= size / total * extent
if i < len(self.colors) - 1:
# extend the color right next to the next value
grad.setColorAt(gradPos + .000001, color)
if extent != 1:
# ensure that the first color is not painted at the edget of the
# last due to antialiasing
grad.setColorAt(0, self.colors[0])
grad.setColorAt(1 - extent, self.colors[-1])
offset = self.penSpin.maximum()
pen = QtGui.QPen(grad, self.penSpin.value(), cap=QtCore.Qt.FlatCap)
painter.setPen(pen)
# move the brush origin so that the conical gradient correctly centered
# in the middle of the ellipse
painter.setBrushOrigin(offset, offset)
painter.drawArc(offset, offset, 100, 100, self.startSpin.value() * 16, -self.extentSpin.value() * 16)
painter.end()
self.label.setPixmap(pm)
I want to do board with square widgets. When I run code it creates nice board but after resize it become looks ugly. I am trying resize it with resize Event but it exists (probably some errors). I have no idea how to resize children after resize of parent.
Children widgets must be squares so it is also problem since I can not use auto expand. Maybe it is simple problem but I can not find solution. I spend hours testing different ideas but it now works as it should.
This what I want resize (click maximize):
After maximize it looks ugly (I should change children widget but on what event (I think on resizeEvent but it is not works) and how (set from parent or children cause program exit).
This is my minimize code:
import logging
import sys
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QFont, QPaintEvent, QPainter
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout
class Application(QApplication):
pass
class Board(QWidget):
def square_size(self):
size = self.size()
min_size = min(size.height(), size.width())
min_size_1_8 = min_size // 8
square_size = QSize(min_size_1_8, min_size_1_8)
logging.debug(square_size)
return square_size
def __init__(self, parent=None):
super().__init__(parent=parent)
square_size = self.square_size()
grid = QGridLayout()
grid.setSpacing(0)
squares = []
for x in range(8):
for y in range(8):
square = Square(self, (x + y - 1) % 2)
squares.append(squares)
square.setFixedSize(square_size)
grid.addWidget(square, x, y)
self.squares = squares
self.setLayout(grid)
def resizeEvent(self, event: QtGui.QResizeEvent) -> None:
# how to resize children?
logging.debug('Resize %s.', self.__class__.__name__)
logging.debug('Size %s.', event.size())
super().resizeEvent(event)
class Square(QWidget):
def __init__(self, parent, color):
super().__init__(parent=parent)
if color:
self.color = QtCore.Qt.white
else:
self.color = QtCore.Qt.black
def resizeEvent(self, event: QtGui.QResizeEvent) -> None:
logging.debug('Resize %s.', self.__class__.__name__)
logging.debug('Size %s.', event.size())
super().resizeEvent(event)
def paintEvent(self, event: QPaintEvent) -> None:
painter = QPainter()
painter.begin(self)
painter.fillRect(self.rect(), self.color)
painter.end()
def main():
logging.basicConfig(level=logging.DEBUG)
app = Application(sys.argv)
app.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
default_font = QFont()
default_font.setPointSize(12)
app.setFont(default_font)
board = Board()
board.setWindowTitle('Board')
# ugly look
# chessboard.showMaximized()
# looks nize but resize not works
board.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()
How should I do resize of square children to avoid holes?
2nd try - improved code but still I have not idea how to resize children
Some new idea with centering it works better (no gaps now) but still I do not know how to resize children (without crash).
After show():
Too wide (it keeps proportions):
Too tall (it keeps proportions):
Larger (it keeps proportions but children is not scaled to free space - I do not know how to resize children still?):
Improved code:
import logging
import sys
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QFont, QPaintEvent, QPainter
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QHBoxLayout, QVBoxLayout
class Application(QApplication):
pass
class Board(QWidget):
def square_size(self):
size = self.size()
min_size = min(size.height(), size.width())
min_size_1_8 = min_size // 8
square_size = QSize(min_size_1_8, min_size_1_8)
logging.debug(square_size)
return square_size
def __init__(self, parent=None):
super().__init__(parent=parent)
square_size = self.square_size()
vertical = QVBoxLayout()
horizontal = QHBoxLayout()
grid = QGridLayout()
grid.setSpacing(0)
squares = []
for x in range(8):
for y in range(8):
square = Square(self, (x + y - 1) % 2)
squares.append(squares)
square.setFixedSize(square_size)
grid.addWidget(square, x, y)
self.squares = squares
horizontal.addStretch()
horizontal.addLayout(grid)
horizontal.addStretch()
vertical.addStretch()
vertical.addLayout(horizontal)
vertical.addStretch()
self.setLayout(vertical)
def resizeEvent(self, event: QtGui.QResizeEvent) -> None:
# how to resize children?
logging.debug('Resize %s.', self.__class__.__name__)
logging.debug('Size %s.', event.size())
super().resizeEvent(event)
class Square(QWidget):
def __init__(self, parent, color):
super().__init__(parent=parent)
if color:
self.color = QtCore.Qt.white
else:
self.color = QtCore.Qt.black
def resizeEvent(self, event: QtGui.QResizeEvent) -> None:
logging.debug('Resize %s.', self.__class__.__name__)
logging.debug('Size %s.', event.size())
super().resizeEvent(event)
def paintEvent(self, event: QPaintEvent) -> None:
painter = QPainter()
painter.begin(self)
painter.fillRect(self.rect(), self.color)
painter.end()
def main():
logging.basicConfig(level=logging.DEBUG)
app = Application(sys.argv)
app.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
default_font = QFont()
default_font.setPointSize(12)
app.setFont(default_font)
board = Board()
board.setWindowTitle('Board')
# ugly look
# chessboard.showMaximized()
# looks nice but resize not works
board.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()
How should I resize square children without crash?
There are two possible solution.
You can use the Graphics View framework, which is intended exactly for this kind of applications where custom/specific graphics and positioning have to be taken into account, otherwise create a layout subclass.
While reimplementing a layout is slightly simple in this case, you might face some issues as soon as the application becomes more complex. On the other hand, the Graphics View framework has a steep learning curve, as you'll need to understand how it works and how object interaction behaves.
Subclass the layout
Assuming that the square count is always the same, you can reimplement your own layout that will set the correct geometry based on its contents.
In this example I also created a "container" with other widgets to show the resizing in action.
When the window width is very high, it will use the height as a reference and center it horizontally:
On the contrary, when the height is bigger, it will be centered vertically:
Keep in mind that you should not add other widgets to the board, otherwise you'll get into serious issues.
This would not be impossible, but its implementation might be much more complex, as the layout would need to take into account the other widgets positions, size hints and possible expanding directions in order to correctly compute the new geometry.
from PyQt5 import QtCore, QtGui, QtWidgets
class Square(QtWidgets.QWidget):
def __init__(self, parent, color):
super().__init__(parent=parent)
if color:
self.color = QtCore.Qt.white
else:
self.color = QtCore.Qt.black
self.setMinimumSize(50, 50)
def paintEvent(self, event: QtGui.QPaintEvent) -> None:
painter = QtGui.QPainter(self)
painter.fillRect(self.rect(), self.color)
class EvenLayout(QtWidgets.QGridLayout):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setSpacing(0)
def setGeometry(self, oldRect):
# assuming that the minimum size is 50 pixel, find the minimum possible
# "extent" based on the geometry provided
minSize = max(50 * 8, min(oldRect.width(), oldRect.height()))
# create a new squared rectangle based on that size
newRect = QtCore.QRect(0, 0, minSize, minSize)
# move it to the center of the old one
newRect.moveCenter(oldRect.center())
super().setGeometry(newRect)
class Board(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
layout = EvenLayout(self)
self.squares = []
for row in range(8):
for column in range(8):
square = Square(self, not (row + column) & 1)
self.squares.append(square)
layout.addWidget(square, row, column)
class Chess(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QGridLayout(self)
header = QtWidgets.QLabel('Some {}long label'.format('very ' * 20))
layout.addWidget(header, 0, 0, 1, 3, QtCore.Qt.AlignCenter)
self.board = Board()
layout.addWidget(self.board, 1, 1)
leftLayout = QtWidgets.QVBoxLayout()
layout.addLayout(leftLayout, 1, 0)
rightLayout = QtWidgets.QVBoxLayout()
layout.addLayout(rightLayout, 1, 2)
for b in range(1, 9):
leftLayout.addWidget(QtWidgets.QPushButton('Left Btn {}'.format(b)))
rightLayout.addWidget(QtWidgets.QPushButton('Right Btn {}'.format(b)))
footer = QtWidgets.QLabel('Another {}long label'.format('very ' * 18))
layout.addWidget(footer, 2, 0, 1, 3, QtCore.Qt.AlignCenter)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Chess()
w.show()
sys.exit(app.exec_())
Using the Graphics View
The result will be visually identical to the previous one, but while the overall positioning, drawing and interaction would be conceptually a bit easier, understanding how Graphics Views, Scenes and objects work might require you some time to get the hang of it.
from PyQt5 import QtCore, QtGui, QtWidgets
class Square(QtWidgets.QGraphicsWidget):
def __init__(self, color):
super().__init__()
if color:
self.color = QtCore.Qt.white
else:
self.color = QtCore.Qt.black
def paint(self, qp, option, widget):
qp.fillRect(option.rect, self.color)
class Scene(QtWidgets.QGraphicsScene):
def __init__(self):
super().__init__()
self.container = QtWidgets.QGraphicsWidget()
layout = QtWidgets.QGraphicsGridLayout(self.container)
layout.setSpacing(0)
self.container.setContentsMargins(0, 0, 0, 0)
layout.setContentsMargins(0, 0, 0, 0)
self.addItem(self.container)
for row in range(8):
for column in range(8):
square = Square(not (row + column) & 1)
layout.addItem(square, row, column, 1, 1)
class Board(QtWidgets.QGraphicsView):
def __init__(self):
super().__init__()
scene = Scene()
self.setScene(scene)
self.setAlignment(QtCore.Qt.AlignCenter)
# by default a graphics view has a border frame, disable it
self.setFrameShape(0)
# make it transparent
self.setStyleSheet('QGraphicsView {background: transparent;}')
def resizeEvent(self, event):
super().resizeEvent(event)
# zoom the contents keeping the ratio
self.fitInView(self.scene().container, QtCore.Qt.KeepAspectRatio)
class Chess(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QGridLayout(self)
header = QtWidgets.QLabel('Some {}long label'.format('very ' * 20))
layout.addWidget(header, 0, 0, 1, 3, QtCore.Qt.AlignCenter)
self.board = Board()
layout.addWidget(self.board, 1, 1)
leftLayout = QtWidgets.QVBoxLayout()
layout.addLayout(leftLayout, 1, 0)
rightLayout = QtWidgets.QVBoxLayout()
layout.addLayout(rightLayout, 1, 2)
for b in range(1, 9):
leftLayout.addWidget(QtWidgets.QPushButton('Left Btn {}'.format(b)))
rightLayout.addWidget(QtWidgets.QPushButton('Right Btn {}'.format(b)))
footer = QtWidgets.QLabel('Another {}long label'.format('very ' * 18))
layout.addWidget(footer, 2, 0, 1, 3, QtCore.Qt.AlignCenter)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Chess()
w.show()
sys.exit(app.exec_())
I've been trying to create a basic clock using PyQt5. The clock part works and the background image behind the clock loads but I am unable to get the background of the text to be transparent.
I have tried both the way listed below and also with self.lbl1.setStyleSheet("background-color: rgba(255, 255, 255, 10);") but I get the same result in both cases.
If I set the layout.setCurrentIndex(0) I see that the background jpeg is there so that is loading just fine.
Any thoughts on what I would need to do to have layered widgets with transparency?
To try to clear it up a bit
Here is what I get
here is what I want
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
layout = QStackedLayout()
#Background area test
self.background = QLabel(self)
self.background.setPixmap(QPixmap("image.jpeg"))
self.background.show()
#self.background.setAutoFillBackground(True)
#Setup text area for clock
newfont = QFont("Consolas",120, QFont.Bold)
self.lbl1 = QLabel()
self.lbl1.setAlignment(Qt.AlignCenter)
self.lbl1.setFont(newfont)
self.lbl1.setWindowFlags(Qt.FramelessWindowHint)
self.lbl1.setAttribute(Qt.WA_TranslucentBackground)
#Timer to refresh clock
timer = QTimer(self)
timer.timeout.connect(self.showTime)
timer.start(1000)
self.showTime()
#layout area for widgets
layout.addWidget(self.background)
layout.addWidget(self.lbl1)
layout.setCurrentIndex(1)
self.setLayout(layout)
self.setGeometry(300,300,250,150)
self.show()
def showTime(self):
time = QTime.currentTime()
text = time.toString('hh:mm')
if (time.second() % 2) == 0:
text = text[:2] + ' ' + text[3:]
self.lbl1.setText(text)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
The problem is using QStackedWidget, according to the documentation:
The QStackedLayout class provides a stack of widgets where only one
widget is visible at a time.
In it tells us that only a widget is visible. That is why the image is not shown, to force make them visible we use:
layout.setStackingMode(QStackedLayout.StackAll)
Obtaining the following:
As mentioned in the documentation QStackedlayout is used to display one widget at a time. In your case I think it is unnecessary, you could only use a label and any layout, you can use styleSheet to place the background image, the following code shows what I say.
class Example(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
self.initUI()
def initUI(self):
self.setGeometry(300,300,250,150)
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
newfont = QFont("Consolas",120, QFont.Bold)
self.lbl1 = QLabel(self)
self.lbl1.setStyleSheet("border-image:url(image.jpeg);")
self.lbl1.setAlignment(Qt.AlignCenter)
self.lbl1.setFont(newfont)
layout.addWidget(self.lbl1)
#Timer to refresh clock
timer = QTimer(self)
timer.timeout.connect(self.showTime)
timer.start(1000)
self.showTime()
self.show()
def showTime(self):
time = QTime.currentTime()
text = time.toString('hh:mm')
if (time.second() % 2) == 0:
text = text[:2] + ' ' + text[3:]
self.lbl1.setText(text)
The following image shows the new output: