I have a Tkinter App and currently I am trying to split the code from each tab to be on each tab. I can pass the string as a parameter into the Tab but is it possible to access the parent variables from the child ttk.Frame ? The actual code has more things.
class Tab(ttk.Frame):
def __init__(self, master):
super().__init__(master)
def PrintThings(self):
Print(self._A) ##How can I access here self._A to print Hello World
class App():
def __init__(self):
self._A = "Hello World"
self._root = Tk()
self._root.geometry("800x1200")
self._TabContainer = ttk.Notebook(self._root)
self._Tab = Tab(self._TabContainer)
def main(self):
self._Tab.pack()
App.main()
The easiest solution is to pass the instance of App to each tab. With that, the tab has access to anything defined in App.
It looks something like this:
class App():
...
self._Tab = Tab(self._TabContainer, app=self)
...
...
class Tab(ttk.Frame):
def __init__(self, master, app):
self.app = app
...
def PrintThings(self):
print(self.app._A)
Related
class View:
def __init__(self, parent):
self.container = parent
self.setup()
def setup(self):
self.create_audio_frame()
def create_audio_frame(self):
self.upload_button = Button(self.leftFrame, text='Upload Audio File', command=lambda: self.UploadAction() )
def setup_audio_frame(self):
self.upload_button.pack(pady=10)
def UploadAction(self):
global path
audios = filedialog.askopenfilenames()
for audio in audios:
path = os.path.split(audio)
audio = path[1]
self.audio_box.insert(END, audio)
path = f'{path[0]}/'
I dont know where to move this upload action. i mean to controller or model. i tried to move to controller, the file dialog box is opening without clicking on the button.
Start by creating a controller class. It needs to know about the other classes. A convenient way to do that is to have it create the other classes. You can then pass the controller to each class so that they can call functions on the controller.
Here's one way to do it:
class Controller(...):
def __init__(self):
...
self.view = View(controller=self)
self.model = Model(controller=self)
...
def uploadAction(self, audios):
for audio in audios:
path = os.path.split(audio)
audio = path[1]
self.view.add_audio(audio)
With that, we can create a view that can call uploadAction on the controller, and then the controller can call the view to update the display:
class View(...):
def __init__(self, controller):
self.controller = controller
...
def create_audio_frame(self):
...
self.upload_button = Button(..., command=self.uploadAction)
...
def uploadAction(self):
audios = filedialog.askopenfilenames()
self.controller.uploadAction(audios)
def add_audio(self, audio):
self.audio_box.insert(END, audio)
In my plugin there is a main dialog, showing list data, and a button that opens another dialog to edit the data in. When you finish the editing the data is saved to a file to be accessed later but a refresh needs to be triggered in the main dialog.
Main Dialog has a refresh function but how can I trigger it from the another "subDialog"?
Main Class
class MainDialog(QDialog):
def __init__(self, iface, parent=None, flags=Qt.WindowFlags()):
QDialog.__init__(self, parent, flags)
uic.loadUi(UI_PATH, self)
self.AnotherClass_instance = AnotherClass(self.iface)
#code to open another dialog when edit is pressed
self.refreshDatabaseData()
def opne_the_other_dialog(self):
self.AnotherClass_instance.execDialog()
def refreshDatabaseData(self):
#code to read txt file and change list view in UI
class MainClass(object):
def __init__(self, iface):
self.act.triggered.connect(self.execDialog)
def initGui(self, menu=None):
if menu is not None:
menu.addAction(self.act)
else:
self.iface.addToolBarIcon(self.act)
def execDialog(self):
self.dialog = MainDialog(self.iface, self.iface.mainWindow())
self.dialog.show()
def quitDialog(self):
self.dialog = None
self.act.setEnabled(True)
self.cancel = False
def execTool(self):
#Do something related to plugin
self.quitDialog()
The other class:
class AnotherClassDialog(QDialog):
def __init__(self, iface, parent=None, flags=Qt.WindowFlags()):
QDialog.__init__(self, parent, flags)
uic.loadUi(UI_PATH, self)
self.iface = iface
class AnotherClass(object):
def __init__(self, iface):
self.iface = iface
self.dialog = None
self.cancel = False
self.act.triggered.connect(self.execDialog)
#connect here the buttons to functions, e.g. "OK"-button to execTool
def execDialog(self):
self.dialog = AnotherClassDialog(self.iface, self.iface.mainWindow())
self.dialog.show()
def scheduleAbort(self):
self.cancel = True
def refreshMainPlugin(self):
#need to execute this correctly
self.refreshDatabaseData()
Edit:
I tried passing the list view in self.AnotherClass_instance.execDialog(here), It works but then I can't pass it from AnotherClass to AnotherClassDialog (it changes from Class Object to QMainWindow).
I have developed a QGIS plugin using Pyqt. I now have a need within this plugin to have a QDialog popup have its fields populated with data from our database.
My problem is how to pass a variable (in this case it might be a table and row reference) into a class and have it used by the static method.
If I print a passed in variable from within the class it will return the variable in addition to None?? If I take the same variable and try and populate a qplaintextedit it won't work because its complaining of being type 'None'.
Here is some test code I'm trying out just to get the concept down...
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import pdb
class mydi(QDialog):
def __init__(self, pass_var, parent=None):
super(mydi, self).__init__(parent)
layout = QVBoxLayout(self)
self.pass_var = pass_var
print pass_var
self.txt_comments = QPlainTextEdit(self)
self.txt_comments.appendPlainText(pass_var)
layout.addWidget(self.txt_comments)
self.buttons = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
Qt.Horizontal, self)
layout.addWidget(self.buttons)
self.buttons.accepted.connect(self.accept)
self.buttons.rejected.connect(self.reject)
def something(self):
return self.somevar
def comments(self):
return self.txt_comments.toPlainText()
#staticmethod
def getData(parent=None):
dialog = mydi(None)
dialog.exec_()
return (dialog.comments())
def main():
app = QApplication([])
pass_in_var = "test"
dia = mydi(pass_in_var)
data = dia.getData()
print data
My PyQt application starts with Login screen. If password OK, a module-screen (with icons) appears. When user click some button, a QMainWindow will appears. But I can't do this because of qmainwindow object has no attribute '_exec' error. This is my code:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Main(QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
...
...
class Login(QDialog):
def __init__(self, parent=None):
super(Login, self).__init__(parent)
...
...
uyg=QApplication(sys.argv)
class icons(QDialog):
def __init__(self, parent=None):
super(icons, self).__init__(parent)
...
self.buton = QPushButton()
self.buton.pressed.connect(self.open)
...
def open(self):
dialogmain = Main()
dialogmain._exec() #or dialogmain.show() ???
self.accept()
self.close()
uyg.exec_()
if Login().exec_() == QDialog.Accepted:
dialog = icons()
dialog.exec_()
else:
uyg.quit()
What am I doing wrong? Thank you.
Lately i have done the similar work:I have a loging window and a main window ,and I used something like a FSM to switch between the loging and main window.
Let's say we have 3 state:loging,main,quit.
STATE_LOGING = 0
STATE_MAIN = 1
STATE_QUIT = 2
STATE_DESTROY = 3 #this is a flag
class CState():
sigSwitchState = pyqtSignal(int)
def __init__(self):
super(CState,self).__init__()
def start(self):
pass
def sendQuit(self,nextstate):
self.sigSwitch.emit(nextstate)
class CLoginState(CState):
def __init__(self):
super(CLoginState,self).__init__()
def start(self):
w = Loging()
w.show()
def whenPasswdOk(self):
self.sendQuit(STATE_MAIN)
class CMainState(CState):
def __init__(self):
super(CMainState,self).__init__()
def start(self):
w = MainWindow()
w.show()
def whenMainWindowQuit(self):
self.sendQuit(STATE_QUIT)
class CQuitState(CState):
def __init__(self):
super(CQuitState,self).__init__()
def start(self):
#do some clean stuff...
pass
def whenCleanDone(self):
self.sendQuit(STATE_DESTROY)
class CMainApp():
def __init__(self):
self.app = QApplication(sys.argv)
def __CreateState(state):
if state == STATE_LOGING:
s = CLoginState()
if state == STATE_MAIN:
s = CMainState()
#... same as other state
s.sigSwitchState.connect(self.procNextState)
def procNextState(self,state):
if state == STATE_DESTROY:
QApplication().exit()
s = self.__CreateState(state)
s.start()
def run(self):
self.procNextState(STATE_LOGING)
sys.exit(self.app.exec_())
if __name__ == "__main__":
app = CMainApp()
app.run()
Apart from the application object and QDrag, please pretend that exec() doesn't exist. It is an utterly confusing method that essentially never has to be used. Especially not by anyone new to Qt.
If you want to display any widget, simply show() it. If you want to be notified when a dialog was accepted, connect some code to its accepted() signal. That's all.
I have the following outline of a Python program (using PyQt4):
class Polygon( QtGui.QGraphicsItem ):
def __init__(self):
super(Polygon, self).__init__()
def addpoint( self, point ):
if last_point:
# trying to add auto-save here
class MainWidget(QtGui.QWidget):
openFileName = ""
list_of_polygons = []
def __init__(self):
super(MainWidget, self).__init__()
def openFile( self ):
call dialog
self.openFileName = ...
def saveFile( self ):
# needs to access a couple something with self.variables, like self.openFileName
def main():
app = QtGui.QApplication(sys.argv)
ex = MainWidget()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Functionality is an image viewer where I'm creating polygons to tag object. I'd like to call an auto-save once a polygon has been created.
So for saving a polygon I need to call it from the saveFile function MainWidget class. My problem is that the saving functionality is implemented in the MainWidget class, and I don't know how to access them from inside the Polygon class.
What would be the best idea to do this? Should I make saveFile global? If yes, then how do I access the self. variables of the MainWidget?
You probably need to pass the widget object to the Polygon when you create it so that it knows what its "parent" widget object is:
class Polygon( QtGui.QGraphicsItem ):
def __init__(self, parent):
self.parent = parent
# ...
(and then foo = Polygon(your_widget) when you create it).
Then you can just call self.parent.saveFile(...) or whatnot.