I am writing a program and I want for external function to access attribute of the main window. It must be an external function, because it is provided by import method. I have created a really small MWE to give an idea of the problem. Here function func is supposed to print value of MainWindow's vari.
class importedclass():
def func(self):
print(win.vari)
x=importedclass()
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.vari = 1
x.func()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Just to make it clear: importedclass class is my fix-up class, I am not allowed to change anything in MainWindow class!
Because each one needs an instance of the other, one of them needs to pass itself to the other. Check if this example solution fully addresses your problem.
# file 1
class External():
def func(self, win):
print(win.vari)
# file 2
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.vari = 1
import External
x = External()
x.func(self)
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
Related
I'm building a desktop app with python and have some issues getting a class variable I set up.
My program is built like this:
CharCreator.py
class MainWindow(QtWidgets.QMainWindow):
charName = ""
def __init__(self):
super().__init__()
def editCharClick(self):
from CharEdit import editUi
MainWindow.charName = self.getSelected()
print(MainWindow.charName)
if(MainWindow.charName is not None):
self.editWin = editUi()
self.editWin.show()
else:
print("charName is none")
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
So I've got my main window class, with a charName class variable.
Then I have the typical methods(init, main etc) and have an editCharClick method that takes the selected row of my table, gets the name of my desired cell and assigns its string content to my class variable.
This part works well in my CharCreator.py file.
The problem comes in my second file. As seen in my editCharClick method, it opens a second window (CharEdit.py file). That's where I need to get the MainWindow.charName class variable.
CharEdit.py
class editUi(QtWidgets.QMainWindow):
def __init__(self):
super(editUi, self).__init__()
uic.loadUi("./ui/new.ui", self)
from CharCreator import MainWindow
print(MainWindow.charName)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
newwindow = editUi()
sys.exit(app.exec_())
I've simplified this file just to get my class variable right, yet can't seem to make it happen.
Any help would be appreciated, thanks.
I tried changing my code to work with event/signals but didn't quite like it.
So I just went the easy way and changed the editUi class constructor so it would accept another argument.
Then, when creating the editUi object in MainWindow.editCharClick(), you can pass the variable in the editUi object as an argument.
CharCreator.py
class MainWindow(QtWidgets.QMainWindow):
charName = ""
def __init__(self):
super().__init__()
def editCharClick(self):
from CharEdit import editUi
MainWindow.charName = self.getSelected()
print(MainWindow.charName)
if(MainWindow.charName is not None):
self.editWin = editUi(MainWindow.charName)
self.editWin.show()
else:
print("charName is none")
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
CharEdit.py
class editUi(QtWidgets.QMainWindow):
def __init__(self, ch):
super(editUi, self).__init__()
uic.loadUi("./ui/new.ui", self)
from CharCreator import MainWindow
print(ch)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
newwindow = editUi()
sys.exit(app.exec_())
I know there are tons of similar questions, but: for this case I haven't found the correct hint.
Overview
I'm writing a GUI (PyQt5). There is a main-class Ui_MainWindow() and a class Algorithm() where some calculations are made.
Ui_MainWindow() is called first and instances then Algorithm().
My idea: in Ui_MainWindow() I call a method which is defined in Algorithm() called def update(self). Now, in def update(self) I want to call a method def move(self) which is again in the first class Ui_MainWindow().
My Problem: to call a method by another class, I need to instance it first, but I can not instance a class twice (at the beginning and in the second class), because that throws endless errors.
Illustrative example:
class Algorithm():
def __init__(self, job_list):
self.job_list = job_list
def update(self):
main = Ui_MainWindow() # this is the problem, I can not do this twice
main.move()
class Ui_MainWindow():
def __init__(self, *args, **kwargs):
super(Ui_MainWindow, self).__init__(*args, **kwargs)
self.setupUi()
def setupUi(self):
""" random code """
def move(self):
""" random code """
if __name__ == "__main__":
main = Ui_MainWindow() # And I need it here.
main.show()
Please tell me, if my explanation is not clear.
I appreciate your help.
I think the fact that your main window doesn't inherit from QMainWindow is going to cause you problems, but disregarding that for now, here's how I'd suggest nesting your objects:
# define Ui_MainWindow first
class Algorithm():
def __init__(self, job_list):
self.job_list = job_list
self.main_window = Ui_MainWIndow()
def show(self):
self.main_window.show()
def update(self):
self.main_window.move()
if __name__ == "__main__":
# generate job_list somehow?
algo = Algorithm(job_list)
algo.show()
You could just add the UI_MainWindow object as an argument of your update function, like this :
def update(self, ui_Window):
main = ui_Window
main.move()
Then, to call it from your UI_MainWindow class, you do :
algorithm = Algorithm(job_list)
algorithm.update(self)
How can I call and run a function with given number of inputs using mouseDoubleClickEvent of a GraphicsView which is in a QMainWindow?
My schematic code:
class MainWindow(QMainWindow):
...
def __setUI(self, appTitle="[default title]"):
...
self.graphicsView = GraphicsView(self)
self.graphicsView.mouseDoubleClickEvent = self.MyFunc(self.in_1, self.in_2)
def MyFunc(self, event, input_1, input_2):
...
I used this code, but is doesn't work. please help me to know how I can call
and run MyFunc using mouseDoubleClickEvent of graphicsView which is in MainWindow.
Many Thanks
One solution is to pass a lambda, something like:
self.graphicsView.mouseDoubleClickEvent = lambda event : self.MyFunc(self.in_1, self.in_2)
It works but it generates problems since mouseDoubleClickEvent has implementation that with the previous code is deleted. In this case the best solution is to use an eventFilter but to viewport since it receives the mouse event.
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.graphicsView = QtWidgets.QGraphicsView()
self.setCentralWidget(self.graphicsView)
self.graphicsView.viewport().installEventFilter(self)
self.in_1 = 10
self.in_2 = 20
def eventFilter(self, obj, event):
if obj is self.graphicsView.viewport():
if event.type() == QtCore.QEvent.MouseButtonDblClick:
self.func(event)
return super(MainWindow, self).eventFilter(obj, event)
def func(self, event):
print(event.pos(), self.in_1, self.in_2)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
This is my first time to ask question, if there are something I get wrong, please tell me, I will be appreciate.
I am using QWebEngineUrlSchemeHandler for a custom url, and I want to use QFile to open a javascript file for testing.
First, if I just use
QFile("ken.js")
The window could open the javascript, but if I use my custom QFile,
I have no idea how to process the data after I read from QIODevice.read().
I want to know what I need to do to make the window could open the javascript after I read the data from QIODevice.read().
Please give me some suggests, thank.
Here is my full code.
class TestQFile(QtCore.QFile):
def __init__(self, fileName):
super().__init__()
self.setFileName(fileName)
self.open(self.ReadOnly)
self.data = b''
while True:
receivedData = self.read(10)
self.data += receivedData
if receivedData == b'':
break
class TestHandler(QWebEngineUrlSchemeHandler):
def requestStarted(self, request):
self._dev = TestQFile("ken.js")
request.reply(b'text/javascript', self._dev)
class TestWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._view = QWebEngineView(self)
self._handler = TestHandler() # Must keep ref
self._view.page().profile().installUrlSchemeHandler(b'myuri', self._handler)
self._view.setHtml('<html><head><title>Test</title></head><body><div id="d1"></div><script src="myuri://test/ken.js"></script></body></html>')
self.setCentralWidget(self._view)
self.show()
self.raise_()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
win = TestWindow()
app.exec_()
Actually if the class inherits from QFile you do not have to do anything since it already has implemented the methods that QWebEngineUrlRequestJob requires since it will use the methods that every class that inherits from QIODevice must implement as readData(), writeData(), atEnd(), etc.
from PyQt5 import QtCore, QtWidgets, QtWebEngineCore,QtWebEngineWidgets
class TestQFile(QtCore.QFile):
def __init__(self, fileName):
super().__init__()
self.setFileName(fileName)
class TestHandler(QtWebEngineCore.QWebEngineUrlSchemeHandler):
def requestStarted(self, request):
self.file = TestQFile("ken.js")
request.reply(b'text/javascript', self.file)
class TestWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._view = QtWebEngineWidgets.QWebEngineView(self)
self._handler = TestHandler() # Must keep ref
self._view.page().profile().installUrlSchemeHandler(b'myuri', self._handler)
self._view.setHtml('<html><head><title>Test</title></head><body><div id="d1"></div><script src="myuri://test/ken.js"></script></body></html>')
self.setCentralWidget(self._view)
self.show()
self.raise_()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
win = TestWindow()
sys.exit(app.exec_())
this example
helped me a lot in understanding of how does the events work.
But I have another problem. After an event when I want to call a function of a main class it seems like it was starting from Filter class and, unfortunately I'm not able to fetch the content from Designer-made file.
class Filter(QtCore.QObject):
def eventFilter(self, widget, event):
if event.type() == QtCore.QEvent.FocusOut:
print 'focus out'
print widget.objectName()
if widget.objectName() == 'edit_notes':
StartQT4().object_edit_notes('edit_notes')
return False
else:
return False
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self._filter = Filter()
self.ui.edit_notes.installEventFilter(self._filter)
def object_edit_notes(self, w):
self.__init__()
something = self.ui.edit_notes.toPlainText()
something = unicode(something).encode('utf-8')
print something
return False
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())
Attribute .something prints nothing. I tried to call identical function with the signal method button clicked() and it works fine.
Can you help me with this?
You don't need a separate class for the event-filter. Any object which inherits QObject or QWidget will do, which includes QMainWindow.
So move the event-filter into your StartQT4 class, like this:
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# filter the events through self
self.ui.edit_notes.installEventFilter(self)
def object_edit_notes(self, w):
# this will convert a QString to a python unicode object
something = unicode(self.ui.edit_notes.toPlainText())
print something
def eventFilter(self, widget, event):
if (event.type() == QtCore.QEvent.FocusOut and
widget is self.ui.edit_notes):
print 'focus out'
self.object_edit_notes('edit_notes')
return False
return QMainWindow.eventFilter(self, widget, event)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())