I want to load an image If I click on a button but only a little tiny pixel of the image appears.
It looks like that:
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(1000, 1000)
self.setWindowTitle("MyWindow")
self.setWindowIcon(QIcon("myIcon.ico"))
self.setMaximumSize(width, height)
self.setMinimumSize(1000, 1000)
self.canvas = QGroupBox(self)
self.canvas.setStyleSheet("QGroupBox { border: 1px solid #9F9B9B}")
self.canvas.move(350, 30)
self.canvas.resize(210, 220)
self.bImage = QPushButton("Load Image", self)
self.bImage.move(150, 207)
self.bImage.clicked.connect(self.openImage)
self.show()
def openImage(self):
self.label = QLabel(self)
self.preview = QPixmap("image.png")
self.label.setPixmap(self.preview)
self.label.move(350, 30)
But Strangely if I place the code from the openImage() function into the first lines of the init() funtion the image will be completely displayed.
What shall I do to load the entire image by the openImage() function?
It is generally a bad idea to try to position widgets using absolute values. You should always use layouts whenever possible. The reason why the image doesn't show is because you move the label to a position behind the group-box. Instead, you should put the label in a layout inside the group-box:
class MyWindow(QtGui.QWidget):
def __init__(self):
...
self.canvas = QtGui.QGroupBox(self)
...
self.label = QtGui.QLabel(self)
layout = QtGui.QVBoxLayout(self.canvas)
layout.addWidget(self.label)
...
def openImage(self):
self.preview = QtGui.QPixmap("image.png")
self.label.setPixmap(self.preview)
Related
I am trying the whole morning already to fix that.
So I have a PyQt Main Window where I want to display two widgets.
In the first widget there are articles listed (which works so far).
When I click on them until now a QMessageBox is opening, but I want that
a second widget is opening where I can read the RSS Feed.
But this is not working. See Code below:
class ArticleWidgets(QWidget):
def __init__(self, *args):
super().__init__(*args)
self.setGeometry(610, 610, 600, 600)
self.initUi()
def initUi(self):
self.box = QHBoxLayout(self)
def show(self, feed=None):
self.title = QLabel()
self.summary = QLabel()
self.link = QLabel()
if feed:
self.title.setText(feed[0])
self.summary.setText(feed[1])
self.link.setText(feed[2])
self.box.addWidget(self.title)
self.box.addWidget(self.summary)
self.box.addWidget(self.link)
self.setLayout(self.box)
class TitleWidgets(QWidget):
def __init__(self, *args):
super().__init__(*args)
self.setGeometry(10, 10, 600, 600)
self.initUi()
def initUi(self):
vbox = QHBoxLayout(self)
self.titleList = QListWidget()
self.titleList.itemDoubleClicked.connect(self.onClicked)
self.titleList.setGeometry(0, 0, 400, 400)
self.news = ANFFeed()
for item in self.news.all_feeds:
self.titleList.addItem(item[0])
vbox.addWidget(self.titleList)
def onClicked(self, item):
feeds = self.news.all_feeds
id = 0
for elem in range(len(feeds)):
if feeds[elem][0] == item.text():
id = elem
summary = feeds[id][1] + '\n\n'
link = feeds[id][2]
if feeds and id:
#ANFApp(self).show_articles(feeds[id])
show = ANFApp()
show.show_articles(feed=feeds[id])
QMessageBox.information(self, 'Details', summary + link)
class ANFApp(QMainWindow):
def __init__(self, *args):
super().__init__(*args)
self.setWindowState(Qt.WindowMaximized)
self.setWindowIcon(QIcon('anf.png'))
self.setAutoFillBackground(True)
self.anfInit()
self.show()
def anfInit(self):
self.setWindowTitle('ANF RSS Reader')
TitleWidgets(self)
#article_box = ArticleWidgets(self)
exitBtn = QPushButton(self)
exitBtn.setGeometry(600, 600, 100, 50)
exitBtn.setText('Exit')
exitBtn.setStyleSheet("background-color: red")
exitBtn.clicked.connect(self.exit)
def show_articles(self, feed=None):
present = ArticleWidgets()
present.show(feed)
def exit(self):
QCoreApplication.instance().quit()
Solution using Pyqtgraph's Docks and QTextBrowser
Here is a code trying to reproduce your sketch. I used the Pyqtgraph module (Documentation here: Pyqtgraph's Documentation and Pyqtgraph's Web Page) because its Dock widget is easier to use and implement from my perspective.
You must install the pyqtgraph module before trying this code:
import sys
from PyQt5 import QtGui, QtCore
from pyqtgraph.dockarea import *
class DockArea(DockArea):
## This is to prevent the Dock from being resized to te point of disappear
def makeContainer(self, typ):
new = super(DockArea, self).makeContainer(typ)
new.setChildrenCollapsible(False)
return new
class MyApp(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
central_widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
label = QtGui.QLabel('This is a label, The widgets will be below')
label.setMaximumHeight(15)
## The DockArea as its name says, is the are where we place the Docks
dock_area = DockArea(self)
## Create the Docks and change some esthetic of them
self.dock1 = Dock('Widget 1', size=(300, 500))
self.dock2 = Dock('Widget 2', size=(400, 500))
self.dock1.hideTitleBar()
self.dock2.hideTitleBar()
self.dock1.nStyle = """
Dock > QWidget {
border: 0px solid #000;
border-radius: 0px;
}"""
self.dock2.nStyle = """
Dock > QWidget {
border: 0px solid #000;
border-radius: 0px;
}"""
self.button = QtGui.QPushButton('Exit')
self.widget_one = WidgetOne()
self.widget_two = WidgetTwo()
## Place the Docks inside the DockArea
dock_area.addDock(self.dock1)
dock_area.addDock(self.dock2, 'right', self.dock1)
## The statment above means that dock2 will be placed at the right of dock 1
layout.addWidget(label)
layout.addWidget(dock_area)
layout.addWidget(self.button)
## Add the Widgets inside each dock
self.dock1.addWidget(self.widget_one)
self.dock2.addWidget(self.widget_two)
## This is for set the initial size and posotion of the main window
self.setGeometry(100, 100, 600, 400)
## Connect the actions to functions, there is a default function called close()
self.widget_one.TitleClicked.connect(self.dob_click)
self.button.clicked.connect(self.close)
def dob_click(self, feed):
self.widget_two.text_box.clear()
## May look messy but wat i am doing is somethin like this:
## 'Title : ' + feed[0] + '\n\n' + 'Summary : ' + feed[1]
self.widget_two.text_box.setText(
'Title : ' + feed[0]\
+ '\n\n' +\
'Summary : ' + feed[1]
)
class WidgetOne(QtGui.QWidget):
## This signal is created to pass a "list" when it (the signal) is emited
TitleClicked = QtCore.pyqtSignal([list])
def __init__(self):
QtGui.QWidget.__init__(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.titleList = QtGui.QListWidget()
self.label = QtGui.QLabel('Here is my list:')
self.layout.addWidget(self.label)
self.layout.addWidget(self.titleList)
self.titleList.addItem(QtGui.QListWidgetItem('Title 1'))
self.titleList.addItem(QtGui.QListWidgetItem('Title 2'))
self.titleList.itemDoubleClicked.connect(self.onClicked)
def onClicked(self, item):
## Just test values
title = item.text()
summary = "Here you will put the summary of {}. ".format(title)*50
## Pass the values as a list in the signal. You can pass as much values
## as you want, remember that all of them have to be inside one list
self.TitleClicked.emit([title, summary])
class WidgetTwo(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.label2 = QtGui.QLabel('Here we show results?:')
self.text_box = QtGui.QTextBrowser()
self.layout.addWidget(self.label2)
self.layout.addWidget(self.text_box)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
Again, there are comments inside the code to help you understand what I did.
Here is how it looks:
If you pass the mouse between the two widgets you will see the mouse icon will change, with that you can readjust on the run the size of both widgets.
Final Words
This is another approach, more "interactive" and more esthetic than my previous answer. As you said, using a QSplitter works too.
Problems
The way you are building your GUI is, in my opinion, messy and it may lead to errors. I suggest the use of Layouts for a more organized GUI.
The other problem is that each widget is an independent class so if you want to connect an action in one widget to do something in the other widget through the Main Window, you must use Signals.
Edit : Another suggestion, use other name for the close function instead of exit and try using self.close() instead of QCoreApplication.instance().quit()
Solution
Trying to emulate what you want to do I made this GUI:
import sys
from PyQt5 import QtGui, QtCore
class MyWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
## Generate the structure parts of the MainWindow
self.central_widget = QtGui.QWidget() # A QWidget to work as Central Widget
self.layout1 = QtGui.QVBoxLayout() # Vertical Layout
self.layout2 = QtGui.QHBoxLayout() # Horizontal Layout
self.widget_one = WidgetOne()
self.widget_two = WidgetTwo()
self.exitBtn = QtGui.QPushButton('Exit')
## Build the structure
# Insert a QWidget as a central widget for the MainWindow
self.setCentralWidget(self.central_widget)
# Add a principal layout for the widgets/layouts you want to add
self.central_widget.setLayout(self.layout1)
# Add widgets/layuts, as many as you want, remember they are in a Vertical
# layout: they will be added one below of the other
self.layout1.addLayout(self.layout2)
self.layout1.addWidget(self.exitBtn)
# Here we add the widgets to the horizontal layout: one next to the other
self.layout2.addWidget(self.widget_one)
self.layout2.addWidget(self.widget_two)
## Connect the signal
self.widget_one.TitleClicked.connect(self.dob_click)
def dob_click(self, feed):
## Change the properties of the elements in the second widget
self.widget_two.title.setText('Title : '+feed[0])
self.widget_two.summary.setText('Summary : '+feed[1])
## Build your widgets same as the Main Window, with the excepton that here you don't
## need a central widget, because it is already a widget.
class WidgetOne(QtGui.QWidget):
TitleClicked = QtCore.pyqtSignal([list]) # Signal Created
def __init__(self):
QtGui.QWidget.__init__(self)
##
self.layout = QtGui.QVBoxLayout() # Vertical Layout
self.setLayout(self.layout)
self.titleList = QtGui.QListWidget()
self.label = QtGui.QLabel('Here is my list:')
self.layout.addWidget(self.label)
self.layout.addWidget(self.titleList)
self.titleList.addItem(QtGui.QListWidgetItem('Title 1'))
self.titleList.addItem(QtGui.QListWidgetItem('Title 2'))
self.titleList.itemDoubleClicked.connect(self.onClicked)
def onClicked(self, item):
## Just test parameters and signal emited
self.TitleClicked.emit([item.text(), item.text()+item.text()])
class WidgetTwo(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.title = QtGui.QLabel('Title : ---')
self.summary = QtGui.QLabel('Summary : ---')
self.link = QtGui.QLabel('Link : ---')
self.layout.addWidget(self.title)
self.layout.addWidget(self.summary)
self.layout.addWidget(self.link)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Inside the code, there are comments to help you understand why I did to build an organized GUI. There is also an example of a Signal being used to connect the action of itemDoubleClicked from the first widget to the second one. Here is how the MainWindow looks:
It is not very clear how the layouts work just from seeing the result, so I did a little paint over to a better understanding:
The blue box is the vertical layout (QVBoxLayout) and the red one is the horizontal layout (QHBoxLayout). Inside the blue layout, are located the red layout (above) and the exit button (below); and inside the red layout, are located the widget_1 (left) and the widget_2 (right).
Other Solution
An "easier" solution will be building the widgets inside the MainWindow instead of creating separate classes. With this you will avoid the use of signals, but the code will become a little more confusing because all the code will be cramped in one class.
I am trying to get font size of QLabel that the text fill entire QLabel's rectangle.I try to use QFontMetrics to get, but QFontMetrics can't get font size by gived rectangle?
The example:
The GUI may stuck while resize the window.
class Label(QLabel):
def __init__(self):
super().__init__()
self.resize(400, 300)
font = self.calculate_font()
self.setFont(font)
self.setText('PASS')
def calculate_font(self):
for i in range(400):
fm = QFontMetrics( QFont('Helvetica', i) )
fmSize = fm.boundingRect(self.geometry(), Qt.AlignCenter, 'PASS').size()
print(fm.boundingRect(self.geometry(), Qt.AlignCenter, 'PASS'), self.size())
#need font height equal label height
if fmSize.height() > self.size().height():
return QFont('Helvetica', i)
def resizeEvent(self, event):
font = self.calculate_font()
self.setFont(font)
app = QApplication([])
demo = Label()
demo.show()
app.exec()
Don't do it
There are dozens of reasons for which what you want to achieve is simply wrong.
The most important one is that dealing with text drawing and its size is not an easy task; also, Qt uses the label contents to tell the window layout about the size it could have, the size it wants to have and, most importantly, the minimum size it should have; all this is very important to the GUI, as it will be taken into account in order to correctly resize all other elements of your interface.
Finally, all those factors are based on the text of the label and its formatting, which might depend on the text contents and the fact that the text might be "rich text" (including multiple font size and weight).
If you really are conscious about the concepts explained above, here are 4 possible implementations. All of them partially support rich text (font weight, text color, etc, but not real text alignment).
Resizing font label
While subclassing a QLabel might seem the simplest approach, it actually isn't, as it is a widget much more complex than it seems (as I wrote before, dealing with text widgets is not an easy task)
The most important downside of this method is that it is very slow, since it has to carefully compute the font size at each resize. While some improvement might be achieved with a better implementation, I wouldn't suggest this method anyway.
class ResizeFontLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.paintFont = self.font()
def updateFont(self):
doc = QTextDocument()
if self.textFormat() == Qt.RichText or self.textFormat() == Qt.AutoText and Qt.mightBeRichText(self.text()):
doc.setHtml(self.text())
else:
doc.setPlainText(self.text())
frame = doc.rootFrame().frameFormat()
frame.setMargin(0)
doc.rootFrame().setFrameFormat(frame)
doc.setDefaultFont(self.paintFont)
width = self.width()
height = self.height()
if doc.size().width() > width or doc.size().height() > height:
while doc.size().width() > width or doc.size().height() > height:
self.paintFont.setPointSizeF(self.paintFont.pointSizeF() - .1)
doc.setDefaultFont(self.paintFont)
elif doc.size().width() < width and doc.size().height() < height:
while doc.size().width() < width and doc.size().height() < height:
self.paintFont.setPointSizeF(self.paintFont.pointSizeF() + .1)
doc.setDefaultFont(self.paintFont)
def resizeEvent(self, event):
self.updateFont()
def paintEvent(self, event):
doc = QTextDocument()
if self.textFormat() == Qt.RichText or self.textFormat() == Qt.AutoText and Qt.mightBeRichText(self.text()):
doc.setHtml(self.text())
else:
doc.setPlainText(self.text())
frame = doc.rootFrame().frameFormat()
frame.setMargin(0)
doc.rootFrame().setFrameFormat(frame)
doc.setDefaultFont(self.paintFont)
qp = QPainter(self)
doc.drawContents(qp, QRectF(self.rect()))
QLabels internally use a QTextDocument for both painting and sizing. The reason of the setMargin is due to the fact that a QTextDocument has some margin by default, and that's not used in labels.
Notes:
be careful about the different or/and in the updateFont() method. Their logic is very important
this method is slow
it doesn't support text alignment (at least with this basic implementation)
Painting based font label
This method is a simplification of the one above. It doesn't compute the font size, but just paints the contents scaled to the size.
class PaintLabel(QLabel):
def paintEvent(self, event):
doc = QTextDocument()
if self.textFormat() == Qt.RichText or self.textFormat() == Qt.AutoText and Qt.mightBeRichText(self.text()):
doc.setHtml(self.text())
else:
doc.setPlainText(self.text())
frame = doc.rootFrame().frameFormat()
frame.setMargin(0)
doc.rootFrame().setFrameFormat(frame)
scale = min(self.width() / doc.size().width(), self.height() / doc.size().height())
qp = QPainter(self)
qp.scale(scale, scale)
doc.drawContents(qp, QRectF(self.rect()))
Notes:
it's faster than the first method
it doesn't support alignment
since the scaling doesn't take into account the font size, the text will not be as big as it could be (that's due to the fact that a QTextDocument can have multiple "text blocks", and computing them at each paintEvent would make this really complex and slow
Graphics view label
This is a completely different approach, as it uses the Graphics View Framework.
The trick is to use a single QGraphicsTextItem in the scene, and let the view take care about the resizing/alignment.
class GraphicsLabel(QGraphicsView):
def __init__(self, text=''):
super().__init__()
# graphics view usually have a background and a frame around them,
# let's remove both of them
self.setFrameShape(0)
self.setStyleSheet('background: transparent;')
# as most QAbstractScrollAreas, views have a default minimum size hint
# that makes them "bigger" whenever they're shown; let's ignore that
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
scene = QGraphicsScene(self)
self.setScene(scene)
self.textItem = scene.addText('')
self.setText(text)
def minimumSizeHint(self):
# this is related to the minimum size hint specified above
font = self.font()
font.setPointSize(1)
return QFontMetrics(font).boundingRect(self.textItem.toPlainText()).size()
def setText(self, text):
font = self.font()
font.setPointSize(1)
self.setMinimumSize(QFontMetrics(font).boundingRect(text).size())
if Qt.mightBeRichText(text):
self.textItem.setHtml(text)
else:
self.textItem.setPlainText(text)
doc = self.textItem.document()
frame = self.textItem.document().rootFrame().frameFormat()
if frame.margin():
frame.setMargin(0)
doc.rootFrame().setFrameFormat(frame)
self.textItem.setDocument(doc)
def text(self):
# provide a basic interface similar to a QLabel
return self.textItem.toPlainText()
def resizeEvent(self, event):
# the base class implementation is always required for QAbstractScrollArea
# descendants; then we resize its contents to fit its size.
super().resizeEvent(event)
self.fitInView(self.textItem, Qt.KeepAspectRatio)
Notes:
it does support alignment
there's no "optimal" minimum size (the readability of the text is based on the font, and we can't do anything about that)
there's no "optimal" size hint, so the widget will be resized without any "complaints" about its text contents: if the label has very long text, that text will just be very, very small.
basic QWidget styling (through QWidget.setStyleSheet) is not supported
Graphics view QLabel widget
This method is very similar to the one above, but instead of creating a simple "text item", it adds an actual QLabel to the graphics scene.
class GraphicsLabelWidget(QGraphicsView):
def __init__(self, text=''):
super().__init__()
self.setFrameShape(0)
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.setStyleSheet('background: transparent;')
scene = QGraphicsScene(self)
self.setScene(scene)
self.label = QLabel(text)
self.labelItem = scene.addWidget(self.label)
self.label.setStyleSheet(self.styleSheet())
self.setText(text)
def minimumSizeHint(self):
font = self.font()
font.setPointSize(1)
doc = QTextDocument()
if Qt.mightBeRichText(self.label.text()):
doc.setHtml(self.label.text())
else:
doc.setPlainText(self.label.text())
return QFontMetrics(font).boundingRect(self.label.text()).size()
def setText(self, text):
font = self.font()
font.setPointSize(1)
self.setMinimumSize(QFontMetrics(font).boundingRect(text).size())
self.label.setText(text)
def text(self):
return self.label.toPlainText()
def resizeEvent(self, event):
super().resizeEvent(event)
self.fitInView(self.labelItem, Qt.KeepAspectRatio)
Notes:
slightly better than the basic addText graphics implementation; at the same time, it's also slightly slower
better support for stylesheets (but they should be applied to the actual child label)
Test example:
Provided just for commodity (add the classes above to see it in action).
class Demo(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
testText = 'PASS <b>bold</b><br/><i>new italic line</i><br/>{}'
resizeLabel = ResizeFontLabel(testText.format('resize mode'))
layout.addWidget(resizeLabel)
resizeLabel.setAlignment(Qt.AlignRight|Qt.AlignBottom)
paintLabel = PaintLabel(testText.format('paint mode'))
layout.addWidget(paintLabel)
paintLabel.setAlignment(Qt.AlignRight|Qt.AlignBottom)
graphicsLabel = GraphicsLabel(testText.format('graphicsview mode'))
layout.addWidget(graphicsLabel)
graphicsLabel.setAlignment(Qt.AlignRight|Qt.AlignBottom)
graphicsLabelWidget = GraphicsLabelWidget(testText.format('graphicsview mode'))
layout.addWidget(graphicsLabelWidget)
graphicsLabelWidget.setAlignment(Qt.AlignRight|Qt.AlignBottom)
graphicsLabelWidget.label.setStyleSheet('QLabel {background: green;}')
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
demo = Demo()
demo.show()
app.exec()
Hi is there a way to resize one widget before another in a layout? For example, when I resize the window, I want one of the widgets to resize to zero first before resizing the other widget.
Here is what I have so far:
from PySide2 import QtCore, QtWidgets, QtGui
class TestWindow(QtWidgets.QMainWindow):
def __init__(self):
super(TestWindow, self).__init__()
wgt = QtWidgets.QWidget(self)
mainLayout = QtWidgets.QHBoxLayout()
wgt.setLayout(mainLayout)
self.setWindowTitle("Test")
l = QtWidgets.QFrame()
r = QtWidgets.QFrame()
l.setStyleSheet("background-color: blue;")
r.setStyleSheet("background-color: green;")
mainLayout.addWidget(l)
mainLayout.addWidget(r)
self.setCentralWidget(wgt)
app = QtWidgets.QApplication()
x = TestWindow()
x.show()
app.exec_()
Here are some pictures showing what I want:
Green disappears first, then blue
So in this example, I want the green box to get smaller first, before the blue one does when I resize the main window. How do I achieve this in QT?
I found a workaround for this. I decided to use a splitter for this solution.
class TitleSplitter(QtWidgets.QSplitter):
def __init__(self):
super(TitleSplitter, self).__init__()
self.setStyleSheet("::handle {background-color: transparent}")
self.setHandleWidth(0)
def resizeEvent(self, event):
""" Restrain the size """
if self.count() > 1:
w = self.widget(0).sizeHint().width()
self.setSizes([w, self.width()-w])
return super(TitleSplitter, self).resizeEvent(event)
def addWidget(self, *args, **kwargs):
""" Hide splitters when widgets added """
super(TitleSplitter, self).addWidget(*args, **kwargs)
self.hideHandles()
def hideHandles(self):
""" Hide our splitters """
for i in range(self.count()):
handle = self.handle(i)
handle.setEnabled(False)
handle.setCursor(QtCore.Qt.ArrowCursor)
handle.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
Usage:
split = TitleSplitter()
l = QtWidgets.QFrame()
r = QtWidgets.QFrame()
l.setStyleSheet("background-color: blue;")
r.setStyleSheet("background-color: green;")
split.addWidget(l)
split.addWidget(r)
It only works if you have 2 widgets added. Ideally I would probably use a layout for this, but this works well enough for me.
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:
I'm trying to display an image in pyqt for my coursework. I'm attempting this in the Handle Question sub routine. here's a sample of it
class IntegrationQuestions(QtGui.QMainWindow):
def __init__(self, parent = None):
from equation import IntQuestion, IntAnswer
QtGui.QDialog.__init__(self, parent)
self.setWindowTitle('Simple Integration')
self.setMinimumSize(265,400)
self.lbl1 = QtGui.QLabel("Integrate the equation below",self)
self.lbl1.move(0,0)
self.lbl1.resize(200,20)
self.lbl2 = QtGui.QLabel(pretty(IntQuestion[0], use_unicode = False), self)
self.lbl2.resize(200, 80)
self.lbl2.move(30,30)
self.lbl3 = QtGui.QLabel("Sketch pad",self)
self.lbl3.move(0,120)
self.SketchPad = QtGui.QLineEdit(self)
self.SketchPad.resize(250,150)
self.SketchPad.move(0,150)
self.lbl4 = QtGui.QLabel("Answer",self)
self.lbl4.move(0,300)
self.Answer = QtGui.QLineEdit(self)
self.Answer.move(0,330)
self.Answer.resize(250,20)
self.next_question.clicked.connect(self.HandleQuestion)
this is where I'm attempting to add in a question
def HandleQuestion(self):
pic = QtGui.QLabel(self)
pic.setPixmap(QtGui.QPixmap("Q107.png"))
self.lbl3.move(0,190)
self.SketchPad.resize(250,80)
self.SketchPad.move(0,220)
You initialized everything properly, however you never set the label to be shown.
def HandleQuestion(self):
pic = QtGui.QLabel(self)
pic.setPixmap(QtGui.QPixmap("Q107.png"))
pic.show() # You were missing this.
self.lbl3.move(0,190)
self.SketchPad.resize(250,80)
self.SketchPad.move(0,220)