QGraphicsView wrong size at start - python

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_())

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()

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_())

Master PyQt5 GUI with pushbuttons that open additional GUI

Using Python3 and PyQt5, I want to have a GUI that has a button on it that, when pressed, opens another widget which also has buttons and other controls. In the future, the master GUI will have many buttons that will open many additional widgets. I'm looking at having one widget with an embedded matplotlib.pyplot. At the moment, I am struggling to open a second widget.
Main Program
import sys
from PyQt5 import QtWidgets
from gui import Ui_MainWindow as Ui_MainWindow1
from gui2 import Ui_MainWindow as Ui_MainWindow2
class Window(QtWidgets.QMainWindow, Ui_MainWindow1):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.ui_gui = Ui_MainWindow1()
self.ui_gui.setupUi(self)
self.pb.clicked.connect(self.on_pb_clicked)
self.graph = Graph(self)
def on_pb_clicked(self):
print('pb clicked')
self.graph.show()
class Graph(QtWidgets.QMainWindow, Ui_MainWindow2):
def __init__(self, parent=None):
super(Graph, self).__init__(parent)
self.ui_graph = Ui_MainWindow2()
self.ui_graph.setupUi(self)
if __name__ == "__main__":
#import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow1()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
gui = gui2. Both look like the below.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(282, 219)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.pb = QtWidgets.QPushButton(self.centralWidget)
self.pb.setGeometry(QtCore.QRect(100, 60, 75, 23))
self.pb.setObjectName("pb")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 282, 21))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
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.pb.setText(_translate("MainWindow", "pb"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I want to click the button on gui and have the gui2 appear. NB gui will not equal gui2 in the future.
Since Window and Graph inherit from Ui_Window1 and Ui_Window2, respectively, you should call self.setupUi(self) in Window.__init__ and Graph.__init__ instead of creating separate instances of Ui_Window1 and Ui_Window2, i.e.
class Window(QtWidgets.QMainWindow, Ui_MainWindow1):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setupUi(self)
self.pb.clicked.connect(self.on_pb_clicked)
self.graph = Graph(self)
# just to see the two windows side-by-side
self.move(500, 400)
self.graph.move(self.x()+self.width()+20, self.y())
def on_pb_clicked(self):
print('pb clicked')
self.graph.show()
class Graph(QtWidgets.QMainWindow, Ui_MainWindow2):
def __init__(self, parent=None):
super(Graph, self).__init__(parent)
self.setupUi(self)
The main part of the program should then be something like
if __name__ == "__main__":
#import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = Window()
MainWindow.show()
app.exec()
You use QMetaObject::connectSlotsByName() to enable the automatic calling of the on_pb_clicked() slot.
You do not need to use self.pb.clicked.connect(self.on_pb_clicked)
You need #QtCore.pyqtSlot()
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from gui_1 import Ui_MainWindow as Ui_MainWindow1
from gui_2 import Ui_MainWindow as Ui_MainWindow2
class Graph(QtWidgets.QMainWindow, Ui_MainWindow2):
def __init__(self, parent=None):
super(Graph, self).__init__(parent)
self.setupUi(self)
self.setWindowTitle("window Graph")
self.setGeometry(QtCore.QRect(850, 260, 282, 219))
# self.pb.clicked.connect(self.on_pb_clicked) # ---
#QtCore.pyqtSlot() # +++
def on_pb_clicked(self):
print('pb clicked -> Graph')
class Window(QtWidgets.QMainWindow, Ui_MainWindow1):
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowTitle("main Window")
# self.pb.clicked.connect(self.on_pb_clicked) # ---
self.graph = Graph(self)
#QtCore.pyqtSlot() # +++
def on_pb_clicked(self):
print('pb clicked -> "main Window')
self.graph.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.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.

Python (QtDesigner) Opening multiple .py files in MdiArea window with buttons

I used QtDesigner to create all of my windows, the main window uses mdiArea so that other windows fit inside of it when called. My main problem is when I close a window inside the mdiArea it disappears and I can't reopen it, id either like the window to not have a exit button or make a window with buttons that will open the files if its not there.
Output Screenshot
The window that is minimized is ValveSimulator and if I close it it doesn't exist anymore and I can't open it
my main code: CreateWindow makes the window with the buttons and CreateValveSimulator is my main program that I want to open from the button when I close it
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget,QWidget, QMdiSubWindow
import ValveSim
import MainWindow
import Window
class Win1(QMainWindow):
def __init__(self):
QWidget.__init__(self)
self.vtn = MainWindow.Ui_MainWindow()
self.vtn.setupUi(self)
self.subwindow = QMdiSubWindow()
self.CreateValveSimulator()
self.CreateWindow()
def CreateValveSimulator(self):
widget = QMainWindow()
self.VSim_subwindow = ValveSim.Ui_ValveSim()
self.VSim_subwindow.setupUi(widget)
self.subwindow = QMdiSubWindow(self.vtn.mdiArea)
widget.setParent(self.subwindow)
self.subwindow.setWidget(widget)
self.vtn.mdiArea.addSubWindow(self.subwindow)
widget.show()
self.subwindow.show()
self.subwindow.widget().show()
def CreateWindow(self):
widget = QMainWindow()
self.win_subwindow = Window.Ui_MainWindow()
self.win_subwindow.setupUi(widget)
self.subwindow = QMdiSubWindow(self.vtn.mdiArea)
widget.setParent(self.subwindow)
self.subwindow.setWidget(widget)
self.vtn.mdiArea.addSubWindow(self.subwindow)
widget.show()
self.subwindow.show()
self.subwindow.widget().show()
if __name__=='__main__':
app =QApplication(sys.argv)
win = Win1()
win.show()
sys.exit(app.exec_())
I connected the self.pushbutton to a function called openvs which I hope to open the Valve Simulator window when its closed as shown in my main code,however it just crashes when I click the button
Table with buttons code:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QWidget, QMdiSubWindow, QAction
import Untitled
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.WindowModal)
MainWindow.resize(351, 442)
MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(85, 125, 75, 23))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(85, 195, 75, 23))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(200, 125, 75, 23))
self.pushButton_3.setObjectName("pushButton_3")
MainWindow.setCentralWidget(self.centralwidget)
self.pushButton.clicked.connect(self.openvs)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "Open Valve Simulator"))
self.pushButton_2.setText(_translate("MainWindow", "Open Module Program"))
self.pushButton_3.setText(_translate("MainWindow", "Open Metal Sizing"))
def openvs(self):
Untitled.Win1.CreateValveSimulator()
You must create the windows independently, and add them to each QMdiSubWindow. When the widget is displayed in the subwindow this will cause the subwindow to be displayed. To open normally with the button you must use the clicked signal and call the showNormal function.
The complete code is here.
class HomeWindow(QMainWindow, Ui_HomeWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
class ValveSim(QMainWindow, Ui_ValveSim):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
class Win1(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
self.vs = ValveSim()
self.hw = HomeWindow()
self.CreateValveSimulator()
self.CreateWindow()
def CreateValveSimulator(self):
subwindow = QMdiSubWindow()
subwindow.setWidget(self.vs)
self.mdiArea.addSubWindow(subwindow)
subwindow.setFixedSize(500, 500)
# self.subwindow.close()
def CreateWindow(self):
self.hw.pushButton.clicked.connect(self.vs.showNormal)
subwindow = QMdiSubWindow()
subwindow.setWindowFlags(Qt.CustomizeWindowHint | Qt.Tool)
subwindow.setWidget(self.hw)
self.mdiArea.addSubWindow(subwindow)

Categories