How can I get widget size which inside layout - python

I have a QLabel in QWidget's layout ,
I try to use sizeHint or geometry but it doesn't work.
how can I get QLabel actural width and height ?
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(689, 439)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
self.label.setSizePolicy(sizePolicy)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
self.label.setText(QtWidgets.QApplication.translate("Form", "TextLabel", None, -1))
import sys,os,asyncio
from PySide2 import QtWidgets
from PySide2.QtWidgets import (QApplication, QMainWindow, QMessageBox)
from qasync import QEventLoop, asyncSlot, asyncClose
from TestLB2 import Ui_Form
class LB(QtWidgets.QWidget, Ui_Form):
def __init__(self, *args, **kwargs):
super(LB, self).__init__(*args, **kwargs)
self.setupUi(self)
print(self.frameGeometry().width())
print(self.label.geometry().width())
print(self.label.sizeHint().width())
if __name__ == '__main__':
# mp.freeze_support()
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
w = LB()
w.show()
sys.exit(app.exec_())
with loop:
loop.run_forever()

For efficiency reasons, only the geometric properties are updated when necessary, in the case of layouts and widgets they are only updated when they are displayed, therefore you do not get the desired values. The solution is to obtain that information an instant after displaying it using a QTimer.
import asyncio
import os
import sys
from PySide2 import QtCore, QtWidgets
from qasync import QEventLoop, asyncSlot, asyncClose
from TestLB2 import Ui_Form
class LB(QtWidgets.QWidget, Ui_Form):
def __init__(self, *args, **kwargs):
super(LB, self).__init__(*args, **kwargs)
self.setupUi(self)
#
self.label.setStyleSheet("QLabel{background-color: red}")
QtCore.QTimer.singleShot(0, lambda: print(self.label.width()))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
w = LB()
w.show()
with loop:
loop.run_forever()

Related

How to set widget for vispy use

I know this question has been asked in a couple ways but I cannot figure it out on my specific use case. I used QT designer (pyQT 5.15) to create a layout and would like to use vispy as the display. After reading it seemed I had to set a widget but it still isn't clear to me how. This is what I have, and I am trying to have the simple example of changing the color from black to white via a timer. There are no errors but there is no visualization either.
Here is the GUI.ui converted to Python called GUI.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(702, 603)
self.vispy_widget = QtWidgets.QWidget(Dialog)
self.vispy_widget.setGeometry(QtCore.QRect(150, 20, 531, 531))
self.vispy_widget.setObjectName("vispy_widget")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(580, 560, 75, 23))
self.pushButton.setObjectName("pushButton")
self.horizontalScrollBar = QtWidgets.QScrollBar(Dialog)
self.horizontalScrollBar.setGeometry(QtCore.QRect(160, 560, 401, 20))
self.horizontalScrollBar.setOrientation(QtCore.Qt.Horizontal)
self.horizontalScrollBar.setObjectName("horizontalScrollBar")
self.horizontalSlider = QtWidgets.QSlider(Dialog)
self.horizontalSlider.setGeometry(QtCore.QRect(20, 60, 111, 16))
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
self.horizontalSlider.setObjectName("horizontalSlider")
self.hist_widget = QtWidgets.QWidget(Dialog)
self.hist_widget.setGeometry(QtCore.QRect(20, 90, 120, 80))
self.hist_widget.setObjectName("hist_widget")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton.setText(_translate("Dialog", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
```
Here is the app part:
import sys
from vispy import gloo, app
from gui import Ui_Dialog
from PyQt5 import QtWidgets
app.use_app('pyqt5')
class Canvas(app.Canvas):
def __init__(self, *args, **kwargs):
app.Canvas.__init__(self, *args, **kwargs)
self._timer = app.Timer('auto', connect=self.on_timer, start=True)
self.tick = 0
def on_draw(self, event):
gloo.clear(color=True)
def on_timer(self, event):
self.tick += 1 / 60.0
c = abs(math.sin(self.tick))
gloo.set_clear_color((c, c, c, 1))
self.update()
class myWindow(QtWidgets.QMainWindow):
def __init__(self):
super(myWindow, self).__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
canvas = Canvas()
self.ui.vispy_widget(canvas.native)
if __name__ == "__main__":
gui = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
app.run()
#sys.exit(app.exec_())
There are the following errors:
The self.ui.vispy_widget(canvas.native) command does not make sense, the idea is to use vispy_widget as a container for the native vispy widget that can be placed through a layout.
The choice of the .ui form is used to determine the base class, in your case you should use QDialog instead of QMainWindow.
If you already set the Ui_Dialog in the widget then it is unnecessary to implement the same in if __name__ == "__main__":.
You must import the math module.
import math
import sys
from vispy import gloo, app
from PyQt5 import QtWidgets
from gui import Ui_Dialog
app.use_app("pyqt5")
class Canvas(app.Canvas):
def __init__(self, *args, **kwargs):
app.Canvas.__init__(self, *args, **kwargs)
self._timer = app.Timer("auto", connect=self.on_timer, start=True)
self.tick = 0
def on_draw(self, event):
gloo.clear(color=True)
def on_timer(self, event):
self.tick += 1 / 60.0
c = abs(math.sin(self.tick))
gloo.set_clear_color((c, c, c, 1))
self.update()
class MyWindow(QtWidgets.QDialog):
def __init__(self):
super(MyWindow, self).__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.canvas = Canvas()
lay = QtWidgets.QVBoxLayout(self.ui.vispy_widget)
lay.addWidget(self.canvas.native)
if __name__ == "__main__":
gui = QtWidgets.QApplication(sys.argv)
w = MyWindow()
w.show()
app.run()

PyQt5 changing QlineEdit text automatically

i have a main window with a read-only QlineEdit that displays today date and a button that opens calendar widget window (from another module in the project) to choose another date ,the problem that when i choose another date the QlineEdit text in Gui do not change although the variable that stores the value changes successfully ,i searched a lot with no clue
before using QlineEdit i tried Qlabel but could not achieve the result also
here is the main window:
import sys
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit
from PyQt5 import QtCore, QtGui, QtWidgets
from cal_window import prev_day, today_str, UiCalWindow
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("My App")
self.setGeometry(50, 50, 800, 600)
self.label = QLineEdit(self)
self.label.setFont(QFont("Arial", 20))
self.label.setReadOnly(True)
self.label.setText(today_str)
self.setCentralWidget(self.label)
self.btn = QPushButton('open calender', self)
self.btn.move(50, 50)
self.btn.clicked.connect(self.choose_date)
def choose_date(self):
self.window = QtWidgets.QMainWindow()
self.ui = UiCalWindow()
self.ui.setupUi(self.window)
self.window.show()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
and here is the calendar sub-window:
from PyQt5 import QtCore, QtGui, QtWidgets, Qt
from datetime import date
today = date.today()
today_str = today.strftime("%Y-%m-%d")
prev_day = "2000-01-01"
class UiCalWindow(object):
def get_date(self, qDate):
global prev_day
self.day = '{0}-{1}-{2}'.format(qDate.year(), qDate.month(), qDate.day())
prev_day = self.day
print(prev_day)
def setupUi(self, cal_window):
cal_window.setObjectName("cal_window")
cal_window.setWindowModality(QtCore.Qt.ApplicationModal)
cal_window.resize(800, 600)
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
cal_window.setFont(font)
self.centralwidget = QtWidgets.QWidget(cal_window)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.calendarWidget.setFont(font)
self.calendarWidget.setLayoutDirection(QtCore.Qt.RightToLeft)
self.calendarWidget.setFirstDayOfWeek(QtCore.Qt.Monday)
self.calendarWidget.setGridVisible(True)
self.calendarWidget.setVerticalHeaderFormat(QtWidgets.QCalendarWidget.NoVerticalHeader)
self.calendarWidget.setObjectName("calendarWidget")
self.gridLayout.addWidget(self.calendarWidget, 0, 0, 1, 1)
self.calendarWidget.clicked.connect(self.get_date)
self.ok_dt_btn = QtWidgets.QPushButton(self.centralwidget)
self.ok_dt_btn.setMinimumSize(QtCore.QSize(0, 50))
self.ok_dt_btn.setObjectName("ok_dt_btn")
self.ok_dt_btn.clicked.connect(cal_window.close)
self.gridLayout.addWidget(self.ok_dt_btn, 1, 0, 1, 1)
cal_window.setCentralWidget(self.centralwidget)
self.retranslateUi(cal_window)
QtCore.QMetaObject.connectSlotsByName(cal_window)
def retranslateUi(self, cal_window):
_translate = QtCore.QCoreApplication.translate
cal_window.setWindowTitle(_translate("cal_window", "MainWindow"))
self.ok_dt_btn.setText(_translate("cal_window", "go"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
cal_window = QtWidgets.QMainWindow()
ui = UiCalWindow()
ui.setupUi(cal_window)
cal_window.show()
sys.exit(app.exec_())```
You have concept problems:
Do not modify the code generated by Qt Designer (it is recommended that you restore cal_window.py.
Do not use global variables, they are unnecessary and generate more problems than solutions.
That the variable "prev_day" is updated does not imply that the text displayed by the QLabel is updated, the QLabel copies the information and does not monitor the string.
The logic is to use the signal to update the text.
import sys
from PyQt5.QtCore import pyqtSignal, QDate
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit
from cal_window import UiCalWindow
class CalendarWindow(QMainWindow, UiCalWindow):
def __init__(self, parent=None):
super(CalendarWindow, self).__init__(parent)
self.setupUi(self)
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("My App")
self.setGeometry(50, 50, 800, 600)
self.label = QLineEdit(self)
self.label.setFont(QFont("Arial", 20))
self.label.setReadOnly(True)
self.setCentralWidget(self.label)
self.btn = QPushButton("open calender", self)
self.btn.move(50, 50)
self.cal = CalendarWindow()
self.cal.calendarWidget.clicked.connect(self.handle_date_clicked)
self.btn.clicked.connect(self.cal.show)
def handle_date_clicked(self, date):
self.label.setText(date.toString("yyyy-MM-dd"))
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

QGraphicsView wrong size at start

I have a problem, i have made a QGraphicsView with 2 rectangles inside. I wanted them to resize when i resize the Dialog so i rewrite a dialog class. It works but at start i have the wrong sized rectangle
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsEllipseItem
import sys
# Redéfinition de dialog pour utiliser resize event
class MyDialog (QtWidgets.QDialog) :
def resizeEvent(self, event):
print("resize")
#print(view.sceneRect())
view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio) ######## I DONT KNOW WHY THIS LINE MAKE THE VIEW TOO SMALL AT START
QtWidgets.QDialog.resizeEvent(self, event)
#view.fitInView(rectangle)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(556, 580)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.graphicsView = QtWidgets.QGraphicsView(Dialog)
self.graphicsView.setObjectName("graphicsView")
self.verticalLayout.addWidget(self.graphicsView)
global view
view = self.graphicsView
triangle = QtWidgets.QGraphicsRectItem(10,10,200,200)
rectangle = QtWidgets.QGraphicsRectItem(100,100,200,200)
global scene
scene = QtWidgets.QGraphicsScene()
scene.addItem(rectangle)
scene.addItem(triangle)
self.graphicsView.setScene(scene)
#self.graphicsView.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
#view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
self.graphicsView_2 = QtWidgets.QGraphicsView(Dialog)
self.graphicsView_2.setObjectName("graphicsView_2")
self.verticalLayout.addWidget(self.graphicsView_2)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = MyDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
When i start the QDialog it looks like this
And when i resize the window it looks like i wanted it to look like
Note: It is recommended not to modify the code generated by Qt Designer, so for my answer to work you must regenerate the file using pyuic5: pyuic5 your_file.ui -o gui.py -x.
So that the fitInView method uses some property that is not updated until it makes the QGraphicsView visible, so the solution is to verify that it is visible:
main.py
from PyQt5 import QtCore, QtGui, QtWidgets
from gui import Ui_Dialog
class MyDialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
triangle = QtWidgets.QGraphicsRectItem(10, 10, 200, 200)
rectangle = QtWidgets.QGraphicsRectItem(100, 100, 200, 200)
scene = QtWidgets.QGraphicsScene()
scene.addItem(rectangle)
scene.addItem(triangle)
self.graphicsView.setScene(scene)
def resizeEvent(self, event):
if self.isVisible():
self.graphicsView.fitInView(
self.graphicsView.scene().sceneRect(), QtCore.Qt.KeepAspectRatio
)
super().resizeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyDialog()
w.show()
sys.exit(app.exec_())

How draw Polygon from MouseEvents on top of Image in Qlabel

Using Python , PYQT5 I want to draw a Polygon on top a Image, which is in a Qlabel widget. I used a simple Qmainwindow with a label widget generated in QT designer (code is below).
I am aware that there are several informations out abaut drawing in a Qmainwindow like here:
PyQT5: How to interactively paint on image within QLabel Widget? - which has no solution within a Qlabel widget.
Draw over image in a QLabel with PyQt5 - marked solution is unclear because also painting on top of Qlabel is not solved
PYQT5 drawing line - paintevent on Qlabel is working, but not on top of the image
Painting in a QLabel with paintEvent - but also not solved to draw on top of an image.
Let me know, if you have a solution for this problem.
import sys
from PyQt5.QtCore import Qt
from PyQt5 import QtWidgets, uic, QtCore, QtGui
from PyQt5.QtGui import QPixmap, QPainter, QPolygon, QPen, QBrush
from PyQt5.QtCore import QPoint
from polygon_ui import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
pixmap = QPixmap("img.png")
self.label.setPixmap(pixmap)
self.label.mousePressEvent = self.getPixel
self.pol = []
def getPixel(self, event):
x = event.pos().x()
y = event.pos().y()
self.pol.append(QPoint(int(x),int(y)))
print(x,y, self.pol)
def paintEvent(self, event):
painter = QPainter(self)
#painter.drawPixmap(self.rect(), self.image)
painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
painter.setBrush(QBrush(Qt.red, Qt.VerPattern))
#points = QPolygon([ QPoint(10,10), QPoint(10,100),
# QPoint(100,10), QPoint(100,100)])
points = QPolygon(self.pol)
painter.drawPolygon(points)
def mouseMoveEvent(self, event):
pass
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
the code for polygon_ui is here - was simply generated by QT-Designer using Mainwindow + Qlabel:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(621, 641)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(10, 10, 600, 600))
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 621, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "TextLabel"))
If you want to add elements such as polygons, lines, circles, etc. on an image then do not complicate yourself with a QLabel since for example with your current code you are painting in the window that is below the QLabel so it will not be seen , a possible solution using with QLabel is to get the QPixmap and paint it on top.
A better alternative is to use the Qt Graphics Framework, where the image is set to a QGraphicsPixmapItem, and a polygon as a child of the QGraphicsPixmapItem as I show below:
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
self._pixmap_item = QtWidgets.QGraphicsPixmapItem()
scene.addItem(self.pixmap_item)
self._polygon_item = QtWidgets.QGraphicsPolygonItem(self.pixmap_item)
self.polygon_item.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
self.polygon_item.setBrush(QtGui.QBrush(QtCore.Qt.red, QtCore.Qt.VerPattern))
#property
def pixmap_item(self):
return self._pixmap_item
#property
def polygon_item(self):
return self._polygon_item
def setPixmap(self, pixmap):
self.pixmap_item.setPixmap(pixmap)
def resizeEvent(self, event):
self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
super().resizeEvent(event)
def mousePressEvent(self, event):
sp = self.mapToScene(event.pos())
lp = self.pixmap_item.mapFromScene(sp)
poly = self.polygon_item.polygon()
poly.append(lp)
self.polygon_item.setPolygon(poly)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
view = GraphicsView()
self.setCentralWidget(view)
view.setPixmap(QtGui.QPixmap("img.png"))
self.resize(640, 480)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Update:
If you want to use the OP design, the implementation is trivial.
Option1:
Create a file called graphicsview.py where the GraphicsView logic is implemented:
graphicsview.py
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
self._pixmap_item = QtWidgets.QGraphicsPixmapItem()
scene.addItem(self.pixmap_item)
self._polygon_item = QtWidgets.QGraphicsPolygonItem(self.pixmap_item)
self.polygon_item.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
self.polygon_item.setBrush(QtGui.QBrush(QtCore.Qt.red, QtCore.Qt.VerPattern))
#property
def pixmap_item(self):
return self._pixmap_item
#property
def polygon_item(self):
return self._polygon_item
def setPixmap(self, pixmap):
self.pixmap_item.setPixmap(pixmap)
def resizeEvent(self, event):
self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
super().resizeEvent(event)
def mousePressEvent(self, event):
sp = self.mapToScene(event.pos())
lp = self.pixmap_item.mapFromScene(sp)
poly = self.polygon_item.polygon()
poly.append(lp)
self.polygon_item.setPolygon(poly)
Replace QLabel with QGraphicsView in polygon_ui:
polygon_ui.py
from PyQt5 import QtCore, QtGui, QtWidgets
from graphicsview import GraphicsView
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(621, 641)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = GraphicsView(self.centralwidget)
self.label.setGeometry(QtCore.QRect(10, 10, 600, 600))
self.label.setObjectName("label")
# ...
Restore the main.py
main.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from polygon_ui import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
pixmap = QtGui.QPixmap("img.png")
self.label.setPixmap(pixmap)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Option2:
Another approach is to promote the widget, and in SO there are many examples of that type so I will obviate showing the procedure:
How to insert video in ui file which made at qt designer?
Clear QLineEdit on click event
Create a widget to embed into QMainWindow
where do I write the class for a single promoted QWidget from Qt designer
Option3:
Another simpler alternative is to use QLabel as a container and set the GraphicsView with a layout:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from polygon_ui import Ui_MainWindow
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
self._pixmap_item = QtWidgets.QGraphicsPixmapItem()
scene.addItem(self.pixmap_item)
self._polygon_item = QtWidgets.QGraphicsPolygonItem(self.pixmap_item)
self.polygon_item.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
self.polygon_item.setBrush(QtGui.QBrush(QtCore.Qt.red, QtCore.Qt.VerPattern))
#property
def pixmap_item(self):
return self._pixmap_item
#property
def polygon_item(self):
return self._polygon_item
def setPixmap(self, pixmap):
self.pixmap_item.setPixmap(pixmap)
def resizeEvent(self, event):
self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
super().resizeEvent(event)
def mousePressEvent(self, event):
sp = self.mapToScene(event.pos())
lp = self.pixmap_item.mapFromScene(sp)
poly = self.polygon_item.polygon()
poly.append(lp)
self.polygon_item.setPolygon(poly)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
self.graphicsview = GraphicsView()
lay = QtWidgets.QVBoxLayout(self.label)
lay.addWidget(self.graphicsview)
pixmap = QtGui.QPixmap("img.png")
self.graphicsview.setPixmap(pixmap)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

Connection between from QDialog to QMainWindow - PyQt5

I have created two widgets (QMainWindow as win_one and QDialog as win_two) with qtdesigner and PyQt5.
From win_one, I open win_two, fill-in the lineEdit and press OK to transfer the entry into a label displayed in win_one. Everything works well except two problems:
win_one window is opened as .showMaximized() but after filled-in the label, the dimension of the window changes.
the button from win_one stops to work
front_win_one.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_win_one(object):
def setupUi(self, win_one):
win_one.setObjectName("win_one")
win_one.resize(1147, 234)
self.centralwidget = QtWidgets.QWidget(win_one)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(50, 50, 111, 51))
self.pushButton.setObjectName("pushButton")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(40, 160, 131, 31))
self.label.setObjectName("label")
win_one.setCentralWidget(self.centralwidget)
self.retranslateUi(win_one)
QtCore.QMetaObject.connectSlotsByName(win_one)
def retranslateUi(self, win_one):
_translate = QtCore.QCoreApplication.translate
win_one.setWindowTitle(_translate("win_one", "MainWindow"))
self.pushButton.setText(_translate("win_one", "To qdialog"))
self.label.setText(_translate("win_one", "TextLabel"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
win_one = QtWidgets.QMainWindow()
ui = Ui_win_one()
ui.setupUi(win_one)
win_one.show()
sys.exit(app.exec_())
front_win_two.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_win_two(object):
def setupUi(self, win_two):
win_two.setObjectName("win_two")
win_two.resize(317, 278)
self.pushButton = QtWidgets.QPushButton(win_two)
self.pushButton.setGeometry(QtCore.QRect(40, 120, 121, 23))
self.pushButton.setObjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(win_two)
self.lineEdit.setGeometry(QtCore.QRect(30, 50, 161, 21))
self.lineEdit.setObjectName("lineEdit")
self.retranslateUi(win_two)
QtCore.QMetaObject.connectSlotsByName(win_two)
def retranslateUi(self, win_two):
_translate = QtCore.QCoreApplication.translate
win_two.setWindowTitle(_translate("win_two", "Dialog"))
self.pushButton.setText(_translate("win_two", "OK"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
win_two = QtWidgets.QDialog()
ui = Ui_win_two()
ui.setupUi(win_two)
win_two.show()
sys.exit(app.exec_())
back.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QDialog
from front_win_1 import Ui_win_one
from front_win_2 import Ui_win_two
class win_two(QDialog, Ui_win_two):
def __init__(self, parent=None):
super(win_two, self).__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.vers_main)
def vers_main(self):
entry = self.lineEdit.text()
win_one().label.setText(entry)
class win_one(QMainWindow, Ui_win_one):
def __init__(self, parent=None):
super(win_one, self).__init__(parent)
self.setupUi(dialog)
self.pushButton.clicked.connect(self.open_qdialog)
def open_qdialog(self):
self.dialog_win_2 = win_two()
self.dialog_win_2.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = QMainWindow()
prog = win_one(dialog)
dialog.showMaximized()
sys.exit(app.exec_())
Thank you
Your code has some inconsistencies:
You should not do this dialog = QMainWindow(), since it is enough to create an object of the class win_one, for this you must change self.setupUi(dialog) to self.setupUi(self).
With the statement win_one().label.setText(entry) you are creating a new object, which is unnecessary, besides that you are losing the previous object so when you press the window again, QDialog is not opened, a simple solution is to pass it as parent to win_one to win_two and use the self.parent() function to access it.
All of the above is implemented in the following part:
class win_two(QDialog, Ui_win_two):
def __init__(self, parent=None):
super(win_two, self).__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.vers_main)
def vers_main(self):
entry = self.lineEdit.text()
self.parent().label.setText(entry)
class win_one(QMainWindow, Ui_win_one):
def __init__(self, parent=None):
super(win_one, self).__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.open_qdialog)
def open_qdialog(self):
self.dialog_win_2 = win_two(self)
self.dialog_win_2.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
prog = win_one()
prog.showMaximized()
sys.exit(app.exec_())
Note: I could never reproduce the first bug, only the second one.

Categories