Fit QGraphisItem in view - python

Is a method to fit any image in view (that I import in QPixmap) and keep aspect ratio>. I try many solution but non of those works.
Also I don't not sure what I need to fit?
QGraphicsScene in QGraphicsView? Or QPixmap in QGraphicsView?
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
scene = QtWidgets.QGraphicsScene()
self.setScene(scene)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
photo = QtGui.QPixmap("image.jpg")
w.scene().addPixmap(photo)
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

You have to use the fitInView() method of QGraphicsView in the resizeEvent() method of QGraphicsView:
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
self.m_pixmap_item = self.scene().addPixmap(QtGui.QPixmap())
def setPixmap(self, pixmap):
self.m_pixmap_item.setPixmap(pixmap)
def resizeEvent(self, event):
if not self.m_pixmap_item.pixmap().isNull():
self.fitInView(self.m_pixmap_item, QtCore.Qt.KeepAspectRatio)
super(GraphicsView, self).resizeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
photo = QtGui.QPixmap("image.jpg")
w.setPixmap(photo)
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

Related

Python Pyqt5 QDateEdit Get Date String

I'm trying to build a date printer using Pyqt5 QDateEdit. I can popup the calendar, but I want to write the clicked date's string in the console (or in a label in window). I tried print(self.calendarWidget().document().toPlainText()) or print(self.calendarWidget().currentText()) but it didn't work.
I use this code;
from PyQt5 import QtCore, QtWidgets
class DateEdit(QtWidgets.QDateEdit):
popupSignal = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(DateEdit, self).__init__(parent)
self.setCalendarPopup(True)
self.calendarWidget().installEventFilter(self)
def eventFilter(self, obj, event):
if self.calendarWidget() is obj and event.type() == QtCore.QEvent.Show:
self.popupSignal.emit()
return super(DateEdit, self).eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = DateEdit()
w.popupSignal.connect(lambda: print("popup"))
w.show()
sys.exit(app.exec_())
What is its syntax? I didn't find enough documentation for it. Can you help please?
EDIT: The answer
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import *
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.dateEdit = QDateEdit(self)
self.lbl = QLabel()
self.dateEdit.setMaximumDate(QtCore.QDate(7999, 12, 28))
self.dateEdit.setMaximumTime(QtCore.QTime(23, 59, 59))
self.dateEdit.setCalendarPopup(True)
layout = QGridLayout()
layout.addWidget(self.dateEdit)
layout.addWidget(self.lbl)
self.setLayout(layout)
self.dateEdit.dateChanged.connect(self.onDateChanged)
def onDateChanged(self, qDate):
print('{0}/{1}/{2}'.format(qDate.day(), qDate.month(), qDate.year()))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())

Embed QGraphics in widget

I have a main widget inside a window who contains a lot of widgets. How can I insert a QGraphics view and a QGraphicsScene in that widget? I have not found a direct insertion method, so I am trying using a wrapper, in this case a box layout but it is not a good solution. The QGraphicsScene stands out from the layout limits.
Code:
class UiVentana(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedSize(1500, 1015)
widget_central = QtWidgets.QWidget(self)
wrapper = QtWidgets.QHBoxLayout(widget_central)
scene = QtWidgets.QGraphicsScene(wrapper)
vista = QtWidgets.QGraphicsView(scene)
wrapper.addWidget(vista)
self.diedrico = Diedrico() # This is a class who draw things, not relevant
self.diedrico.setFixedSize(2000, 2000)
scene.addWidget(self.diedrico)
self.setCentralWidget(widget_central)
I would like to get this result:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QPen, QColor
import sys
class Diedrico(QWidget):
def __init__(self, parent):
super().__init__(parent)
def paintEvent(self, event):
qp = QPainter(self)
qp.setPen(QPen(QColor(Qt.black), 5))
qp.drawRect(500, 500, 1000, 1000)
class UiVentana(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(UiVentana, self).__init__(parent)
self.resize(520, 520)
self.widget_central = QtWidgets.QWidget(self)
scrol = QtWidgets.QScrollArea(self.widget_central)
scrol.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scrol.setGeometry(QtCore.QRect(30, 30, 500, 500))
scrol.setWidgetResizable(False)
contenido = QtWidgets.QWidget()
contenido.setGeometry(QtCore.QRect(0, 0, 2000, 2000))
scrol.setWidget(contenido)
self.Diedrico = Diedrico(contenido)
self.Diedrico.setGeometry(QtCore.QRect(0, 0, 2000, 2000))
self.setCentralWidget(self.widget_central)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
ui = UiVentana()
ui.show()
sys.exit(app.exec_())
But using QGraphics instead of a scroll area
The QGraphicsProxyWidget that is created using the widget takes into account the minimum size of the widget to set the boundingRect, and the QGraphicsScene uses the boundingRect to set the initial scene rect.
from PyQt5 import QtCore, QtGui, QtWidgets
class Diedrico(QtWidgets.QWidget):
def paintEvent(self, event):
qp = QtGui.QPainter(self)
pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.black), 5)
qp.setPen(pen)
qp.drawRect(500, 500, 1000, 1000)
def minimumSizeHint(self):
return QtCore.QSize(2000, 2000)
class UiVentana(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(UiVentana, self).__init__(parent)
self.resize(520, 520)
widget_central = QtWidgets.QWidget()
self.setCentralWidget(widget_central)
lay = QtWidgets.QVBoxLayout(widget_central)
scene = QtWidgets.QGraphicsScene(self)
view = QtWidgets.QGraphicsView(scene)
diedrico = Diedrico()
scene.addWidget(diedrico)
lay.addWidget(view)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ui = UiVentana()
ui.show()
sys.exit(app.exec_())

QCalendarWidget Renders Small

I am trying to use the QCalendarWidget but it doesn't render in the user interface as expected. The examples that I have seen show a calendar picker like object, but in my case I get a quite small rendering of a field. Here's what it looks like in the UI:
This is my first time using it so I am not sure if I am missing a step. Any thoughts on what I could be doing incorrectly? Here is the complete code being used:
from PyQt5.QtWidgets import QMainWindow, QCalendarWidget, QLabel
from PyQt5 import QtCore, QtWidgets, QtGui
import sys
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
cal = QCalendarWidget(self)
cal.setGridVisible(True)
cal.move(20, 20)
cal.clicked[QtCore.QDate].connect(self.showDate)
self.lbl = QLabel(self)
date = cal.selectedDate()
self.lbl.setText(date.toString())
self.lbl.move(20, 200)
self.setGeometry(100,100,300,300)
self.setWindowTitle('Calendar')
self.show()
def showDate(self, date):
self.lbl.setText(date.toString())
def main():
app = QtWidgets.QApplication(sys.argv)
mainWin = Example()
mainWin.show()
sys.exit( app.exec_() )
if __name__ == '__main__':
main()
Use a layout, for example a QVBoxLayout, in the centralWidget of QMainWindow:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
cal = QtWidgets.QCalendarWidget(gridVisible=True)
cal.clicked.connect(self.showDate)
self.lbl = QtWidgets.QLabel()
date = cal.selectedDate()
self.lbl.setText(date.toString())
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(cal)
lay.addWidget(self.lbl)
self.setGeometry(100, 100, 300, 300)
self.setWindowTitle("Calendar")
#QtCore.pyqtSlot(QtCore.QDate)
def showDate(self, date):
self.lbl.setText(date.toString())
def main():
app = QtWidgets.QApplication(sys.argv)
mainWin = Example()
mainWin.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

QRubberBand.geometry().intersects(???) How to find intersecting images in QGraphicsScene?

I found few codes which demonstrates intersects, but it was mainly buttons. Something like this:
for child in self.findChildren(QPushButton):
if rect.intersects(child.geometry( )):
selected.append(child)
But how do you find images intersecting in your GraphicsScene with "Marquee" selection(QRubberBand)? I tried replacing findChildren(QPushButton) with QPixmap, QGraphicsScene, QGraphicsPixmapItem it always giving me back empty list.
If you are using the QRubberBand that has the QGraphicsView you have to use the rubberBandChanged signal and next to the items method you get the items that are below the QRubberBand.
from PyQt5 import QtCore, QtGui, QtWidgets
import random
def create_pixmap():
pixmap = QtGui.QPixmap(100, 100)
pixmap.fill(QtGui.QColor(*random.sample(range(255), 3)))
return pixmap
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setScene(QtWidgets.QGraphicsScene(self))
self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)
self.rubberBandChanged.connect(self.on_rubberBandChanged)
for _ in range(5):
item = QtWidgets.QGraphicsPixmapItem(create_pixmap())
item.setPos(*random.sample(range(500), 2))
self.scene().addItem(item)
#QtCore.pyqtSlot("QRect", "QPointF", "QPointF")
def on_rubberBandChanged(
self, rubberBandRect, fromScenePoint, toScenePoint
):
r = QtCore.QRectF(fromScenePoint, toScenePoint)
selected = self.items(rubberBandRect)
print(selected)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
If you are using another QRubberBand the logic is similar to that since you must use the items() method of QGraphicsView
from PyQt5 import QtCore, QtGui, QtWidgets
import random
def create_pixmap():
pixmap = QtGui.QPixmap(100, 100)
pixmap.fill(QtGui.QColor(*random.sample(range(255), 3)))
return pixmap
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setScene(QtWidgets.QGraphicsScene(self))
self._rubberBand = QtWidgets.QRubberBand(
QtWidgets.QRubberBand.Rectangle, self.viewport()
)
self._rubberBand.hide()
self._origin = QtCore.QPoint()
for _ in range(5):
item = QtWidgets.QGraphicsPixmapItem(create_pixmap())
item.setPos(*random.sample(range(500), 2))
self.scene().addItem(item)
def mousePressEvent(self, event):
self._origin = event.pos()
self._rubberBand.setGeometry(QtCore.QRect(self._origin, QtCore.QSize()))
self._rubberBand.show()
super(GraphicsView, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
self._rubberBand.setGeometry(
QtCore.QRect(self._origin, event.pos()).normalized()
)
def mouseReleaseEvent(self, event):
self._rubberBand.setGeometry(
QtCore.QRect(self._origin, event.pos()).normalized()
)
selected = self.items(self._rubberBand.geometry())
print(selected)
self._rubberBand.hide()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

Painter Shape over QIcon in PySide

How can I append a painted rectangle to a QIcon. The final returned result has to be a qicon because I'm using this on a control which expects a qicon.
Before:
After:
import os, sys
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.resize(600,400)
self.btn = QtGui.QPushButton()
self.btn.setFixedSize(128,128)
icon = QtGui.QIcon('thumb.jpg')
self.btn.setIconSize(icon.availableSizes()[0])
self.btn.setIcon(icon)
lay = QtGui.QVBoxLayout()
lay.addWidget(self.btn)
self.setLayout(lay)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You have to read the image as QPixmap, use QPainter to modify the QPixmap by adding the rectangle and finally use the QPixmap to create the QIcon
import sys
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.resize(600,400)
lay = QtGui.QHBoxLayout(self)
pixmap = QtGui.QPixmap('thumb.jpg')
painter = QtGui.QPainter(pixmap)
painter.fillRect(QtCore.QRect(20, 20, 40, 40), QtGui.QColor("red"))
painter.end()
for icon in (QtGui.QIcon('thumb.jpg'), QtGui.QIcon(pixmap)):
btn = QtGui.QPushButton()
btn.setFixedSize(128,128)
btn.setIconSize(icon.availableSizes()[0])
btn.setIcon(icon)
lay.addWidget(btn)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Categories