New to PyQt5... Here is a very basic question.
I would like to add an image inside the layout of a widget. This widget is the Main Window / root widget of my application. I use the following code, but I get an error message.
import sys
from PyQt5.QtGui import QImage
from PyQt5.QtWidgets import *
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(300,300,300,220)
self.setWindowTitle("Hello !")
oImage = QImage("backgound.png")
oLayout = QVBoxLayout()
oLayout.addWidget(oImage)
self.setLayout(oLayout)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
oMainwindow = MainWindow()
sys.exit(app.exec_())
TypeError: QBoxLayout.addWidget(QWidget, int stretch=0, Qt.Alignment alignment=0): argument 1 has unexpected type 'QImage'
Apparently a QLayoutWidget does not accept a QImage as an input. Is there a workaround to have an image appear as a brackground in a QWidget ?
The QVBoxLayout class lines up widgets vertically.
documentation QVBoxLayout
QImage is no widget.
on many widgets e.g. QmainWindow, QLabel you can use
widget.setStyleSheet(„ background-image: url(backgound.png);“)
on my machine this doesn't work with QWidget. In this case you can use the following rewrite of your code:
import sys
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QImage, QPalette, QBrush
from PyQt5.QtWidgets import *
class MainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.setGeometry(100,100,300,200)
oImage = QImage("test.png")
sImage = oImage.scaled(QSize(300,200)) # resize Image to widgets size
palette = QPalette()
palette.setBrush(QPalette.Window, QBrush(sImage))
self.setPalette(palette)
self.label = QLabel('Test', self) # test, if it's really backgroundimage
self.label.setGeometry(50,50,200,50)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
oMainwindow = MainWindow()
sys.exit(app.exec_())
Related
I am trying to show the icon in the window bar and this is not simply working. I tried several solutions but still it doesn't work. Any solution for this code?
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.browser = QWebEngineView()
self.browser.setUrl(QUrl('http://gmail.com'))
self.setCentralWidget(self.browser)
self.showMaximized()
self.setWindowTitle('G')
self.setWindowIcon(QIcon(os.path.join('cil.png')))
self.show()
app = QApplication(sys.argv)
window = MainWindow()
app.exec_()
Try putting the icon like this
icon = QIcon()
icon.addPixmap(QtGui.QPixmap()) #add full path or respective path to the icon image inside QtGui.QPixmap()
self.setWindowIcon(icon)
so I'm currently working on a little project but I have an issue and all what I've tried did not work. I have 2 files :
Page1test :
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel
import sys
from page2test import Page2
class Page1(QWidget):
def __init__(self):
super(Page1, self).__init__()
self.setWindowTitle("Page 1")
label1 = QLabel(self)
label1.setText("\n PAGE 1")
self.btn_inMyApp = QPushButton ('Next page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage1_OpenPage2)
self.show()
def closePage1_OpenPage2(self):
self.Open = Page2()
self.Open.showMaximized()
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Page1()
window.showMaximized()
sys.exit(app.exec_())
And page2test :
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel
from Page1test import Page1
class Page2(QWidget):
def __init__(self):
super(Page2, self).__init__()
self.setWindowTitle("Test window principale")
label1 = QLabel(self)
label1.setText("\n Page2")
self.btn_inMyApp = QPushButton ('previous Page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage2_OpenPage1)
self.show()
def closePage2_OpenPage1(self):
self.Open = Page1()
self.Open.showMaximized()
self.close()
I run the code of Page1test : empty window with just a Qpushbutton "Next Page", goal : we click on it and it open Page 2 (and close Page 1). And, when we are in Page 2, we have A Qpushbutton with "Previous Page" and when we click on it, it opens page 1, and close Page 2. Like a loop.
But, when I run the code, it returns an error :
cannot import name 'Page2' from partially initialized module 'page2test' (most likely due to a circular import)
and I have no idea how to fix it...
If someone had an idea, it would be really helpful.
So, I've finally found the solution, that was not so difficult in the end. Here it is (if it can help someone) :
Instead of making 2 files, I've done just 1 file. Here is the code :
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel, QMainWindow
import sys
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.setWindowTitle("Page 1")
label1 = QLabel(self)
label1.setText("\n PAGE 1")
self.btn_inMyApp = QPushButton ('Page suivante', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage1_OpenPage2)
self.show()
def btn1_onClicked(self):
pass
def closePage1_OpenPage2(self):
self.Open = NewApp()
self.Open.showMaximized()
self.close()
class NewApp(QMainWindow):
def __init__(self):
super(NewApp, self).__init__()
self.setWindowTitle("Test window principale")
label1 = QLabel(self)
label1.setText("\n Page2")
self.btn_inMyApp = QPushButton ('previous Page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage2_OpenPage1)
self.show()
def closePage2_OpenPage1(self):
self.Open = MyApp()
self.Open.showMaximized()
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.showMaximized()
sys.exit(app.exec_())
```
I'm using the below code to try and capture double clicks within the main window"
import sys
from PySide6 import QtCore
from PySide6.QtWidgets import (
QApplication,
QGridLayout,
QMainWindow,
QSplitter,
QTreeView,
QWidget,
)
from PySide6.QtWebEngineWidgets import QWebEngineView
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.windowLayout = QGridLayout()
self.splitter = QSplitter()
self.webView = QWebEngineView()
self.webView.setUrl(QtCore.QUrl("http://127.0.0.1:8080"))
self.tree = QTreeView()
self.splitter.addWidget(self.webView)
self.splitter.addWidget(self.tree)
self.windowLayout.addWidget(self.splitter)
self.mainWidget = QWidget()
self.mainWidget.setLayout(self.windowLayout)
self.setCentralWidget(self.mainWidget)
def mouseDoubleClickEvent(self, e):
print('test')
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.resize(1500, 1000)
window.show()
app.exec()
And I get the following console output:
qt.pointer.dispatch: delivering touch release to same window QWindow(0x0) not QWidgetWindow(0x600003bb8e40, name="MainWindowClassWindow")
qt.pointer.dispatch: skipping QEventPoint(id=1 ts=0 pos=0,0 scn=749.346,451.159 gbl=749.346,451.159 Released ellipse=(1x1 ∡ 0) vel=0,0 press=-749.346,-451.159 last=-749.346,-451.159 Δ 749.346,451.159) : no target window
however, when I comment out self.setCentralWidget(self.mainWidget) I obviously don't see anything, but the double click triggers. Any suggestions?
EDIT: update to min repro, also note that clicking anywhere not inside the QWebEngineView correctly results in mouseDoubleClickEvent triggering. However, the above error results when I click in the QWebEngineView, and nothing happens when I click inside the QTreeView
As per musicamante's very useful comments (see original post), the solution I ended up using was
...
self.tree.doubleClicked.connect(self.treeDoubleClicked)
...
def treeDoubleClicked(self, index):
self.selectedFilepath = index.model().filePath(index)
I can't find good explanations about the different usage of QMainWindow vs. QWidget in PyQt5 (and Qt in general, I guess). From what I've read, QMainWindow inherits from QWidget, so should be able to do everything QWidget can and more. But when I try to convert an example I've found from QWidget into QMainWindow, the layout gets screwed up.
The example I'm trying to work off is from https://www.tutorialspoint.com/pyqt/pyqt_qstackedwidget.htm. (My GUI will have a StackedWidget as central widget, with a sidepanel for navigation, so getting this example to work in a QMainWidget would be a great basis for my own code.)
PyQT5-converted and slightly shortened version:
#!/usr/bin/env python3
import sys
from PyQt5.QtWidgets import (QApplication, QFormLayout, QLabel, QRadioButton, QCheckBox,
QListWidget, QStackedWidget, QLineEdit,
QHBoxLayout, QGridLayout
)
from PyQt5.Qt import QWidget, QMainWindow
class StackedExample(QMainWindow):
def __init__(self):
super(stackedExample, self).__init__()
self.leftlist = QListWidget ()
self.leftlist.insertItem (0, 'Contact' )
self.leftlist.insertItem (1, 'Personal' )
self.stack1 = QWidget()
self.stack2 = QWidget()
self.stack1UI()
self.stack2UI()
self.Stack = QStackedWidget (self)
self.Stack.addWidget (self.stack1)
self.Stack.addWidget (self.stack2)
grid = QGridLayout()
self.setLayout(grid)
grid.addWidget(self.leftlist,0,0)
grid.addWidget(self.Stack,0,1)
self.leftlist.currentRowChanged.connect(self.display)
self.resize(300,100)
self.show()
def stack1UI(self):
layout = QFormLayout()
layout.addRow("Name",QLineEdit())
layout.addRow("Address",QLineEdit())
self.stack1.setLayout(layout)
def stack2UI(self):
layout = QFormLayout()
sex = QHBoxLayout()
sex.addWidget(QRadioButton("Male"))
sex.addWidget(QRadioButton("Female"))
layout.addRow(QLabel("Sex"),sex)
layout.addRow("Date of Birth",QLineEdit())
self.stack2.setLayout(layout)
def display(self,i):
self.Stack.setCurrentIndex(i)
def main():
app = QApplication(sys.argv)
ex = StackedExample()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This code worked fine while it was based on QWidget, but when it's based on QMainWidget (like in the above version), everything gets crammed into the upper left corner.
What changes are neccessary to show a layout that works for QWidget in a QMainWindow?
A QMainWindow must have a central widget to display correctly. You need to define a central widget and then add any layouts to it instead of the main window.
class StackedExample(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.leftlist = QListWidget()
self.leftlist.insertItem(0, 'Contact' )
self.leftlist.insertItem(1, 'Personal' )
self.central_widget = QWidget() # define central widget
self.setCentralWidget(self.central_widget) # set QMainWindow.centralWidget
self.stack1 = QWidget()
self.stack2 = QWidget()
self.stack1UI()
self.stack2UI()
self.Stack = QStackedWidget (self)
self.Stack.addWidget (self.stack1)
self.Stack.addWidget (self.stack2)
grid = QGridLayout()
self.centralWidget().setLayout(grid) # add the layout to the central widget
grid.addWidget(self.leftlist,0,0)
grid.addWidget(self.Stack,0,1)
self.leftlist.currentRowChanged.connect(self.display)
self.resize(300,100)
self.show()
There are also other areas besides centralWidget defined for a QMainWindow. Here is the documentation for QMainWindow. It explains this in more detail.
For past few days I was trying to solve the issue of widget movement. At some point I tried rewriting QComboBox classes with mouse signals but that did not work. As a work around I settled for parenting my widget to a QGraphicsWidget but once I try to add another item it does not display any more and I'm not sure what to do. Here is full test script:
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QApplication,QGraphicsItem, QGraphicsView, QGraphicsScene, QDesktopWidget, QCheckBox, QGroupBox, QPushButton, QGridLayout, QLabel, QLineEdit, QComboBox, QFont, QRadioButton, QButtonGroup, QWidget, QShortcut, QKeySequence, QIcon, QListView, QStandardItemModel, QStandardItem, QAction, QIntValidator, QListWidget, QProgressBar, QSpacerItem
from PyQt4.QtCore import QRect
from functools import partial
import sys
class node_GUI(QtGui.QWidget):
def __init__(self):
super(node_GUI, self).__init__()
class Main(QtGui.QMainWindow):
def __init__(self, *args):
super(Main, self).__init__(*args)#QtGui.QMainWindow.__init__(self)
self.init_defaults()
def init_defaults(self):
self.setGeometry(800,800,500,200)
self.lay_main = QGridLayout()
self.centralwidget = QtGui.QWidget()
self.centralwidget.setLayout(self.lay_main)
self.setCentralWidget(self.centralwidget)
btn_create_node = QPushButton("Create Node View")
btn_create_node.clicked.connect(self.create_node_view)
self.lay_main.addWidget(btn_create_node)
def showWindow(self,window):
window.show()
def printTest(self):
print "Start"
box = QGroupBox("subWidget")
box_btn = QPushButton("Test")
box_btn.clicked.connect(self.printTest)
le_edit = QLineEdit()
lay = QGridLayout()
box.setLayout(lay)
lay.addWidget(box_btn)
lay.addWidget(le_edit)
area = QtGui.QGraphicsWidget()
area.setMinimumSize(QtCore.QSizeF(400,300))
area.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
area.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
proxy = self.scene.addWidget(box)
proxy.setParentItem(area)
print "END"
def create_node_view(self):
print "creting node view"
window = node_GUI()
window.setGeometry(QRect(100, 100, 400, 200))
window.setWindowTitle("node ")
window.setObjectName("node")
show_window = QPushButton("Show Node Editor")
show_window.setObjectName("btn")
show_window.clicked.connect(partial(self.showWindow,window))
self.lay_main.addWidget(show_window)
box = QGroupBox("Widgets")
box_btn = QPushButton("Test")
box_btn.clicked.connect(self.printTest)
le_edit = QLineEdit()
lay = QGridLayout()
box.setLayout(lay)
lay.addWidget(box_btn)
lay.addWidget(le_edit)
area = QtGui.QGraphicsWidget()
area.setMinimumSize(QtCore.QSizeF(300,300))
area.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
area.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
area.setAutoFillBackground(True)
ecs = QtGui.QGraphicsEllipseItem()
ecs.setRect(QtCore.QRectF(79,79,79,79))
ecs.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
ecs.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
view = QGraphicsView()
self.scene = QGraphicsScene()
self.scene.addItem(area)
proxy = self.scene.addWidget(box)
proxy.setParentItem(area)
self.scene.addItem(ecs)
view.setScene(self.scene)
lay_window = QGridLayout()
window.setLayout(lay_window)
lay_window.addWidget(view)
def main():
app = QtGui.QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
When you click on Create Node View > Show Node Editor > Test button > a new GroupBox should appear but that does not work. Not sure why.
Right so I stopped using QGraphicsWidget() and instead I just use QGraphicsRectItem(ecs for example) once I did that change everything started to work as expected.