I have just worked out how to show an svg image in pyqt5 using QSvgWidget and have tried to transplant it into a blank gui created with the qt designer. The svg image displays but in it's own window instead of in a container or boarder.
I have tried to read through the QSvgWidget docs to see what I am doing wrong but I have a feeling this is a problem with how I am using PyQT5 rather than QSvgWidget.
from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.viewer = QtSvg.QSvgWidget()
self.viewer.load('C:/Windows/Temp/tubesheetsvgpreview.svg')
self.viewer.setGeometry(QtCore.QRect(0,0,600,600))
self.viewer.show()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 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"))
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_())
The results look like this:
whereas I would just like the svg to appear in a boarder within the main window and scaled to the boarder or window size
For a widget to be part of a window it must be a child of the window or child of a child from a window, in the case of QMainWindow it must be from the centralWidget, for this there are 2 methods:
Pass to the window as a parent.
# ...
# pass self.centralwidget as parent
self.viewer = QtSvg.QSvgWidget(self.centralwidget)
self.viewer.load('C:/Windows/Temp/tubesheetsvgpreview.svg')
self.viewer.setGeometry(QtCore.QRect(0,0,600,600))
# ...
Set the widget through a layout.
# ...
self.centralwidget.setObjectName("centralwidget")
self.viewer = QtSvg.QSvgWidget()
self.viewer.load('C:/Windows/Temp/tubesheetsvgpreview.svg')
self.viewer.setGeometry(QtCore.QRect(0,0,600,600))
# set the layout to centralWidget
lay = QtWidgets.QVBoxLayout(self.centralwidget)
# add the viewer to the layout
lay.addWidget(self.viewer)
MainWindow.setCentralWidget(self.centralwidget)
# ...
Update:
If you want to center the widget, it is best to use the second method and establish an alignment:
# ...
lay = QtWidgets.QVBoxLayout(self.centralwidget)
lay.addWidget(self.viewer, alignment=QtCore.Qt.AlignCenter) # <---
# ...
In the case of the first method, move the official widget (and in essence it is what the layout does in the other method) but you would have to do the same every time the widget changes in size.
So the simplest method is to use the layout.
Related
I have two files, "main.py", "debugger.py".
On "debugger.py" I have a "textEdit" where I want to get/show messages.
On "main.py" I import and instantiate the class from "debugger.py" but instead of just sending/showing the messages, it opens the "debugger.py" window UI and shows the messages, i just need to send the message without opening the window, how can I do that?
"debugger.py".
import os, time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QTextCursor
class Debugger_MainWindow(object):
def __init__(self):
super().__init__()
#def print_text(self):
#self.txtEdit_debugger.insertPlainText('hi')
def Debugger_setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.lbl_info = QtWidgets.QLabel(self.centralwidget)
self.lbl_info.setGeometry(QtCore.QRect(90, 450, 451, 61))
self.lbl_info.setObjectName("lbl_info")
self.lbl_tittle = QtWidgets.QLabel(self.centralwidget)
self.lbl_tittle.setGeometry(QtCore.QRect(280, 40, 56, 15))
self.lbl_tittle.setObjectName("lbl_tittle")
self.txtEdit_debugger = QtWidgets.QTextEdit(self.centralwidget)
#self.txtEdit_debugger.setEnabled(False)
self.txtEdit_debugger.setGeometry(QtCore.QRect(70, 80, 481, 361))
self.txtEdit_debugger.setObjectName("txtEdit_debugger")
self.txtEdit_debugger.setReadOnly(True)
##Check box on/off
self.chkb_on_off_debugger = QtWidgets.QCheckBox(self.centralwidget)
self.chkb_on_off_debugger.setGeometry(QtCore.QRect(90, 500, 30, 20))
self.chkb_on_off_debugger.setObjectName("chkb_on_off_debugger")
#self.chkb_on_off_debugger.stateChanged.connect(self.print_text)#Show logger messages
self.chkb_on_off_debugger.setCheckable(True)
self.lbl_on_off_debugger = QtWidgets.QLabel(self.centralwidget)
self.lbl_on_off_debugger.setGeometry(QtCore.QRect(110, 500, 60, 20))
self.lbl_on_off_debugger.setObjectName("lbl_on_off_debugger")
MainWindow.setCentralWidget(self.centralwidget)
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.lbl_info.setText(_translate("MainWindow", "This is read only mode. "))
self.lbl_tittle.setText(_translate("MainWindow", "Debugger"))
self.lbl_on_off_debugger.setText(_translate("MainWindow", "Show messages"))
self.lbl_on_off_debugger.adjustSize()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Debugger_MainWindow()
ui.Debugger_setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
"main.py"
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSlot, QThreadPool, QTimer
from PyQt5.QtGui import QColor, QKeySequence, QIcon, QTextCursor
from Debugger import Debugger_MainWindow
class Ui_MainWindow(object):
def __init__(self):
super().__init__()
###### Methods
#this method opens a new window, i just want to send the message
def print_text(self):
self.ui_debugger = Debugger_MainWindow()
self.ui_debugger.Debugger_setupUi(MainWindow)
self.ui_debugger.txtEdit_debugger.insertPlainText('hi')
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(500, 500)
MainWindow.setStyleSheet(open("styles.qss", "r").read())
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
##Group box
self.gpb_spell_main = QtWidgets.QGroupBox(self.centralwidget)
self.gpb_spell_main.setGeometry(QtCore.QRect(10, 5, 290, 230))
self.gpb_spell_main.setObjectName("gpb_spell_main")
self.gpb_spell_main.setCheckable(True)
self.gpb_spell_main.setChecked(False)
##Button
spell_main_color = QColor(255, 0, 255)
self.btn_spell_main = QtWidgets.QPushButton(self.gpb_spell_main)
self.btn_spell_main.setGeometry(QtCore.QRect(10, 35, 85, 27))
self.btn_spell_main.setObjectName("btn_spell_main")
self.btn_spell_main.clicked.connect(self.print_text)
#self.btn_spell_main.setEnabled(False)
MainWindow.setCentralWidget(self.centralwidget)
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.gpb_spell_main.setTitle(_translate("HeallingWindow", "Spell Main"))
self.btn_spell_main.setText(_translate("MainWindow", "Click Here"))
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_())
Note: I couldn't fix my issue reading similar questions. PyQt5 - Show QDialog from a different class
I don't know if I understand problem but you may have to create new QtWidgets.QMainWindow() to create separated Debug Window. If you use existing MainWindow then it replaces widgets in existing window.
You may also set None to Debug Window in __init__ and later check if Debug Window is not None - to create only one window.
class Ui_MainWindow(object):
def __init__(self):
super().__init__()
self.DebugWindow = None
def print_text(self):
if self.DebugWindow is None:
self.DebugWindow = QtWidgets.QMainWindow()
self.ui_debugger = Debugger_MainWindow()
self.ui_debugger.Debugger_setupUi(self.DebugWindow)
self.DebugWindow.show()
self.ui_debugger.txtEdit_debugger.insertPlainText('hi\n')
Other problem cam be when you close Debug Window because it will not opne it again. It may need to change code in Debug Window and assign function which will hide it instead of destroing it.
I want to display an image using QGraphicsView in a window. I have a basic QGraphicsView and a button based test.ui file generated from QtDesigner tool. Corresponding test.py file:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.graphicsView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.graphicsView.setObjectName("graphicsView")
self.verticalLayout.addWidget(self.graphicsView)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 640, 26))
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.pushButton.setText(_translate("MainWindow", "PushButton"))
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 made use of QGraphicsScene to display an image inside this QGraphicsView. My current working solution is to mess up the above .py file as follows:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.scene = QtWidgets.QGraphicsScene(self.centralwidget) #added
self.graphicsView = QtWidgets.QGraphicsView(self.scene) #edited
self.graphicsView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.graphicsView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.graphicsView.setObjectName("graphicsView")
self.verticalLayout.addWidget(self.graphicsView)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 640, 26))
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.pushButton.setText(_translate("MainWindow", "PushButton"))
self.pushButton.clicked.connect(self.display)
def display(self):
import imageio, numpy
self.scene.clear()
input_image = imageio.imread('image.jpg').copy()
height, width, channels = input_image.shape
bytesPerLine = channels * width
qimg = QtGui.QImage(input_image, width, height, bytesPerLine, QtGui.QImage.Format_RGB888)
self.pixmap = QtGui.QPixmap.fromImage(qimg)
self.scene.addPixmap(self.pixmap) #add pixmap to scene
self.graphicsView.scale(0.5,0.5)
self.scene.update()
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_())
However, this solution is not systematic. I want to do the same without editing the original test.ui generated test.py file.
So, I tried following code which to me appears like a systematic translation of the previous working code. However, it fails to produce any display on button click:
from PyQt5 import QtCore, QtGui, QtWidgets
from test import Ui_MainWindow
class myWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
self.scene = QtWidgets.QGraphicsScene(self.centralwidget) #append scene method
self.graphicsView = QtWidgets.QGraphicsView(self.scene) #graphicsView re-assigned with scene
self.pushButton.clicked.connect(self.display)
def display(self):
import imageio, numpy
self.scene.clear()
input_image = imageio.imread('image.jpg').copy()
height, width, channels = input_image.shape
bytesPerLine = channels * width
qimg = QtGui.QImage(input_image, width, height, bytesPerLine, QtGui.QImage.Format_RGB888)
self.pixmap = QtGui.QPixmap.fromImage(qimg)
self.scene.addPixmap(self.pixmap) #add pixmap to scene
self.graphicsView.scale(0.5,0.5)
self.scene.update()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = myWindow()
w.show()
sys.exit(app.exec_())
I am likely messing up something due to my limited understanding of class inheritance, QGraphicsView, and QGraphicsScene. Any pointers to my mistakes would be very helpful.
Note: I am using a myWindow class to integrate some key press functionality in future. I think the issue is more to do with how to selectively append/redefine few lines inside a parent class function. Is this even possible without re-writing the whole setupUi method? Or, is there another smarter way to perform the same task?
You have to set the scene to the existing QGraphicsView instead of creating a new QGraphicsView:
class myWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.scene = QtWidgets.QGraphicsScene(self.centralwidget)
self.graphicsView.setScene(self.scene)
self.pushButton.clicked.connect(self.display)
def display(self):
# ...
This is a sample code with just a push button and a textedit, i need to write line x line using a loop in a textedit when button is clicked.
The problem is that i need to implement threads because without them the program crashes or it doesn't write line x line, but all together when the loop ends;
and i need to implement in my application a textedit that shows info while the program loads "something".
So my question is, how to rewrite this code using threads to write in textedit when button is clicked?
The method i should run when the button is clicked is "write"
it should work like a print inside a for loop , it would print not all at once
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(150, 220, 321, 71))
self.textEdit.setObjectName("textEdit")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(240, 100, 75, 23))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 640, 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.pushButton.setText(_translate("MainWindow", "PushButton"))
self.pushButton.clicked.connect(self.write)
def write(self):
string=""
for i in range(1000):
string="\n"+str(i)
self.textEdit.insertPlainText(string)
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
First of all it is recommended not to modify the class generated by Qt Designer so you must regenerate the file and assume that it is called mainwindow.py: pyuic5 your_file.ui -o mainwindow.py -x.
Considering the above, the logic is to generate the information in another thread and send it to the GUI to modify it:
main.py
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
from mainwindow import Ui_MainWindow
class WriterWorker(QtCore.QObject):
textChanged = QtCore.pyqtSignal(str)
def start(self):
threading.Thread(target=self._execute, daemon=True).start()
def _execute(self):
string = ""
for i in range(1000):
string = "\n"+str(i)
self.textChanged.emit(string)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.writer_worker = WriterWorker()
self.writer_worker.textChanged.connect(self.on_text_changed)
self.pushButton.clicked.connect(self.writer_worker.start)
#QtCore.pyqtSlot(str)
def on_text_changed(self, text):
self.textEdit.insertPlainText(text)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Code has been edited per requests
I have a program where one menu will link to another menu and then you can perform functions from there.
When I add a hide MainWindow function to the second window, so it goes into the background while you follow the prompts, it will crash, IF you run the whole script.
Ex: Run the main script, click on investigations and then click on any of the menu items.
If I run the script by itself, without going through the main menu, it will run with no issues.
The issue lies within the Mainwindow.hide(), because I can comment this out in the second menu- InvMenu, and I can run the program from the MainMenu and follow the prompts with no issues.
I'm not sure how to fix this. I've ran through quite a few things online and none seem to work.
Here's the code-
Test.py
from PyQt5 import QtCore, QtGui, QtWidgets
from Test2 import *
class Ui_MainWindow(object):
def ipDombtn(self):
self.window=QtWidgets.QMainWindow()
self.ui=Ui_MainWindow1()
self.ui.setup(self.window)
self.window.show()
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 440)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.pushButton.clicked.connect(self.ipDombtn)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 412, 31))
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.pushButton.setText(_translate("MainWindow", "Investigation"))
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_())
Here is the second menu's code. It's set to call specific functions based on what they select. If I comment out the MainWindow.hide() I can run the MainMenu, select investigations and then click on one of the options and they work. If I run this code without running the main menu, and nothing commented out, it works just fine.
Is it an issue with two menus, even though they are renamed?
Test2.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow1(object):
def exIpDomInv_clicked(self):
MainWindow1.hide()
print("You clicked a button...")
MainWindow1.show()
def setup(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 440)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.exIpDomInv = QtWidgets.QPushButton(self.centralwidget)
self.exIpDomInv.setObjectName("exIpDomInv")
self.verticalLayout.addWidget(self.exIpDomInv)
MainWindow.setCentralWidget(self.centralwidget)
self.Menu = QtWidgets.QMenuBar(MainWindow)
self.Menu.setGeometry(QtCore.QRect(0, 0, 412, 31))
self.Menu.setObjectName("Menu")
MainWindow.setMenuBar(self.Menu)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.exIpDomInv.clicked.connect(self.exIpDomInv_clicked)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Investigation"))
MainWindow.setAccessibleName(_translate("MainWindow", "InvestigationMenu"))
self.exIpDomInv.setText(_translate("MainWindow", "External IP/ Domain Investigation"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow1 = QtWidgets.QMainWindow()
ui2 = Ui_MainWindow1()
ui2.setup(MainWindow1)
MainWindow1.show()
sys.exit(app.exec_())
Note that the program is broken does not help, you are probably using some IDE, many times the IDEs do not handle these types of errors correctly so I recommend you execute it in a CMD, if you do so you will get the following message:
Traceback (most recent call last):
File "/path/of/Test2.py", line 6, in exIpDomInv_clicked
MainWindow1.hide()
NameError: name 'MainWindow1' is not defined
Aborted (core dumped)
Well, more or less, it gives us an idea of the problem, it tells us that MainWindow1 is not defined, and this leads me to think that you are not clear about some concepts:
The expression if __name__ == "__main__": can have all the files but only the first one is observed so that the if __name__ == "__main__": of Test2.py will not run and therefore the MainWindow1 that you assume exists will not exist.
Classes are abstractions ie they describe a behavior of their objects, besides they only access the members of their scope, that is, it is like a black box, if the object is not defined within the class it can not be accessed, so if you want to access the Ui_MainWindow of Test.py you can not do it directly as it is, there are several methods to achieve it but it is based on the above.
On the other hand the classes that generate Qt Designer are recommended not to edit them because if you modify something in the .ui and recompile it will erase all the changes, besides they are not widgets so you have limitations such as overwriting of the methods. For more information read this.
Considering the above, I am going to divide it into several files:
ui_mainwindow1.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow1(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 440)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.exIpDomInv = QtWidgets.QPushButton(self.centralwidget)
self.exIpDomInv.setObjectName("exIpDomInv")
self.verticalLayout.addWidget(self.exIpDomInv)
MainWindow.setCentralWidget(self.centralwidget)
self.Menu = QtWidgets.QMenuBar(MainWindow)
self.Menu.setGeometry(QtCore.QRect(0, 0, 412, 31))
self.Menu.setObjectName("Menu")
MainWindow.setMenuBar(self.Menu)
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", "Investigation"))
MainWindow.setAccessibleName(_translate("MainWindow", "InvestigationMenu"))
self.exIpDomInv.setText(_translate("MainWindow", "External IP/ Domain Investigation"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow1 = QtWidgets.QMainWindow()
ui2 = Ui_MainWindow1()
ui2.setup(MainWindow1)
MainWindow1.show()
sys.exit(app.exec_())
ui_mainwindow.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 440)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 412, 31))
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.pushButton.setText(_translate("MainWindow", "Investigation"))
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_())
main.py
from PyQt5 import QtWidgets
from ui_mainwindow1 import Ui_MainWindow1
from ui_mainwindow import Ui_MainWindow
class MainWindow1(QtWidgets.QMainWindow, Ui_MainWindow1):
def __init__(self, parent=None):
super(MainWindow1, self).__init__(parent)
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.other_window = MainWindow1()
self.pushButton.clicked.connect(self.other_window.show)
self.other_window.exIpDomInv.clicked.connect(self.hide)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
As you see the object other_window is in the same scope of the class so it can be accessed and therefore all the elements are defined. Also each file has its if __name__ == "__main__":, these serve to test the operation of each class, but only the one in the main.py will be executed, the others will be ignored.
I have tried
self.mdiArea.activeSubWindow().objectName
self.mdiArea.activeSubWindow().objectName()
But neither of them gave me the object name I set:
self.subwindow.setObjectName("subwindow_1")
Any advice? Thanks a lot. Full testing code is attached:
# Created by: PyQt5 UI code generator 5.6
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(687, 438)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.mdiArea = QtWidgets.QMdiArea(self.centralwidget)
self.mdiArea.setGeometry(QtCore.QRect(140, 10, 531, 381))
self.mdiArea.setObjectName("mdiArea")
self.subwindow = QtWidgets.QWidget()
self.subwindow.setObjectName("subwindow_test_the_object_name")
self.Add = QtWidgets.QPushButton(self.centralwidget)
self.Add.setGeometry(QtCore.QRect(10, 30, 121, 23))
self.Add.setObjectName("Add")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 687, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.Add.clicked.connect(self.Add_window) # connect the button to Add_window function
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def Add_window(self):
self.mdiArea.addSubWindow(self.subwindow)
print("there is a subwindow activated")
self.mdiArea.activeSubWindow()
self.subwindow.show()
Act_window=self.mdiArea.activeSubWindow()
print("this is subwindow 1 "+str(Act_window.objectName()))
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.subwindow.setWindowTitle(_translate("MainWindow", "Subwindow"))
self.Add.setText(_translate("MainWindow", "Add Window"))
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_())
This is a very simple sample with objectName() does not work with subwindow but it works with button and the parent MDIarea, my goal is to get the active subwindow object name such as subwindow_test_the_object_name in this case, if I have multiple subwindows with different object name, I can grab this object name as a signal. Thanks.
With the following instruction:
self.subwindow = QtWidgets.QWidget()
self.subwindow.setObjectName("subwindow_test_the_object_name")
you are giving a name to the widget that is going to be inside the QMdiSubWindow, not the QMdiSubWindow, so if you want to retrieve the name of that element you must use the widget() method of QMdiSubWindow:
def Add_window(self):
self.mdiArea.addSubWindow(self.subwindow)
print("there is a subwindow activated")
self.mdiArea.activeSubWindow()
self.subwindow.show()
Act_window =self.mdiArea.activeSubWindow()
print("this is subwindow 1 "+str(Act_window.widget().objectName()))
Output:
there is a subwindow activated
this is subwindow 1 subwindow_test_the_object_name